понедельник, 4 марта 2013 г.

nginx: ограничить количество подключений на сервер

Задача ограничить подключения с 1 айпи - тема весьма популярная, но иногда бывает нужно ограничить всем клиентам.

http://nginx.org/ru/docs/http/ngx_http_limit_conn_module.html#limit_conn

"Допустимо одновременное указание нескольких директив limit_conn, при этом будет срабатывать любое из ограничений. Например, следующая конфигурация ограничивает число соединений с сервером с одного клиентского IP-адреса и в то же время ограничивает общее число соединений с виртуальным хостом:

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;

server {
    ...
    limit_conn perip 10;
    limit_conn perserver 100;
}
Директивы наследуются с предыдущего уровня при условии, что на данном уровне не описаны свои директивы limit_conn."

Только нужно учитывать, что limit_zone применяется только на уровне http. Также приведенный формат - для версии 1.1.8+, для более старых - limit_zone название $переменная размер;

PS
"Здесь в качестве ключа используется IP-адрес клиента. Обратите внимание, что вместо переменной $remote_addr использована переменная $binary_remote_addr. Длина значения переменной $remote_addr может колебаться от 7 до 15 байт, при этом размер хранимого состояния составляет либо 32, либо 64 байта на 32-битных платформах, и всегда 64 байта на 64-битных. Длина значения переменной $binary_remote_addr всегда равна 4 байтам, при этом размер состояния всегда равен 32 байтам на 32-битных платформах и 64 байтам на 64-битных. В зоне размером 1 мегабайт может разместиться около 32 тысяч состояний размером 32 байта, или 16 тысяч состояний размером 64 байта. При переполнении зоны в ответ на последующие запросы сервер будет возвращать ошибку 503 (Service Temporarily Unavailable)."

PS2
Хитрое ограничение с отдачей разных страниц тем, кого ограничивали и кого нет.
http {
...
  limit_req_zone $server_name zone=lreq:10m rate=1r/s;
  
  server ... {
    location = /redir.php {
      error_page 302 /error.html; 
      recursive_error_pages on; 
      return http://ext-site.ru/content;
    }
    location = /error.html {
      internal;
      limit_req zone=lreq burst=1;
      #error_page 503 =302 https://ext-site.ru/sorry.php;
    }
  }
}
!!!При этом файл error.html должен существовать, иначе будет 404! Файл должен быть статическим, поскольку его содержимое будет напрямик отдавать nginx, поэтому если нужна динамика -- снимаем комментарий и получим 302 редирект.
Содержимое файла также будет в ответе, даже если сделали внешний редирект (сняли комментарий), поэтому в файле должен быть или Html код, или файл должен быть просто пустым в случае редиректа.
Это легко проверить, сделав curl site.ru/redir.php в момент перегрузки.
Почему бы не сделать такое через return? Потому что такой метод не сработает.
"Обработка запросов в nginx происходит в разных фазах.
Директивы модуля ngx_http_rewrite_module (директива return в т.ч.)
срабатывают на более ранних фазах, чем модули ngx_http_limit_*."
Ruslan Ermilov, из рассылки nginx.

Комментариев нет:

Отправить комментарий