Компьютерные сети

Rate Limiting

Один клиент с циклом без sleep может генерировать 10,000 RPS и положить ваш сервис. Rate limiting - обязательный компонент любого production API, от защиты до монетизации.

  • **Twitter/X API**: 15 requests per 15-min window для поиска. Превысил - 429 Too Many Requests до конца окна
  • **Stripe API**: разные лимиты для read/write операций, burst capacity для пиков, постепенное восстановление
  • **Cloudflare**: rate limiting на edge, защита origin серверов от перегрузки и DDoS

Предварительные знания

  • Load Balancing: Basics

Token Bucket

**Token Bucket** - самый популярный алгоритм rate limiting. Представьте ведро с токенами: токены добавляются с фиксированной скоростью, каждый запрос забирает токен. Нет токенов - запрос отклонён.

**Burst capacity** - ключевое преимущество token bucket. Если клиент молчал минуту, он накопил токены и может сделать burst запросов. Это хорошо для real-world трафика.

AWS API Gateway, Stripe, GitHub API используют token bucket. Параметры: **capacity** (макс токенов), **refill rate** (токенов/сек). Запрос может требовать несколько токенов (тяжёлые операции дороже).

Token bucket с capacity=100 и rate=10/sec. Клиент молчал 20 секунд. Сколько запросов он может сделать мгновенно?

Leaky Bucket

**Leaky Bucket** - альтернатива, обеспечивающая **строго равномерный** выходной поток. Запросы попадают в очередь (bucket), обрабатываются с постоянной скоростью. Переполнение очереди - отказ.

**Leaky bucket используется** для network traffic shaping (QoS роутерах), когда нужен гарантированно равномерный поток. Для API rate limiting предпочитают token bucket из-за поддержки burst.

Nginx использует leaky bucket (ngx_http_limit_req_module). При burst параметре запросы ставятся в очередь вместо мгновенного отказа. `limit_req zone=api burst=20 nodelay;`

Когда leaky bucket лучше token bucket?

Sliding Window

**Fixed Window** считает запросы в фиксированных интервалах (например, по минутам). Проблема: на границе окон возможен burst в 2x лимита. **Sliding Window** решает это.

**Sliding Window Counter** - оптимальный баланс точности и памяти. Используется в Cloudflare, Redis rate limiting. Погрешность ~0.003% при равномерном трафике.

На интервью: Fixed Window проще всего реализовать (один счётчик), Sliding Window Log точнее всего (но дорого по памяти), Sliding Window Counter - production выбор для большинства случаев.

Почему sliding window counter предпочтительнее sliding window log в production?

Distributed Rate Limiting

При множестве серверов rate limit должен быть **глобальным**. Локальный счётчик на каждом сервере позволит клиенту превысить лимит в N раз (по числу серверов).

**Production выбор**: Redis с replica для HA. При Redis failure - fallback на local rate limit (лучше пропустить лишнее, чем отказать всем). Stripe, Discord используют этот подход.

Race condition: два сервера читают counter=99, оба инкрементят до 100, оба пропускают. Решение: атомарные операции Redis (INCR возвращает новое значение) или Lua скрипты для check-and-increment.

Как избежать race condition при distributed rate limiting?

Redis Rate Limiting

Redis - стандарт для distributed rate limiting благодаря атомарным операциям и скорости. Рассмотрим практические реализации разных алгоритмов.

**Lua scripts** выполняются атомарно в Redis - никаких race conditions. Передаём скрипт через EVALSHA (кешируется). Latency: ~0.1ms для Lua скрипта.

Лучшие практики: добавляйте jitter к TTL (избежать thundering herd), возвращайте клиенту заголовки X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After. При Redis failure - graceful degradation на local limits.

Rate limiting нужен только для защиты от DDoS атак

Rate limiting защищает от перегрузки (fair usage), обеспечивает предсказуемую производительность (SLA), и является инструментом монетизации (API tiers: free/pro/enterprise)

DDoS - лишь один сценарий. Rate limiting нужен даже без злоумышленников: один клиент с багом может положить сервис. API экономика построена на rate limits (Stripe: 100 req/sec free, 1000 req/sec paid).

Почему Lua скрипты предпочтительнее множественных Redis команд для rate limiting?

Итоги

  • **Token Bucket**: позволяет burst, затем ограничивает - лучший выбор для API
  • **Leaky Bucket**: сглаживает трафик до константы - для network shaping
  • **Sliding Window Counter**: O(1) память, нет boundary burst - production стандарт
  • **Redis + Lua**: атомарные операции для distributed rate limiting

Связанные темы

Rate limiting связан с другими паттернами защиты и масштабирования:

  • Load Balancing — Rate limit часто на уровне load balancer
  • API Gateway — Gateway - централизованное место для rate limiting
  • Resilience Patterns — Rate limit + circuit breaker для полной защиты

Вопросы для размышления

  • Как бы вы реализовали разные rate limits для free и premium пользователей?
  • Что делать, если Redis недоступен - отказывать всем или пропускать всех?
  • Как rate limiting взаимодействует с retry логикой клиента?

Связанные уроки

  • sd-17-rate-limiting
Rate Limiting

0

1

Войти