Обновлено: 8 апреля 2026 г. в 14:55

Rate Limiter

средний

Классический кейс про лимитер запросов: выбор алгоритма, хранение счётчиков в Redis и определение точки применения лимита в распределённой системе.

Лимитер запросов кажется задачей про счётчик, но на деле это кейс про справедливое распределение ресурса, всплески нагрузки и поведение системы в момент отказа защитного слоя.

Глава помогает сравнить Token Bucket, Leaky Bucket и Sliding Window, выбрать точку применения лимита, способ хранения счётчиков и режим работы при сбоях.

В интервью и архитектурных обсуждениях этот кейс быстро показывает, умеете ли вы рассуждать о злоупотреблениях, критическом пути и цене неудачной политики по умолчанию.

Control Plane

Фокус на governance-политиках, лимитах, маршрутизации и стабильности edge-поведения.

Data Path

Нужно держать предсказуемую latency и throughput при росте трафика и burst-нагрузке.

Failure Modes

Покрывайте fail-open/fail-close, деградацию и безопасный резервный сценарий при частичных отказах.

Ops Ready

Показывайте мониторинг saturation, retry storm и операционные защитные ограничения.

Rate Limiter — классический кейс про защиту публичного API и справедливое распределение ресурса. На поверхности это просто счётчик запросов, но на практике приходится решать, где именно применять лимит, как хранить состояние между инстансами и что делать, если сам лимитер начинает ошибаться или недоступен.

Именно поэтому задача так полезна на интервью: она быстро выводит разговор на между точностью ограничения, на критическом пути и поведением системы при отказе самого защитного слоя.

Глава 4

Alex Xu: Rate Limiter

Подробный разбор алгоритмов и архитектурных решений в книге

Читать обзор

Зачем нужен лимитер запросов

Что происходит без лимитов

  • DDoS атаки — перегрузка сервиса вредоносным трафиком
  • Каскадные отказы — один источник трафика может перегрузить весь сервис
  • Перерасход ресурсов — бесконтрольное потребление API
  • Неравномерная нагрузка — "шумные соседи" мешают другим

Что даёт лимитер запросов

  • Защита сервисов — предотвращение перегрузки
  • Справедливое распределение — квоты для каждого клиента
  • Экономия денег — контроль использования платных API
  • Предсказуемость — стабильная производительность

Типичные требования

Функциональные

  • FR1
    Ограничение запросов по IP-адресу, идентификатору пользователя или API-ключу
  • FR2
    Настраиваемые лимиты для разных эндпоинтов
  • FR3
    Информативный ответ при превышении лимита (429)
  • FR4
    Работа в распределённой среде

Нефункциональные

  • NFR1
    Низкая задержка — меньше 1 мс дополнительного времени на запрос
  • NFR2
    Высокая доступность — сбой лимитера ≠ сбой сервиса
  • NFR3
    Точность лимитов (допустима погрешность до ±5% в распределённой среде)
  • NFR4
    Горизонтальное масштабирование

Алгоритмы ограничения запросов

У каждого классического алгоритма свой профиль точности, памяти и поведения под всплесками нагрузки:

Интерактивная визуализация

1. Token Bucket

Бакет с токенами пополняется с постоянной скоростью. Каждый запрос забирает один токен.

Преимущества

  • Простая реализация
  • Хорошо переживает всплески нагрузки
  • Экономно расходует память (два числа на пользователя)

Недостатки

  • Непросто выбрать размер бакета
  • В распределённой среде возможны гонки при обновлении счётчиков

# Параметры:

bucket_size = 10 # максимум токенов

refill_rate = 2 # скорость пополнения

Визуализация алгоритма

Токены:
5.0 / 5
Пополнение: 1 ток./сек
t = 0.0s
История запросов:
Нажмите "Старт" и отправляйте запросы

Архитектура решения

Связанный кейс

API Gateway

Полный разбор API Gateway: маршрутизация, безопасность, BFF-паттерн и сравнение технологий.

Читать кейс

Где лучше ставить лимитер запросов?

На стороне клиента

Такой лимит легко обойти, поэтому он годится только как дополнительная оптимизация.

API Gateway

Самая удобная точка: единый вход в систему перед прикладными сервисами. AWS API Gateway, Kong, Envoy.

Внутри сервиса

Даёт гибкость, но приводит к дублированию логики и усложняет синхронизацию лимитов.

Zhiyong Tan

Acing SDI: Rate Limiter

Сравнение вариантов размещения лимитера в реальных системах

