Какие плюсы и минусы у ограничения частоты запросов (rate limiting)?

«Какие плюсы и минусы у ограничения частоты запросов (rate limiting)?» — вопрос из категории Веб-серверы и балансировка, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Rate limiting (ограничение частоты запросов) — это механизм контроля количества запросов от клиента за единицу времени.

Плюсы:

  • Защита от атак: Основная защита от DDoS-атак типа "flood" и brute-force атак на логины/API.
  • Стабильность сервиса: Предотвращает исчерпание ресурсов бэкенда (CPU, память, соединения с БД) одним клиентом, обеспечивая fair usage для всех.
  • Контроль затрат: Для API с тарификацией позволяет контролировать использование в рамках платного плана.
  • Защита бэкенда: Служит "буфером" для медленных или уязвимых upstream-сервисов.

Минусы и сложности:

  • Ложные срабатывания: Клиенты за общим NAT или прокси (корпоративные сети, мобильные операторы) могут быть восприняты как один источник и заблокированы.
  • Усложнение архитектуры: Для распределенного лимитирования (когда несколько инстансов бэкенда или балансировщика) требуется общее хранилище состояния, например, Redis. Конфигурация в Nginx без Redis работает только для одного инстанса.
  • Блокировка легитимного трафика: Агрессивные поисковые роботы, сканеры безопасности или полезные скрипты могут быть ошибочно ограничены.
  • Нагрузка на клиента: Требует от клиентских приложений корректной обработки HTTP-статуса 429 Too Many Requests и реализации механизма backoff (экспоненциальной задержки) при повторе.

Практический пример в Nginx:

# Определяем зону лимита 'mylimit' (10 МБ памяти, ключ — IP, лимит 10 запросов в секунду)
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

server {
    location /api/ {
        # Применяем зону. burst=20 позволяет накапливать "кредиты" для кратковременных всплесков.
        # nodelay немедленно обрабатывает запросы в пределах burst, не задерживая их.
        limit_req zone=mylimit burst=20 nodelay;

        # Проксируем запрос дальше, если лимит не превышен
        proxy_pass http://backend;

        # Возвращаем 429 при превышении
        limit_req_status 429;
    }
}