Nginx и limit_req_zone

M
На сайте с 11.01.2006
Offline
153
2637

Добрый день. Нуждаюсь в совете.

Имеется - VPS - 1 ядро CPU, 1ГБ ОЗУ, 20 Гб SSD диск. Посещаемость сайтов - 10-15 уников в сутки.

Сегодня в очередной раз пришла смс от ping-admin о недоступности сервера. Упал Mysql - в связи с созданием огромного количества процессов apache.

Что происходит - по логам nginx - на сервер приходит какой-то робот, и начинает усиленно качать все страницы сайта. В секунду получается 40-60 запросов к apache. Из-за нехватки памяти - убивается Mysql.

Решил попробовать ограничить кол-во запросов с одного IP. В nginx есть специальный модуль - ngx_http_limit_req_module

Почитал мануал, в принципе все понятно, кроме нескольких моментов.

Дописав в секцию http конфига nginx следующий фрагмент:

limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

limit_req zone=one burst=15;

limit_req_status 503;

Вопрос №1 и самый важный - правильно ли я мыслю, выбрав такой вариант борьбы с ботами?

Вопрос №2 - насколько я понимаю - ограничение сработает для всех типов запрашиваемых документов (в т.ч. и статика). Как можно применить это правило только для динамического контента?

Вопрос №3 - достаточно ли написать фрагмент вышеуказанного кода в секцию http, и не дописывать в каждую секцию server (на VPS крутится около 20 сайтов)?

Буду благодарен за любые советы и подсказки.

G-and-Y
На сайте с 29.06.2013
Offline
182
#1

Я борюсь пока так /ru/forum/comment/13743376

Думаю поставить это http://habrahabr.ru/post/139931/

Абузо-устойчивые впс ( http://vps-hosting.lv/?p=13408 )
UF
На сайте с 25.12.2011
Offline
28
#2

Сколько ОЗУ на сервере?

M
На сайте с 11.01.2006
Offline
153
#3
UnFeeLing:
Сколько ОЗУ на сервере?

Прошу прощения, поправил первый пост...

на сервере 1 Гб ОЗУ

S
На сайте с 02.05.2014
Offline
61
#4
Magistr:
Вопрос №2 - насколько я понимаю - ограничение сработает для всех типов запрашиваемых документов (в т.ч. и статика). Как можно применить это правило только для динамического контента?

В вашем примере - будет распространяться и и на статику.

Если нужно тормознуть только вызов апача, то для этого в секцию http пропишите только это:

limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

А в секцию location / каждого виртуальго хоста добавить это:

location / {

limit_req zone=one burst=15;
............................
}

И тогда это правило будет применяться только для динамики в указанных виртуальных хостах.

UF
На сайте с 25.12.2011
Offline
28
#5
Magistr:
Прошу прощения, поправил первый пост...
на сервере 1 Гб ОЗУ

Что за скрипт? ОС? покажите кто-что грузит больше всего при нагрузках бд. Таблицы InnoDB или MyISAM?

top

K5
На сайте с 21.07.2010
Offline
209
#6

ТС может все же не давать серверу плодить апачи чрезмерно много, тогда и база отваливаться не будет ;)

аська 45два48499два записки на работе (http://memoryhigh.ru) помогу с сайтом, удалю вирусы, настрою впс -> отзывы ТУТ (/ru/forum/836248) и ТАМ (http://www.maultalk.com/topic140187.html) !!!всегда проверяйте данные людей, которые сами пишут вам в аську или скайп!!!
M
На сайте с 11.01.2006
Offline
153
#7
Sujcnm:
В вашем примере - будет распространяться и и на статику.
Если нужно тормознуть только вызов апача, то для этого в секцию http пропишите только это:
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

А в секцию location / каждого виртуальго хоста добавить это:
location / {

limit_req zone=one burst=15;
............................
}

И тогда это правило будет применяться только для динамики в указанных виртуальных хостах.

Спасибо за ответ. У меня возник только 1 вопрос - обязательно ли для каждой локации прописывать вручную

limit_req zone=one burst=15

или достаточно прописать это в секцию - http? Понимаю, что маловероятно, но как говорится, а вдруг? :)

UnFeeLing:
Что за скрипт? ОС? покажите кто-что грузит больше всего при нагрузках бд. Таблицы InnoDB или MyISAM?

top

Без шаловливого робота ВПС-ка держит нагрузку на отлично. ЛА не выше 0,1. Тут проблема именно в создании огромного кол-ва запросов от робота за единицу времени - в моем случае это 40-60 запросов/сек, на протяжении 30-40 секунд, чего достаточно, чтобы положить apache :(

kgtu5:
ТС может все же не давать серверу плодить апачи чрезмерно много, тогда и база отваливаться не будет ;)

Я как бы и спрашиваю совета - верно ли мое мышление, либо нужно плясать не в сторону настройки nginx, а в сторону к-ва дочерних процессов апача. К сожалению, опыта у меня не так много в этом вопросе.

UF
На сайте с 25.12.2011
Offline
28
#8

http://nginx.org/ru/docs/http/ngx_http_limit_req_module.html#limit_req_zone

nano /etc/nginx/nginx.conf

# Увеличиваем максимальное количество используемых файлов

