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