NGINX: поведение ограничения времени ожидания для запросов в очереди (пакет)

В настоящее время у нас есть размер очереди 3000 запросов.

location /api/v2 {
     limit_req zone=bursted burst=3000;
     include /etc/nginx/proxy.conf;
 }

Ограничение скорости составляет 10 запросов в секунду.

 limit_req_zone $limit zone=api_slow:10m rate=1r/s;
 limit_req_zone $server_name zone=bursted:10m rate=10r/s;

Срок действия Keep-Alive составляет 30 секунд. Другими словами, 2700 запросов следует отклонять с кодом ошибки 408 каждые 30 секунд, когда очередь заполнена.

 reset_timedout_connection on;
 client_body_timeout 10;
 send_timeout 2;
 keepalive_timeout 30;

В часы пик я не смог найти ни одного запроса в журналах, который был отклонен с кодом ошибки 408 NGINX из-за истечения времени ожидания, пока запрос находился в очереди для пересылки в контейнер сервлета. Отклонять только с кодом ошибки 503, который соответствует накладным расходам.

delaying request, excess: 2958.320, by zone "bursted"
limiting requests, excess: 3000.730 by zone "bursted"

NGINX отклоняет запросы в таких очередях по таймауту, если они слишком долго зависают? Что это за тайм-аут? Где его конфигурация?

1 ответ

Кажется, есть некоторая путаница, как работают ограничения скорости nginx и таймауты. Для ограничения скорости нет времени ожидания. Вы просто устанавливаете скорость и размер очереди. Любые запросы, превышающие скорость, добавляются в очередь для последующей обработки. Как только очередь будет полностью заполнена, любой дополнительный запрос будет отклонен с кодом состояния 503.


В вашем примере вы установили скорость 10 запросов в секунду (10r/s), размер пакета 3000 для зоны, "лопнувшей" с размером 10 мегабайт. И это ограничение скорости применяется как отдельный счет для каждого определенного сервера.

Другими словами, ваш сервер принимает и обрабатывает один запрос каждые 0,1 секунды и может поставить в очередь до 3000 превышающих запросов, которые затем обрабатываются с определенной скоростью: один раз в 0,1 секунды. И ваша взрывная зона может хранить около 160 000 IP-адресов.

Это означает, что если запрос 3011 приходит в течение одной секунды, nginx немедленно обрабатывает первые 10 запросов, помещает в очередь еще 3000 запросов, и 3011-й запрос будет отклонен с кодом состояния 503. Затем очередь будет обрабатываться с определенной скоростью одного запроса каждые 0,1 секунды. Пока новые запросы не поступают, очередь становится короче и новые запросы могут быть снова добавлены в очередь. Но хотя очередь уже содержит 3000 запросов, каждый дополнительный запрос будет отклонен с кодом состояния 503.

Такое поведение при линейной обработке очереди может сделать ваш сайт медленным. Чтобы предотвратить это, вы можете добавить nodelay параметр для limit_req zone=bursted burst=3000 nodelay;, Это приведет к немедленной обработке всех запросов из вашей очереди пакета, в то время как слоты в очереди помечаются как "занятые", а затем снова "освобождаются" слот за слотом с определенной скоростью, поэтому с течением времени достигается определенный лимит скорости.

Кстати: вы можете изменить код состояния для отклоненных запросов с 503 на 444, добавив limit_req_status 444; на ваш http блок конфигурации

Для более подробной информации смотрите:


Два таймаута из вашей конфигурации:

client_body_timeout 10; заставит ваш сервер ждать до 10 секунд, пока тело клиента не будет отправлено после запроса. Если в течение этого времени от клиента не будет отправлено тело, сервер закроет соединение с кодом состояния 408.

keepalive_timeout 30; заставит ваш сервер закрыть любое соединение с клиентом, которое все еще открыто через 30 секунд. Но, согласно моим тестам, время ожидания запроса в очереди пакета не учитывается для keepalive_timeout.


Выполните нагрузочные испытания, используя ab или осаду.

Другие вопросы по тегам