worker_rlimit_nofile 8192;
## Число рабочих процессов, рекомендуется ставить по количеству ядер
worker_processes 1;
# Уменьшает число системных вызовов gettimeofday(), что приводит к увеличению производительности
timer_resolution 100ms;
# Директива задаёт приоритет рабочих процессов от -20 до 20 (отрицательное число означает более высокий приоритет).
worker_priority -5;
events {
# Увеличиваем максимальное количество соединений
worker_connections 2048;
# Использовать эффективный метод epoll для обработки соединений
use epoll;
}
http {
# Включить sendfile(). Использование sendfile() экономит системные вызовы, уменьшает число копирований данных
sendfile on;
output_buffers 2 64k;

gzip on;
gzip_min_length 1100;
gzip_buffers 64 8k;
gzip_comp_level 3;
gzip_http_version 1.1;
gzip_proxied any;
gzip_types text/plain application/xml application/x-javascript text/css;
# Отключаем таймаут на закрытие keep-alive соединений
keepalive_timeout 0;
# Не отдавать версию nginx в заголовке ответа
server_tokens off;
# Сбрасывать соединение по таймауту
reset_timedout_connection on;
#Директива описывает зону, в которой хранятся состояния сессий. Значения сессий определяется заданной переменной.
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

}

server {
listen 80 default;
server_name localhost;

access_log /var/log/nginx/localhost.access.log;

location / {
root /var/www/;
index index.html index.htm index.php;
open_file_cache max=1024 inactive=600s;
open_file_cache_valid 2000s;
open_file_cache_min_uses 1;
open_file_cache_errors on;
}
location ~ \.php$ {
limit_req zone=one burst=5;
fastcgi_pass unix://tmp/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header "Cache-Control";
}
location ~ /\.ht {
deny all;
}
expires max; # Внимание!!! Эта строка expires необходима!
add_header Last-Modified $sent_http_Expires;
}


---------- Добавлено 08.06.2015 в 17:11 ----------

nano /etc/apache2/apache2.conf

Проставить

StartServers 5 

MinSpareServers 5
MaxSpareServers 5
MaxClients 30
MaxRequestsPerChild 1000

MaxClients

Директива MaxClients устанавливает максимальное количество параллельных запросов, которые будет поддерживать сервер. Apache не будет порождать больше процессов/потоков чем MaxClients. Значение MaxClient не долно быть слишком маленьким (иначе много клиентов останутся необслуженными), но и не стоит устанавливать слишком большое количество - лучше не обслужить часть клиентов чем исчерпать все ресурсы, залезть в своп и умереть под нагрузкой. Хорошим может быть значение MaxClients = количество памяти выделенное под веб-сервер / максимальный размер порожденного процесса или потока. Для статических файлов apache использует около 2-3 Мб на процесс, для динамики (php, cgi) - зависит от скрипта, но обычно около 16-32 Мб.

Вы можете прикинуть примерный размер посмотрев на колонку rss в выводе `ps -ylC httpd --sort:rss`

Если сервер уже обслуживает MaxClients запросов, новые запросы попадут в очередь, размер которой устанавливается с помощью директивы ListenBacklog.

MinSpareServers, MaxSpareServers, и StartServers

Т.к. создание потока, и особенно процесса - дорогая операция, apache создает их заранее. Директивы MaxSpareServers и MinSpareServers устанавливают как много процессов/потоков должны ожидать в готовности принять запрос (максимум и минимум). Если значение MinSpareServers слишком маленькое и неожиданно приходит много запросов, apache вынужден будет создавать много новых процессов/потоков, что создаст дополнительную нагрузку в этой стрессовой ситуации. С другой стороны, если MaxSpareServers слишком велико, apache будет сильно нагружать систему этими процессами, даже если количество клиентов минимально.

Постарайтесь установить такие MinSpareServers и MaxSpareServers, чтобы apache не создавал более 4 процессов/потоков в секунду. Если он создаст более 4, в ErrorLog будет помещено сообщение об этом. Это - сигнал того что MinSpareServers слишком мало.

MaxRequestsPerChild

Директива MaxRequestsPerChild устанавливает сколько запросов может обработать один дочерний процесс/поток прежде чем он будет завершен. По умолчанию значение этой директивы установлено в 0, что означает что однажды созданный процесс/поток не будет завершен никогда (ну кроме случаев остановки сервера или краха этого процесса/потока). Рекомендую установить MaxRequestsPerChild равное какому-нибудь достаточно большому числу (несколько тысяч). Это не создаст излишней нагрузки, связаной с тем что apache будет вынужден создавать новые дочерние процессы, в то же время это поможет избавиться от проблем с утечкой памяти в дочерних процессах (что очень возможно например если вы используете нестабильную версию php).

KeepAlive и KeepAliveTimeout

KeepAlive позволяет делать несколько запросов в одном TCP-подключении. Это особенно полезно для html-страниц с большим количеством изображений. Если KeepAlive установлен в Off, то для самой страницы и для каждого изображения будет создано отдельное подключение (которое нужно будет обработать master-процессу), что плохо и для сервера и для клиента. Так что для подобных случаев рекомендуется устанавливать KeepAlive в On. Для других применений (например для download-сервера) KeepAlive может быть бесполезен и даже вреден, т.к. при включенном KeepAlive сервер закрывает соединение не сразу, а ждет KeepAliveTimeout секунд нового запроса. Для того чтобы процессы не висели слишком долго в бесполезном ожидании, устанавливайте KeepAliveTimeout достаточно малым, около 5-10 секунд обычно достаточно.

Вообще обсуждалось по-моему где-то уже ;)

S
На сайте с 02.05.2014
Offline
61
#9
Magistr:
или достаточно прописать это в секцию - http?

Если только в секцию http, то эта директива будет действовать и на статику. А ограничение в 15 может задеть нормальных юзеров с быстрым каналом(если много картинок, стилей и т.д.).

А если за одним ip сидит несколько человек, то кому то не повезет :)

Но если прописать в location / для каждого защищаемого хоста, то действовать будет на динамический контент и 15 запросов в секунду это более чем достаточно.

итог:

т.е. http -глобально на все, location / - только для конкретного локейшина.

ps

И еще умерьте аппетиты апач, как посоветовал kgtu5

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий