среда, 2 июля 2014 г.

Оптимизация nginx

Третья заметка из цикла оптимизации веб-сервера на базе apache+nginx+mysql+php.

Перед изменением конфигурационного файла необходимо сделать его резервную копию:
# cp nginx.conf nginx.conf.bak

Для замера производительности до оптимизации и после можно использовать этот сервис: developers.google.com/speed/pagespeed/insights

Настройки nginx находятся в основном конфиге nginx /etc/nginx/nginx.conf, поэтому большая часть настроек будет производиться в этом файле:
# vim /etc/nginx/nginx.conf
# Максимальное количество одновременных соединений ~=числу ядер процессора (значение auto доступно с версии 1.6.2 точно)
worker_processes auto;

events {
# Максимальное число соединений одного рабочего процесса
worker_connections 1024;
# Приём максимально возможного количества соединений
multi_accept on;
# Выбор метода соединений, для linux - epoll
use epoll;
}

http{
# Скрыть версию nginx для безопасности
server_tokens off;

# Защита от Poodle
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# Метод отправки данных, эффективнее чем read+write
sendfile on;
# Отправка заголовков начала и конца в одном пакете
tcp_nodelay on;
tcp_nopush on;

# Максимальное количество файлов в кэше
open_file_cache max=200000 inactive=20s;
# Через какое время будет удалён кэш
open_file_cache_valid 30s;
# Кэширование информации использованной хотя бы 2 раза
open_file_cache_min_uses 2;
# Кэширование информации об отсутствующих файлах
open_file_cache_errors on;

# Сжатие
# Проверка сжатия: http://highloadtools.com/gzip
gzip on;
gzip_disable "msie6";
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;

# Ждать перед закрытием keepalive соединения
keepalive_timeout 5 5;
# Максимальное количествоо keepalive запросов от одного клиента
keepalive_requests 100;

# Если нет ответа от клиента - сброс соединения
reset_timedout_connection on;
# Ждать тело запроса клиента, затем сброс соединения
client_body_timeout 10;
# Таймаут при чтении заголовка запроса клиента
client_header_timeout 10;
# Если клиент пркратит чтение ответа - сброссоединения
send_timeout 10;

# Не принимать запрос размером более 1 Мб (если запрос большой - увеличить значение)
client_max_body_size 2048m;
# Максимальный размер буфера для хранения тела запроса клиента
client_body_buffer_size 1k;
# Максимальный размер буфера для хранения заголовков запроса клиента
client_header_buffer_size 1k;
# Число и размер буферов для чтения большого заголовка запроса клиента
large_client_header_buffers 4 8k;
}


Проверка сжатия и кэширования:
$ curl -I -H 'Accept-Encoding: gzip,deflate' site.ru | grep 'Expires\|Content-Encoding'
Expires: Mon, 08 Feb 2016 12:52:54 GMT
Content-Encoding: gzip

В моём случае с использованием ISPmanager, все виртуальные хосты находятся в /etc/nginx/nginx.conf и к каждому виртуальному хосту инклудится файл /usr/local/ispmgr/etc/nginx.inc и мне достаточно один раз прописать настройки в этом файле.
В случае использования одного хоста, можно просто прописать настройки не в /usr/local/ispmgr/etc/nginx.inc, а в секцию server основного конфига nginx.

# vim /usr/local/ispmgr/etc/nginx.inc
# Ограничение методов обращения к серверу
if ($request_method !~ ^(GET|HEAD|POST)$) {
   return 444;
}

# Блокируем менеджеры загрузки
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
   return 403;
}

# Блокируем некоторые типы ботов
if ($http_user_agent ~* msnbot|scrapbot) {
   return 403;
}

# Блокировка Referrer-спама
if ($http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen)) {
   return 403;
}


Кэширование на стороне клиента.
Если сайтов немного, то в каждую секцию для статики нужно дописать expires max;
# vim /etc/nginx/nginx.conf
server {
   ...
   location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ {
      ...
      root $root_path;
      access_log /var/www/nginx-logs/site isp;
      access_log /var/www/httpd-logs/site.access.log ;
      error_page 404 = @fallback;
      expires max;
   }
}

Но в моём случае этих сайтов много и это затруднительно, поэтому это можно просто сделать так:
# sed -i "s/error_page 404 = \@fallback;/error_page 404 = \@fallback;\n\t\t\texpires max;/g" /etc/nginx/nginx.conf

Теперь нужно сделать так, чтобы при создании новых сайтов в ISPmanager кэширование также было:
# vim /usr/local/ispmgr/etc/server.templ
location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ {
   expires max;
}

Установка значений системных переменных (необходимо для безопасности и уменьшения нагрузки):
# vim /etc/sysctl.conf
# Защита от smurf-атак
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Защита от неправильных ICMP-сообщений
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Защита от SYN-флуда
net.ipv4.tcp_syncookies = 1

# Запрет маршрутизации от источника
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Защита от спуфинга
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Запрет маршрутизации
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Включаем ExecShield
kernel.exec-shield = 1
kernel.randomize_va_space = 1

# Расширение диапазона доступных портов
net.ipv4.ip_local_port_range = 2000 65000

# Увеличение максимального размера TCP-буферов
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1


Проверяем конфиг nginx:
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful


Перезагружаем nginx:
# service nginx restart

Теперь можно замерить производительность после оптимизации.

Полезные ссылки:
Оптимальная настройка nginx: ruhighload.com/index.php/2009/04/24/настройка-nginx
Полный тюнинг движка. Делаем из nginx непробиваемый Web-сервер: xakep.ru/post/54168
ISPManager, nginx и expires: itldc.com/blog/ispmanager-nginx-i-expires

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