Возникла надобность использовать limit_req, но столкнулся с неприятным моментом работы ограничителя. В документации приводится пример:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
location /search/ {
limit_req zone=one;
}
}
который (за отсутствием исчерпывающего описания) наталкивает на мысль, что указанный limit_req будет ограничивать частоту прихода запросов GET /search/, однако на практике это не так.
Счётчик, указанный директивой limit_req_zone, является глобальным для $binary_remote_addr и накручивается независимо от запроса. Из-за этого если в одну и ту же секунду от одного и того же IP пришёл какой-то запрос и запрос GET /search/, последний будет отклонён - сработает limit_req, хотя он был единственным search-ем за эту секунду.
Попробовал на опыте - действительно работает не так, как ожидалось:
http {
limit_req_zone $binary_remote_addr zone=limited:10m rate=1r/s;
server {
listen 80 default_server;
location / { return 404; }
location /123 {
root /tmp/zzz;
limit_req zone=limited nodelay;
}
}
}
bash$ touch /tmp/zzz/123
bash$ { curl -s -o /dev/null -D - localhost/123; curl -s -o /dev/null -D - localhost/123; } | fgrep HTTP
HTTP/1.1 200 OK
HTTP/1.1 503 Service Temporarily Unavailable
bash$ { curl -s -o /dev/null -D - localhost/aaaaa; curl -s -o /dev/null -D - localhost/123; } | fgrep HTTP
HTTP/1.1 404 Not Found
HTTP/1.1 503 Service Temporarily Unavailable
Вопрос: как задать ограничение для конкретных запросов ?
К примеру есть задача: все запросы вида ./$ (оканчивающиеся на "/", за исключением корня) ограничить до 60 запросов/мин для каждого IP. Можно ли с помощью nginx это сделать ?
Ну и было бы не плохо акцентировать на этом моменте внимание в документации.