Nginx — настройка ограничения на кол-во подключений и количество запросов в единицу времени

В Nginx есть возможность ограничить количество соединений с одного адреса(модуль ngx_http_limit_conn_module) и ограничить количество запросов в единицу времени с одного адреса (модуль ngx_http_limit_req_module)

— позволяет ограничить число соединений по заданному ключу, в частности, число соединений с одного IP-адреса.

– позволяет ограничить скорость обработки запросов по заданному ключу, в частности, скорость обработки запросов, поступающих с одного IP-адреса

 

Ограничение количества соединений с одного адреса

Задаёт параметры зоны разделяемой памяти, которая хранит состояние для разных значений ключа. Состояние в частности содержит текущее число соединений

 

( по умолчанию limit_conn_log_level error;)

Задаёт желаемый уровень записи в лог случаев ограничения числа соединений.

 

(По умолчанию limit_conn_status 503;)

Позволяет переопределить код ответа, используемый при отклонении запросов.

 

В секции http файла nginx.conf

Задаем ключ, к которому относятся ограничения ($binary_remote_addr), зону с именем connection и размер зоны 10 мегабайт

Изменяем уровень протоколирования ограничений соединения с error на warn

 

Задаёт зону разделяемой памяти и максимально допустимое число соединений для одного значения ключа. При превышении этого числа в ответ на запрос сервер вернёт ошибку 503 (Service Temporarily Unavailable)

 

Ограничиваем кол-во соединений с одного адреса – не более 8 в конфигурационном файле виртуального хоста

 

 

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

 

Задаёт параметры зоны разделяемой памяти, которая хранит состояние для разных значений ключа. Состояние в частности хранит текущее число избыточных запросов.

 

( по умолчанию limit_conn_log_level error;)

Задаёт желаемый уровень записи в лог случаев отказа в обработке запросов при превышении скорости и случаев задержек при обработке запроса. Задержки записываются в лог с уровнем на единицу меньшим, чем отказы, например, если указано limit_req_log_level warn, то задержки будут записываться в лог на уровне notice.

 

(по умолчанию limit_req_status 503;   )

Позволяет переопределить код ответа, используемый при отклонении запросов.

Очень полезная утилита для запуска dry-run режима по rate limit

Эта директива появилась в Nginx версии 1.17.1

(по умолчанию limit_req_dry_run off;)

Включает режим пробного запуска. В данном режиме скорость обработки запросов не ограничивается, однако в зоне разделяемой памяти текущее число избыточных запросов учитывается как обычно.
Т.е отклонения запросов по факту не происходит, но выполняется полный расчет кол-ва соединений и все превышающие лимиты запросы записываются в лог-файл

 

 

Ограничение количества запросов в секунду с одного адреса — не более 5 со всплесками не более 10 запросов

Изменяем уровень протоколирования ограничений соединения с error на warn

 

В секции http файла nginx.conf

 

Задаёт зону разделяемой памяти (zone) и максимальный размер всплеска запросов (burst). Если скорость поступления запросов превышает описанную в зоне, то их обработка задерживается так, чтобы запросы обрабатывались с заданной скоростью. Избыточные запросы задерживаются до тех пор, пока их число не превысит максимальный размер всплеска. При превышении запрос завершается с ошибкой 503 (Service Temporarily Unavailable). По умолчанию максимальный размер всплеска равен нулю

 

В конфигурационном файле виртуального хоста

 

Если же избыточные запросы в пределах лимита всплесков задерживать не требуется, то следует использовать параметр nodelay:

 

 

Ограничения можно устанавливать,как для всего виртуального хоста (в директиве server), так и для отдельных location

Например, при связке Nginx+PHP-FPM можно устанавливать ограничения на количество запросов в секунду к php-файлам

 

В конфигурационном файле виртуального хоста

Тестировать можно через ab или siege утилиты

# siege -v -b -r 1 -c 10 https://mysite.com/index.php
# ab -n 20 -c 20 https://mysite.com/index.php

Для определенных IP-адресов, подсетей можно отключить rate limit
Для этого в http -секции добавляем блок

Вместо подключения файла с помощью директивы include можно перечислять список IP-адресов/сетей в таком же формате, как это указано в файле
sites-available/rate-limit-ips.txt

 

Далее приведу перевод отличной, на мой взгляд, статьи
оригинал
https://www.freecodecamp.org/news/nginx-rate-limiting-in-a-nutshell-128fe9e0126c
перевод
https://habr.com/ru/company/southbridge/blog/329876/

Директивы NGINX по ограничению скорости обработки запросов

В этой статье мы будем говорить о ngx_http_limit_req_module, в котором реализованы директивы limit_req_zone, limit_req, limit_req_status и limit_req_level. Они позволяют управлять значением кода состояния HTTP-запроса для отклоненных (rejected) запросов, а также логированием этих отказов.

