hostprofi.ru
Подобрать хостинг
Термин·буква T

Too Many Requests (429)

краткое определение

429 Too Many Requests — HTTP-статус, означающий, что клиент превысил допустимое количество запросов за определённый период времени (rate limit). Сервер отвергает запрос и рекомендует подождать через заголовок Retry-After.

HTTP 429 Too Many Requests — код ответа RFC 6585 (2012), возвращаемый сервером при превышении клиентом rate limit — ограничения частоты запросов. Защищает сервер от злоупотреблений, DDoS-атак и некорректно настроенных клиентов, которые отправляют избыточное число запросов за короткий период.

Заголовки при 429

Корректный ответ 429 включает заголовок Retry-After и опциональные заголовки информации о лимите:

  • Retry-After: 60 — подождать 60 секунд перед повтором.
  • Retry-After: Wed, 26 Jun 2024 10:30:00 GMT — подождать до конкретного времени.
  • X-RateLimit-Limit: 100 — максимальное число запросов в периоде.
  • X-RateLimit-Remaining: 0 — осталось запросов в текущем периоде.
  • X-RateLimit-Reset: 1719398400 — unix-timestamp сброса счётчика.

Стандарт IETF Draft «RateLimit Header Fields for HTTP» (2023) предлагает унифицировать эти заголовки как RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset.

Алгоритмы rate limiting

  • Fixed Window — N запросов за период T (100 req/min). Прост в реализации, но уязвим к burst-атаке на границе временного окна: 100 запросов в конце одного окна + 100 в начале следующего = 200 запросов за 2 секунды.
  • Sliding Window Log — хранит timestamps всех запросов за последние T секунд. Точный, но памятеёмкий.
  • Sliding Window Counter — гибрид: считает запросы в текущем окне + взвешенный остаток из предыдущего. Точный и дешёвый по памяти.
  • Token Bucket — токены добавляются с постоянной скоростью (r токенов/с), каждый запрос тратит 1 токен. Разрешает burst при накопленных токенах. Использует Nginx (через burst параметр).
  • Leaky Bucket — запросы добавляются в очередь (bucket), обрабатываются с постоянной скоростью. Сглаживает bursts, но добавляет задержку.

Реализация в Nginx

Nginx поддерживает rate limiting через модуль ngx_http_limit_req_module:

http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $http_x_api_key zone=apikeyzone:10m rate=100r/s;

    server {
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            limit_req zone=apikeyzone burst=200 nodelay;
            limit_req_status 429;
        }
    }
}

rate=10r/s — 10 запросов в секунду. burst=20 — вспышка до 20 запросов без задержки. nodelay — не ставить в очередь, сразу отдавать 429. Зона apikeyzone — отдельный лимит для авторизованных клиентов с API-ключом.

История

Код 429 стандартизирован в RFC 6585 (апрель 2012 года). До этого API-провайдеры использовали нестандартные коды: Twitter возвращал 420 (нестандартный), некоторые провайдеры — 403. RFC 6585 унифицировал подход. С ростом публичных API в 2010-х rate limiting стал обязательным требованием безопасности и защиты от злоупотреблений.

Rate limiting в хостинге

На VPS-серверах 429 применяется для защиты API и форм от автоматизированных запросов. Redis — стандартный backend для счётчиков rate limiting: атомарный INCR + EXPIRE на ключ вида ratelimit:IP:minute. Cloudflare WAF и Anti-DDoS сервисы предоставляют готовые правила rate limiting на сетевом уровне — до достижения origin-сервера. При настройке rate limiting важно учитывать легитимных пользователей за корпоративным NAT: один IP, но сотни пользователей. Ограничивать по API-ключу или учётной записи эффективнее, чем только по IP.

429 в API-интеграциях

При интеграции с внешними API (OpenAI, Yandex API, Telegram Bot API) код 429 означает исчерпание квоты. Правильная обработка: exponential backoff с jitter — каждая повторная попытка удваивает паузу с добавлением случайной составляющей. Пример на Python:

import time, random

def api_call_with_retry(func, max_retries=5):
    for attempt in range(max_retries):
        response = func()
        if response.status_code != 429:
            return response
        retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
        time.sleep(retry_after + random.uniform(0, 1))
    raise Exception("Rate limit exceeded after retries")

Другие термины

Too Many Requests (429) — что это, определение и как работает | Справочник — hostprofi.ru