Читать обзор

Реализация на базе Redis

Redis часто выбирают для лимитера запросов из-за работы в памяти и атомарных операций.

Sliding Window Counter на Redis

-- Lua-скрипт для атомарного обновления
local key = KEYS[1]
local window = tonumber(ARGV[1])  -- размер окна в секундах
local limit = tonumber(ARGV[2])   -- лимит запросов
local now = tonumber(ARGV[3])     -- текущая метка времени

-- Удаляем устаревшие записи
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)

-- Считаем запросы в текущем окне
local count = redis.call('ZCARD', key)

if count < limit then
    -- Добавляем новый запрос
    redis.call('ZADD', key, now, now .. '-' .. math.random())
    redis.call('EXPIRE', key, window)
    return 1  -- запрос разрешён
else
    return 0  -- запрос отклонён
end

Защита от гонок

Проблема: Параллельные запросы могут одновременно увидеть одно и то же значение счётчика.

Решение: Lua-скрипты выполняются в Redis атомарно.

Альтернатива: Redis MULTI/EXEC или Redlock, если нужна распределённая блокировка.

Синхронизация между инстансами

Централизованный вариант: Один Redis-кластер обслуживает все инстансы приложения.

Согласованность в конечном счёте: Локальные счётчики с периодической синхронизацией.

Компромисс: Точность против задержки.

HTTP-заголовки ответа

# При успешном запросе:

X-RateLimit-Limit: 100

X-RateLimit-Remaining: 42

X-RateLimit-Reset: 1640995200

# При превышении лимита:

HTTP/1.1 429 Too Many Requests

Retry-After: 30

Глубже: многоуровневые лимиты

В реальных системах лимиты почти всегда задают на нескольких уровнях одновременно:

Уровни лимитов

  • Глобальный: 10 млн запросов в сутки на весь сервис
  • На пользователя: 1000 запросов в час
  • На эндпоинт: 100 запросов в минуту на `/api/search`
  • На IP-адрес: защита от перегрузки с одного источника

Мягкая деградация

  • Мягкий лимит: предупреждение в заголовках ответа
  • Жёсткий лимит: ответ `429` и `Retry-After`
  • Сбой Redis: пропускать запросы или, наоборот, блокировать их?
  • Наблюдаемость: оповещения об аномалиях трафика

Что важно проговорить на интервью

  • 1
    Начните с требований: какой профиль трафика, допустима ли погрешность и нужна ли работа в распределённой среде?
  • 2
    Выберите алгоритм: Token Bucket подходит для всплесков, Sliding Window Counter — когда нужна более точная оценка текущей нагрузки.
  • 3
    Проговорите компромиссы: память против точности, задержка против строгости синхронизации между инстансами.
  • 4
    Redis + Lua: атомарные операции убирают гонки при обновлении счётчиков.
  • 5
    Поведение при сбое: что делать, если сам лимитер недоступен?

Для дополнительной практики и сравнения реализаций полезно посмотреть System Design Primer: Rate Limiter и Cloudflare Rate Limiting Rules.

Связанные главы

  • System Design Primer (краткий обзор) - даёт базовую рамку для требований, ограничений и оценки узких мест в задачах про лимиты запросов.
  • System Design Interview - Alex Xu - содержит классический интервью-разбор лимитера запросов с акцентом на алгоритмы и архитектурные компромиссы.
  • Acing the System Design Interview - дополняет тему практическими вариантами размещения лимитера в распределённой среде.
  • API Gateway - показывает основной эксплуатационный контур, где лимиты запросов чаще всего вводят централизованно.
  • API Security Patterns - связывает лимиты запросов с более широкой защитой API: аутентификацией, борьбой со злоупотреблениями и исполнением политик доступа.
  • Стратегии кэширования - помогает выбрать подход к хранению счётчиков и кэшированию так, чтобы не раздувать дополнительную задержку.
  • Resilience Patterns - расширяет тему поведения лимитера при сбоях: когда пропускать запросы, когда блокировать и как деградировать без каскадных отказов.
  • Notification System - показывает прикладной кейс, где многоуровневые лимиты сдерживают всплески нагрузки и защищают зависимые сервисы.
  • Web Crawler - демонстрирует необходимость лимитов для вежливого и контролируемого доступа к внешним источникам.
  • Payment System - даёт контекст критичных систем, где лимиты запросов защищают дорогостоящие и чувствительные операции.

Чтобы отмечать прохождение, включи трекинг в Настройки