Re: Реализация multiple limit_req

Gena Makhomed gmm на csdoc.com
Вс Дек 18 20:00:51 UTC 2011


On 14.12.2011 18:24, Maxim Dounin wrote:

> E.g. типичная ситуация для хостинга, когда лимиты хочется на
> каждый $host (чтобы один атакуемый сайт не мог съесть все
> ресурсы), и на ip (чтобы с одного ip-адреса, вздремнув на ^R,
> нельзя было съесть все ресурсы):
>
>     limit_req<per-host>;
>     limit_req<per-ip>;
>
> Если атакуют $host, то всё хорошо.
>
> Если ^R, то проблема: легко "выедается" лимит на $host (хотя
> запросы реально не обслуживаются), и тем самым нужный хост
> фактически блокируется.
>
> В данном конкретном случае - проблема легко решается сменой
> порядка применения лимитов: сначала per-ip, потом per-host.
>
> Вопрос: есть ли в реальной жизни задачи, где проблема так *не*
> решается?
>
> (С теоретической точки зрения - понятно, что такие задачи есть.
> Интересуют сколько-нибудь относящиеся к реальной жизни примеры.)

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

в haproxy есть очень изящное решение:

maxconn <maxconn>
maxqueue <maxqueue>

это почти идеальное решение для выравнивания нагрузки на backend,
так чтобы никакой $host не занял 100% ресурсов backend`а,
и в то же время, чтобы не было 503 ошибок при небольшом
и временном всплеске нагрузки на какой-то $host.
например:

maxconn 1
maxqueue 128

или

maxconn 1
maxqueue 1024

с помощью

limit_req<per-host>;

такого плавного выравнивания нагрузки получить нельзя,
потому что backend или будет перегружен "тяжелыми" запросами,
при слишком высоких лимитах или backend будет простаивать,
а клиентов будет отсекать ограничение limit_req<per-host>;
если на $host идет большое количество "легких" запросов
а лимиты limit_req<per-host>; стоят слишком низкие.

более идеальное решение - равномерно распределять запросы
к backend`у из разных очередей, если количество виртуальных
хостов больше, чем количество worker-процессов у backend`а.
т.е. очереди proxy_maxconn/proxy_maxqueue на один и тот же
backend из разных server{ ... } обрабатываются в виде
round-robin и first_in-first_out с учетом лимита maxconn.
(для случая если всплеск нагрузки идет на все/многие $host`ы)

совсем идеальное решение - возможность управлять приоритетами
очередей, примерно как в http://lartc.org/lartc.html

или что-то похожее на maxconn / maxqueue между nginx
и backend`ом можно сделать средствами netfilter,
если подключение к backend`у идет по tcp/ip ?

пока что народ ставит nginx <-> haproxy <-> backend

а если подключение к backend`у идет через

proxy_pass http://unix:/path/to/backend.socket:/uri/;
uwsgi_pass unix:/var/run/example.com.sock;

и т.п. ?

-- 
Best regards,
  Gena



Подробная информация о списке рассылки nginx-ru