Ответ
Ключ должен связать limit_req_zone
и map
.О них есть две соответствующие заметки в документах. map :
default value
устанавливает результирующее значение, если исходное значение не соответствует ни одному из указанных вариантов.Если default
не указано, результирующим значением по умолчанию будет пустая строка .
и limit_req_zone :
limit_req_zone key zone = name: size rate = rate;
Устанавливает параметры для зоны общей памяти, в которой будут храниться состояния для различных клавиш,В частности, государство хранит текущее количество чрезмерных запросов.key
может содержать текст, переменные и их комбинацию. Запросы с пустым значением ключа не учитываются .
Таким образом, можно просто использовать и день и ночь limit_req_zone
с $server_name
как ключ , если он должен работать, и с пустой строкой, если он не должен.И map
вернет либо $server_name
, либо пустую строку в зависимости от времени суток.
map $date_gmt $day {
# 07:00-20:59 GMT
~(0[7-9]|1[0-9]|20):[0-5][0-9]:[0-5][0-9] $server_name;
}
map $date_gmt $night {
# 21:00-06:59 GMT
~(2[1-4]|0[0-6]):[0-5][0-9]:[0-5][0-9] $server_name;
}
limit_req_zone $day zone=day_zone:1m rate=1r/s;
limit_req_zone $night zone=night_zone:1m rate=4r/s;
...
limit_req zone=day_zone burst=100;
limit_req zone=night_zone burst=100;
Некоторые заметки о req_limit
При первой попытке я попыталсяиспользуйте сопоставленную переменную в limit_req
, но nginx не понимает такой синтаксис.Более того, на первый взгляд nginx -s reload
работал без проблем, но на самом деле перезагрузки не было, и только service nginx restart
показывал ошибку (версия nginx: 1.12.2).Поэтому я хотел бы показать, как один не должен делать :
limit_req_zone $server_name zone=day:1m rate=1r/s;
limit_req_zone $server_name zone=night:1m rate=4r/s;
map $date_gmt $time_of_day {
~(0[7-9]|1[0-9]|20):[0-5][0-9]:[0-5][0-9] day;
~(2[1-4]|0[0-6]):[0-5][0-9]:[0-5][0-9] night;
}
...
limit_req zone=$time_of_day burst=100;
Несколько замечаний о производительности
Это не таклучшее решение из-за двойной проверки времени на каждый запрос.Существует возможность иметь два отдельных конфига nginx и переключать их чем-то вроде cron.Это было бы уродливо и глючно, потому что вы должны помнить, что нужно редактировать две конфигурации, но это будет работать быстрее;Я думаю, что этот вариант следует использовать в качестве крайней меры.Если есть возможность горизонтального масштабирования, лучше балансировать нагрузку на несколько серверов.В моем случае это не имеет большого значения: сервис получает около 8 тыс. Запросов в час (2,2 об / с).