Чаще всего путаются именно в логике отклонения запроса.

Сначала нужно разобраться с директивой limit_req, которой требуется параметр zone. У него также есть необязательные параметры burst и nodelay.

Здесь используются следующие концепции:

zone определяет «ведро» (bucket) — разделяемое пространство, в котором считаются входящие запросы. Все запросы, попавшие в одно «ведро», будут посчитаны и обработаны в его разрезе. Этим достигается возможность установки ограничений на основе URL, IP-адресов и т. д.

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

nodelay — также необязательный параметр, который используется совместно с burst. Ниже мы разберемся, зачем он нужен.

Каким образом NGINX принимает решение о принятии или отклонении запроса?

При настройке зоны задается ее скорость. Например, при 300r/m будет принято 300 запросов в минуту, а при 5r/s — 5 запросов в секунду.

Примеры директив:

Важно понимать, что эти две зоны имеют одинаковые лимиты. С помощью параметра rate NGINX рассчитывает частоту и, соответственно, интервал, после которого можно принять новый запрос. В данном случае NGINX будет использовать алгоритм под названием «дырявое ведро» (leaky bucket).

Для NGINX 300r/m и 5r/s одинаковы: он будет пропускать один запрос каждые 0,2 с. В данном случае NGINX каждые 0,2 секунды будет устанавливать флаг, разрешающий прием запроса. Когда приходит подходящий для этой зоны запрос, NGINX снимает флаг и обрабатывает запрос. Если приходит очередной запрос, а таймер, считающий время между пакетами, еще не сработал, запрос будет отклонен с кодом состояния 503. Если время истекло, а флаг уже установлен в разрешающее прием значение, никаких действий выполнено не будет.

Нужны ли ограничение скорости обработки запросов и шейпинг трафика?

Поговорим о параметре burst. Представьте, что флаг, о котором мы говорили выше, может принимать значения больше единицы. В этом случае он будет отражать максимальное количество запросов, которые NGINX должен пропустить в рамках одной пачки (burst).

Теперь это уже не «дырявое ведро», «маркерная корзина» (token bucket). Параметр rate определяет временной интервал между запросами, но мы имеем дело не с токеном типа true/false, а со счетчиком от 0 до 1 + burst Счетчик увеличивается каждый раз, когда проходит рассчитанный интервал времени (срабатывает таймер), достигая максимального значения в b+1. Напомню еще раз: burst — это количество запросов, а не скорость их пропускания.

Когда приходит новый запрос, NGINX проверяет доступность токена (счетчик > 0). Если токен недоступен, запрос отклоняется. В противном случае запрос принимается и будет обработан, а токен считается израсходованным (счетчик уменьшается на один).

Хорошо, если есть неизрасходованные burst-токены, NGINX примет запрос. Но когда он его обработает?

Мы установили лимит в 5r/s, при этом NGINX примет запросы сверх нормы, если есть доступные burst-токены, но отложит их обработку таким образом, чтобы выдержать установленную скорость. То есть эти burst-запросы будут обработаны с некоторой задержкой или завершатся по таймауту.

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

Приведем простой пример: скажем, у нас установлен лимит 1r/s и burst=3. Что будет, если NGINX получит сразу 5 запросов?

Первый будет принят и обработан.
Поскольку разрешено не больше 1+3, один запрос будет сразу отклонен с кодом состояния 503.
Три оставшихся будут обработаны один за другим, но не мгновенно. NGINX пропустит их со скоростью 1r/s, оставаясь в рамках установленного лимита, а также при условии, что не будут поступать новые запросы, которые также используют квоту. Когда очередь опустеет, счетчик пачки (burst counter) снова начнет увеличиваться (маркерная корзина начнет наполняться).

В случае использования NGINX в качестве прокси-сервера расположенные за ним сервисы будут получать запросы со скоростью 1r/s и ничего не узнают о всплесках трафика, сглаженных прокси-сервером.

Итак, мы только что настроили шейпинг трафика, применив задержки для управления всплесками запросов и выравнивания потока данных.

nodelay

nodelay говорит NGINX, что он должен принимать пакеты в рамках окна, определенного значением burst, и сразу их обрабатывать (так же как и обычные запросы).

В результате всплески трафика все же будут достигать сервисов, расположенных за NGINX, но эти всплески будут ограничены значением burst.

Источник:

https://habr.com/ru/company/southbridge/blog/329876

https://www.freecodecamp.org/news/nginx-rate-limiting-in-a-nutshell-128fe9e0126c

http://nginx.org/ru/docs/http/ngx_http_limit_conn_module.html

http://nginx.org/ru/docs/http/ngx_http_limit_req_module.html

Комментирование и размещение ссылок запрещено.

Комментарии закрыты.

Яндекс.Метрика