Домен: система управления арендой автомобилей. API обслуживает публичный каталог автомобилей, регистрацию и авторизацию пользователей, а также операции аренды.
Hot paths:
GET /cars/available- часто вызывается клиентским приложением при открытии каталога.GET /cars/search?class=...- частый фильтр каталога по классу автомобиля.POST /auth/login- публичный endpoint, может получать много повторных запросов и brute-force попыток.POST /rentalsиPOST /rentals/{rentalId}/complete- менее частые, но меняют доступность автомобилей.
Медленные операции:
- чтение списков автомобилей из MongoDB/PostgreSQL;
- поиск пользователей и автомобилей по индексируемым полям;
- создание аренды, где выполняются проверки пользователя, автомобиля, водительского удостоверения, оплаты и транзакционное обновление статусов;
- внешние интеграции в production-версии: проверка прав и preauthorization платежа.
Целевые требования:
- p95 latency для кешируемых read endpoints: до 50 мс при cache hit, до 200 мс при cache miss;
- p95 latency для login: до 200 мс без перегрузки хранилища;
- пропускная способность каталога: не менее 100 RPS на один учебный instance;
- отказоустойчивое поведение при перегрузке login endpoint: возврат
429 Too Many Requests.
Используется in-memory Cache-Aside TTL cache. Это соответствует учебному single-instance запуску приложения и не требует Redis в docker-compose.yml. Production-ограничение: при горизонтальном масштабировании нужен общий кеш, например Redis, и централизованная инвалидация.
Кешируемые данные:
| Endpoint | Данные | Стратегия | TTL | Инвалидация |
|---|---|---|---|---|
GET /cars/available |
список доступных автомобилей | Cache-Aside | 30 секунд | POST /cars, POST /rentals, POST /rentals/{id}/complete |
GET /cars/search?class=... |
список автомобилей по классу | Cache-Aside | 60 секунд | POST /cars, POST /rentals, POST /rentals/{id}/complete |
Почему не кешируются пользовательские аренды и профили:
- данные зависят от авторизации и прав доступа;
- риск вернуть чужие данные выше выигрыша от кеширования;
- активные аренды меняются при создании и завершении аренды.
Инвалидация реализована по префиксу cars:. После успешной мутации парка или аренды удаляются все fleet cache entries, чтобы следующие чтения получили актуальное состояние из БД.
Эффективность кеша измеряется через hit rate:
cache_hit_rate = cache_hits / (cache_hits + cache_misses)
Для текущей реализации hit/miss виден в HTTP-заголовке X-Cache: HIT|MISS. В production метрики нужно экспортировать в Prometheus: cache_hits_total, cache_misses_total, cache_evictions_total, cache_entry_count.
Rate limiting применяется к POST /auth/login, так как endpoint публичный, делает чтение пользователя и проверку пароля, а также является целью brute-force атак.
| Endpoint | Алгоритм | Ключ | Лимит | Ответ при превышении |
|---|---|---|---|---|
POST /auth/login |
Fixed Window Counter | IP клиента | 5 запросов / 60 секунд | 429 Too Many Requests |
Fixed Window выбран из-за простоты реализации и достаточности для учебного задания. Для production можно заменить на Sliding Window Counter или Token Bucket в Redis, чтобы сгладить всплески на границе окна и синхронизировать лимиты между instance'ами.
Ответы login endpoint включают заголовки:
X-RateLimit-Limit- размер окна;X-RateLimit-Remaining- оставшиеся запросы;X-RateLimit-Reset- Unix timestamp завершения окна;Retry-After- количество секунд до следующей попытки, только для429.
Кеширование уменьшает количество чтений из БД на горячих endpoints каталога. При повторных запросах API возвращает готовый JSON из памяти, что снижает latency и нагрузку на MongoDB/PostgreSQL.
Rate limiting защищает login endpoint от всплесков и brute-force попыток. Вместо бесконечной нагрузки на БД и CPU API быстро возвращает 429, сохраняя ресурсы для легитимных запросов.
Рекомендуемые метрики:
- p50/p95/p99 latency по endpoint;
- RPS по endpoint и HTTP status;
- количество
429наPOST /auth/login; - cache hit rate и miss rate;
- время ответа БД и количество запросов к БД;
- количество активных HTTP потоков и длина очереди сервера;
- ошибки
5xx,401,403,409.
Измерение эффективности:
- выполнить серию повторных
GET /cars/availableиGET /cars/search?class=...; - сравнить долю
X-Cache: HITиX-Cache: MISS; - сравнить latency первого запроса после инвалидации и повторных запросов до истечения TTL;
- проверить, что после
POST /cars,POST /rentalsиPOST /rentals/{id}/completeследующий GET возвращаетX-Cache: MISS.