Re: Улучшение ngx_http_limit_req_module
Maxim Dounin
mdounin на mdounin.ru
Пн Фев 1 18:16:37 UTC 2016
Hello!
On Mon, Feb 01, 2016 at 11:03:16PM +0600, Pavel V. wrote:
[...]
> > Сделать явный отдельный параметр if - можно, но сколько-нибудь
> > принципиальной разницы нет. В то же время не факт, что мы хотим
> > тут усложнять синтаксис.
>
> Если условия везде одинаковые, то они задаются map-ом, пусть и чуть более
> громоздким конфигом, чем с параметром if. Принципиальная разница появляется
> только в том, что в разные директивы limit_req в параметр if можно задать разные
> условия.
Если условия вдруг разные - то они, при желании, аналогично
задаются чуть более сложным map'ом. Так что это, в общем-то, в
первую очередь вопрос синтаксиса. Принципиально разницы тут не
прослеживается.
Плюсы, которые видны: чуть проще синтаксис (не всякий пользователь
nginx'а готов писать логику с использованием map'ов), и можно
менять burst/nodelay без добавления поддержки переменных в
соответствующих параметрах. Но я совершенно не уверен в
востребованности всего этого.
[...]
> > Если хочется программировать - стоит подумать о том, чтобы
> > вытащить результаты ограничений в переменные, и дальше
> > программировать с помощью директив rewrite-модуля же.
>
> Можно увидеть пример конфигурации, как она могла бы быть заданной
> таким способом?
> Например, для двух условий: $is_spider и $is_vip.
> Если $is_vip - ограничений вообще нет, если $is_spider - одна зона
> (ограничения), иначе вторая (другие ограничения)?
Вот конкретно для такой задачи - всё решается существующими
механизмами, ничего изобретать не надо. Как-то так:
map $is_vip$is_spider $user {
10 "";
11 "";
01 "";
00 $binary_remote_addr;
}
map $is_vip$is_spider $spider {
10 "";
11 "";
01 $binary_remote_addr;
00 "";
}
limit_req_zone $spider zone=spider:1m rate=1r/m;
limit_req_zone $user zone=user:1m rate=10r/m;
limit_req zone=spider;
limit_req zone=user;
Что до использования переменных и программирования, то оно может
быть нужно в случаях сложной логики - e.g., если мы хотим
отвергать запрос только в случае срабатывания нескольких
ограничений одновременно. Или хотим даже при срабатывании
одного ограничения увеличивать остальные счётчики.
Как это должно выглядеть - надо думать, вероятно экспротировать
счётчики в каких-то переменных, задаваемых через limit_req_zone, и
строить логику на обращениях к ним, как-то так:
limit_req_zone $binary_remote_addr zone=addr:1m rate=1r/m
variable=$limit_addr_count;
limit_req_zone $server_name zone=host:1m rate=1r/m
variable=$limit_host_count;
set $limit $limit_addr_count:$limit_host_count;
if ($limit ~ "\d\d+:\d\d+") {
return 401;
}
Но, опять же, не факт, что мы вообще что-то подобное хотим делать.
> >> Возможность безусловного отключения ограничений, наследованных с
> >> предыдущего уровня.
>
> > Это уже записано в TODO, возможность отказаться от унаследованных
> > ограничений, безусловно, нужна.
>
> >> Из планируемых вещей также есть мысли по поводу добавления параметра "dry-run".
>
> > Да, сделать возможность проверки ограничений без их реального
> > применения - тоже уже в TODO.
>
> Судя по всему, это должен быть параметр директивы limit_req_zone. Как он зовется
> в вашем TODO?
Скорее, отдельная директива, аналогично limit_req_status /
limit_req_log_level. В TODO значится:
Dry-run for limit_req. See also:
http://mailman.nginx.org/pipermail/nginx/2016-January/049648.html
> "Patches are welcome"? По этим двум пунктам они достаточно тривиальны.
Да. На всякий случай оставлю эту ссылку здесь:
http://nginx.org/ru/docs/contributing_changes.html
--
Maxim Dounin
http://nginx.org/
Подробная информация о списке рассылки nginx-ru