Как настроить rate limiting и throttling?
Подробный ответ
Зачем нужны лимиты
Rate limiting защищает API от перебора паролей, злоупотребления дорогими endpoints, случайных циклов на клиенте и перегрузки инфраструктуры. Лимиты обычно различаются для анонимных пользователей, авторизованных клиентов, API keys и административных операций.
Где реализовывать
API gateway, CDN или WAF — удобно для защиты периметра и IP-лимитов;
Nginx, Traefik или ingress — подходит для инфраструктурных ограничений;
FastAPI dependency или middleware — удобно для бизнес-лимитов по пользователю, тарифу или endpoint;
Redis — общий backend для счётчиков между workers и репликами.
Стратегии ограничения
Fixed window прост в реализации, но допускает всплеск на границе окна. Sliding window даёт более ровное ограничение. Token bucket и leaky bucket позволяют контролировать среднюю скорость и допустимый burst. Для production важно, чтобы проверка и увеличение счётчика были атомарными.
Пример dependency
from fastapi import Depends, HTTPException, Request, status
async def rate_limit(request: Request):
key = f'ratelimit:{request.client.host}'
allowed = await redis_rate_limiter.allow(key, limit=100, window_seconds=60)
if not allowed:
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail='Too many requests',
headers={'Retry-After': '60'},
)
@app.get('/api/v1/articles', dependencies=[Depends(rate_limit)])
async def get_articles():
return []Выбор ключа
IP-адрес не всегда надёжен: за NAT может находиться много пользователей, а прокси может скрывать клиента. Для авторизованных API лучше лимитировать по user ID или API key, а IP использовать как дополнительный уровень защиты. При работе за reverse proxy нужно безопасно настроить доверие к forwarded headers.
Ответ и наблюдаемость
При превышении лимита API возвращает 429 Too Many Requests, а при необходимости — заголовки с информацией о лимите и времени повтора. Нужно собирать метрики срабатываний, чтобы отличать атаки от неправильно настроенных лимитов для легитимных клиентов.
Как ответить на собеседовании
В распределённом сервисе я не храню rate limit в памяти worker. Для общих лимитов использую Redis с атомарным алгоритмом или настраиваю ограничение на API gateway. Ключ выбираю по user ID или API key, для превышения возвращаю 429 и добавляю метрики; лимиты для авторизации делаю строже, чем для обычного чтения.
Оцени свой прогресс