Обмеження частоти запитів

OxPHP має вбудований обмежувач частоти запитів за IP-адресою, тож вам не потрібні зовнішні залежності чи окрема інфраструктура. Після ввімкнення він рахує запити від кожної клієнтської IP-адреси й повертає відповідь 429 Too Many Requests, щойно клієнт перевищує налаштований поріг.

Як це працює

Обмежувач використовує лічильник із фіксованим вікном, прив’язаний до IP-адреси клієнта. Кожна IP-адреса має власний незалежний лічильник і власне вікно.

  1. Коли надходить запит, OxPHP шукає IP-адресу клієнта у своєму внутрішньому трекері.
  2. Якщо запису немає або поточне вікно вже минуло, починається нове вікно з нульовим лічильником.
  3. Лічильник збільшується з кожним запитом.
  4. Якщо лічильник перевищує RATE_LIMIT, сервер одразу повертає відповідь 429 із заголовками rate limit. Запит відхиляється ще до маршрутизації та виконання PHP.

Обмежені запити все одно потрапляють до журналів доступу та метрик.

Налаштування

Змінна Типове значення Опис
RATE_LIMIT 0 Максимальна кількість запитів з однієї IP-адреси в межах вікна. 0 повністю вимикає обмеження без жодних накладних витрат
RATE_WINDOW_SECONDS 60 Тривалість вікна обмеження в секундах
bash
# Allow 100 requests per IP per 60-second window RATE_LIMIT=100 RATE_WINDOW_SECONDS=60

Заголовки відповіді

Відхилені запити отримують відповідь 429 Too Many Requests з такими заголовками:

Заголовок Опис
Retry-After Кількість секунд до скидання поточного вікна
x-ratelimit-limit Максимальна дозволена кількість запитів за вікно
x-ratelimit-remaining Скільки запитів лишилося в поточному вікні (0, коли ліміт вичерпано)
x-ratelimit-reset Кількість секунд до скидання поточного вікна
x-request-id Ідентифікатор запиту, щоб зіставити цю відповідь із журналами доступу

Приклад відповіді 429:

http
HTTP/1.1 429 Too Many Requests Retry-After: 45 x-ratelimit-limit: 100 x-ratelimit-remaining: 0 x-ratelimit-reset: 45 x-request-id: 67e2a1f412341a2b0042 429 Too Many Requests

Усунення несправностей

Обмеження зачіпає звичайних користувачів

Можливо, ваш поріг занадто низький для реального трафіку. Перевірте частку відповідей 429 у метриках і відповідно змініть RATE_LIMIT або RATE_WINDOW_SECONDS.

Перевірте кількість обмежених запитів:

bash
curl http://localhost:9090/metrics | grep rate_limited

Рішення: збільште RATE_LIMIT або подовжте RATE_WINDOW_SECONDS, щоб дати клієнтам більше простору.

Користувачі за корпоративним NAT ділять один лічильник IP

OxPHP обмежує частоту за IP-адресою джерела. Усі користувачі за спільним NAT чи проксі ділять один лічильник. Якщо це спричиняє проблеми, вимкніть вбудований обмежувач OxPHP (RATE_LIMIT=0) і застосуйте обмеження на вищому рівні (наприклад, на балансувальнику навантаження чи API-шлюзі), де вам доступні ідентифікатори користувачів.

За зворотним проксі?

Задайте TRUSTED_PROXIES, щоб обмеження спиралося на справжню IP-адресу клієнта, а не на IP-адресу проксі. Див. Довірені проксі.

Обмеження не працює між кількома екземплярами

Обмежувач OxPHP зберігає стан у пам’яті окремо для кожного екземпляра. Якщо ви запускаєте кілька екземплярів OxPHP за балансувальником навантаження, кожен веде власні незалежні лічильники. Клієнт може надіслати RATE_LIMIT запитів на кожен екземпляр, не отримавши 429. Для узгодженого обмеження між екземплярами використовуйте зовнішній обмежувач на рівні балансувальника навантаження чи API-шлюзу.

Пам’ять зростає під час атак із ротацією IP

OxPHP відстежує до 100 000 унікальних IP-адрес. Коли цю межу досягнуто, прострочені записи видаляються перед додаванням нових. Якщо ви бачите зростання пам’яті через те, що зловмисник швидко змінює IP-адреси, автоматичне очищення обмежує вплив фіксованим обсягом пам’яті.

Приклад для Docker

compose.yaml
services: app: image: ghcr.io/oxphp/oxphp:0.13.0 ports: - "8080:80" environment: RATE_LIMIT: "100" RATE_WINDOW_SECONDS: "60" volumes: - ./app:/var/www/html:ro

Рекомендації

  • Починайте обережно. Задайте спершу нижчий ліміт (наприклад, 60 запитів на хвилину) і підвищуйте його з огляду на реальний трафік. Послабити ліміти легше, ніж відновити перевантажений сервер.
  • Для розгортань із кількома екземплярами використовуйте спільний обмежувач. Обмежувач OxPHP працює в межах одного екземпляра. Для узгодженого обмеження між екземплярами застосуйте його на рівні балансувальника навантаження чи API-шлюзу.
  • Стежте за часткою відповідей 429. Відстежуйте в метриках частку обмежених запитів, щоб помітити хибно налаштовані пороги чи несподівані сплески трафіку.

Примітки

  • Алгоритм фіксованого вікна. Обмежувач використовує лічильник із фіксованим, а не ковзним вікном. На межі двох вікон клієнт може надіслати сплеском до 2x від налаштованого ліміту.
  • Лише за IP-адресою. Ключем обмеження є IP-адреса джерела. Власні ключі, як-от API-ключ чи ідентифікатор користувача, не підтримуються.
  • Стан у пам’яті. Лічильники не спільні між кількома екземплярами OxPHP.
  • Автоматичне очищення. Коли трекер перевищує 100 000 IP-адрес, з нього видаляються всі записи з простроченими вікнами.

Промпти для вашого агента

Ці промпти розраховані на агента з підключеним MCP-сервером документації OxPHP — потрібні сторінки він прочитає сам.

prompt
Налаштуй обмеження частоти запитів для мого розгортання OxPHP. Прочитай сторінку `features/rate-limiting` через MCP-сервер документації OxPHP. Переглянь ендпоінти, які відкриває цей репозиторій, і трафік, що припадає на один екземпляр, обери ліміт і вікно та скажи, чи вистачить обмежувача на рівні екземпляра для мого способу розгортання.

Див. також