Практические советы по тюнингу веб-сервера NGINX

Обновлено Обновлено: Опубликовано Опубликовано:

Тематические термины: NGINXFreeBSDCentOSLinux.

Советы и примеры по тюнингу NGINX показаны на базе операционных систем FreeBSD, CentOS и Ubuntu.

Прежде чем начать

Убедимся, что мы готовы перейти в оптимизации. Для этого мы должны обладать достаточными правами и понимать, какие нам нужны конфигурационные файлы веб-сервера.

Права root

Предполагается, что все действия мы будем выполнять от суперпользователя, поэтому для удобства, сразу зайдем в систему под ним:

$ su

Конфигурационный файл nginx

Путь до конфигурационного файла nginx зависит от его способа установки и типа операционной системы.

а) во FreeBSD:

vi /usr/local/etc/nginx.conf

б) в Linux:

vi /etc/nginx/nginx.conf

* для собранного из исходников nginx путь может быть разным, например, /etc/nginx/conf/nginx.conf.

Прежде чем начать, определите путь до конфигурационного файла в вашей системе.

Настройка NGINX

Начнем тюнинг nginx, настроив несколько основных параметров, отвечающих за количество обрабатываемых соединений и сроки их поддержания.

Пример настроенного nginx.conf:

worker_processes  auto;
worker_priority     -2;
...
events {
    worker_connections  2048;
    multi_accept on;
}
...
http {
    ...
    keepalive_timeout          45;
    reset_timedout_connection  on;
    client_body_timeout        35;
    send_timeout               30;
    ...
}

worker_processes, по умолчанию 1. Определяет количество рабочих процессов. Обычно, выставляют равному числу ядер, но в новых версиях nginx его лучше устанавливать в auto.

worker_priorityпо умолчанию 0. Задает приоритет рабочих процессов от -20 до 20 (отрицательное число означает более высокий приоритет). Ему стоит отдать чуть больший приоритет (-2). Это нужно для того, чтобы при сильной нагрузке на скриптовую часть сайта или DDoS атаке, nginx продолжал обрабатывать запросы и отдавать статику.

worker_connections, по умолчанию 512. Устанавливает максимальное количество соединений одного рабочего процесса, то есть nginx будет обрабатывать worker_processes * worker_connections, остальные запросы ставить в очередь. Следует выбирать значения от 1024 до 4096. В нашем примере — 2048.

multi_accept, по умолчанию off. Если включен, позволяет принимать максимально возможное количество соединений. Иначе, процесс nginx за один раз будет принимать только одно новое соединение.

keepalive_timeout, по умолчанию 75Отвечает за максимальное время поддержания keepalive-соединения, в случае, если пользователь по нему ничего не запрашивает. Для современных систем, стоит выставить от 30 до 50. В нашем случае 45.

reset_timedout_connection, по умолчанию offЕсли клиент перестал читать страницу, Nginx будет сбрасывать соединение с ним.

client_body_timeout, по умолчанию 60. Будет ждать выставленное количество секунд тело запроса от клиента, после чего сбросит соединение. Значение по умолчанию слишком высокое и мы его снизили до 35.

send_timeout, по умолчанию 60. Если клиент прекратит чтение ответа, Nginx подождет выставленное количество секунд и сбросит соединение.

Оптимизация работы с файлами

Пример настроенного nginx.conf:

http {
  ...
    sendfile      on;
    aio           on;
    tcp_nopush    on;

    open_file_cache max=100000 inactive=20s;
    open_file_cache_valid 45s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
    ...
}

sendfile позволяет использовать более совершенный системный вызов, который обеспечивает прямую передачу файла (без системных вызовов read + write).

aio включает использование асинхронного обращения к файлам, что избавит от очередей запросов.

tcp_nopush позволит передавать заголовок ответа и начало файла в одном пакете.

open_file_cache по умолчанию выключена. Задает настройку для кэширования информации о файлах, с которыми работает nginx. По умолчанию, выключено.

open_file_cache_valid задает время, через которое веб-сервер будет проверять актуальность данных. По умолчанию, 60 секунд.

open_file_cache_min_uses задает минимальное число обращений к файлу, чтобы дескриптор файла оставался открытым в кэше.

open_file_cache_errors включает или выключает кэширование ошибок.

Также вы можете найти инструкции по тюнингу, где говорится об опции tcp_nodelay. Ее менять не нужно, так как по умолчанию она уже включена.

Для того, чтобы aio заработал в FreeBSD, необходимо выполнить следующее.

Подгружаем модуль aio в ядро системы:

kldload aio

Для автоматической подгрузки модуля во время включения нашего веб-сервера:

ee /boot/loader.conf

...
aio_load="YES"

Открываем на редактирование файл с настройками лимитов для пользователей и групп:

vi /etc/security/limits.conf

Добавим строки:

...
nginx           hard    nofile          199680
nginx           soft    nofile          65535
...

* в данном примере мы задаем ограничение для пользователя nginx на количество открытых файлов.

Зададим ограничение для текущей загрузки:

ulimit -n 65536

Логирование

Если отключить логирование всех подключений к nginx, можно немного снизить нагрузку на дисковую систему. Но при этом стоит оставить логирование критических ошибок.

Пример настроенного nginx.conf:

error_log /var/log/nginx-error.log crit;

http {
    ...
    access_log off;
    ...

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

Сжатие

Это один из самых эффективных методов ускорить ответ от вашего веб-сервера nginx.

Пример настроенного nginx.conf:

http {
    ...
    gzip                on;
    gzip_min_length     1000;
    gzip_proxied        expired no-cache no-store private auth;
    gzip_types          text/plain text/css text/javascript application/javascript application/x-javascript text/xml application/xml application/xml+rss application/json;
    gzip_disable        "msie6";
    ...

gzip включает сжатие.

gzip_min_length устанавливает минимальную длину ответов, для которых будет применяться сжатие. По умолчанию 20, но имеет смысл поставить больше, так как постоянное сжатие приведет к повышению нагрузки на процессоры сервера и клиента.

gzip_proxied перечисляет параметры проксированных запросов, для которых будет разрешено сжатие.

gzip_types по умолчанию включено сжатие для ответов типа текст. В данном параметре можно перечислить все необходимые типы ответов.

gzip_disable запрещает для перечисленных параметров заголовка User-Agent сжатие. В данном примере для Internet Explorer 6 сжатие применяться не будет (данный браузер не умеет принимать сжатые ответы).

Настройка метода select

В Linux и FreeBSD используются свои методы обработки соединений. На данный момент наиболее эффективными являются epoll (Linux) и kqueue (FreeBSD).

а) Пример nginx.conf для FreeBSD:

events {
    ...
    use kqueue;
}

б) Пример nginx.conf для Linux:

events {
    ...
    use epoll;
}

Обработка статики и ее кэширование

NGINX умеет сам отдавать статические данные, не заставляя сервер backend этим заниматься. В настройке каждого сайта (секция server добавляем):

    server {
        ...
        location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js|svg|woff2|ttf)$ {
            root /var/www/site
            expires modified +1w;
        }
    }

* в данном примере для перечисленных статических файлов NGINX сам будет сам их отдавать. Сами файлы мы будем искать в каталоге /var/www/site, однако, опцию root можно и не задавать в location, если мы ее задали уровнем выше (в секции server). Также мы задали время кэширования для файлов, равное 1 недели от момента их модификации.

Пример настроенного файла конфигурации

В итоге, у нас получиться что-то на подобие:

worker_processes  auto;
worker_priority     -2;

events {
    worker_connections  2048;
    multi_accept on;
    use epoll;
}

http {
    include mime.types;
    default_type application/octet-stream;

    keepalive_timeout          45;
    reset_timedout_connection  on;
    client_body_timeout        35;
    send_timeout               30;

    sendfile      on;
    aio           on;
    tcp_nopush    on;

    open_file_cache max=100000 inactive=20s;
    open_file_cache_valid 45s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    access_log off;
    error_log /var/log/nginx-error.log crit;

    gzip                on;
    gzip_min_length     1000;
    gzip_proxied        expired no-cache no-store private auth;
    gzip_types          text/plain text/css text/javascript application/javascript application/x-javascript text/xml application/xml application/xml+rss application/json;
    gzip_disable        "msie6";

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

* обратите внимание, что в Linux в events use задается epoll, во FreeBSD — kqueue.

Проверка корректности настроек и их применение

После внесения всех настроек необходимо проверить их корректность командой:

nginx -t

Мы должны получить что-то на подобие:

...
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Теперь можно применить настройки командой:

nginx -s reload

Кэширование на стороне сервера

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

Подробнее про данную настройку рассказано в инструкции Кэширование ответа от backend с помощью NGINX.

Установка NGINX

Если же нам нужно выжать из сервера максимум производительности установка nginx из пакетов или портов не подходит. Лучше всего выполнять сборку и установку из исходников — таким образом, мы можем отказаться от части функций, которые нам не нужны.

Скачайте последнюю стабильную версию nginx (актуальную ссылку можно посмотреть по адресу http://nginx.org/ru/download.html):

Копируем ссылку на последнюю стабильную версию NGINX

... и с помощью данной ссылки скачиваем исходник.

а) во FreeBSD:

fetch http://nginx.org/download/nginx-1.16.1.tar.gz

б) в Linux:

wget http://nginx.org/download/nginx-1.16.1.tar.gz

* На момент обновления статьи актуальная версия nginx — 1.16.1.

Распакуйте скачанный архив и сразу удалите его, чтобы не мешался:

tar -xvf nginx-*.tar.gz && \rm nginx-*.tar.gz

И перейдите в распакованную директорию:

cd nginx-*

Сконфигурируйте исходники для установки:

а) для FreeBSD:

Сначала устанавливаем пакеты, необходимые для сборки:

pkg install pcre

Приступаем к конфигурированию:

./configure \
    --prefix=/usr/local/etc/nginx \
    --with-cc-opt='-I /usr/local/include' \
    --with-ld-opt='-L /usr/local/lib' \
    --conf-path=/usr/local/etc/nginx/nginx.conf \
    --sbin-path=/usr/local/sbin/nginx \
    --pid-path=/var/run/nginx.pid \
    --error-log-path=/var/log/nginx-error.log \
    --user=www \
    --group=www \
    --http-client-body-temp-path=/var/tmp/nginx/client_body_temp \
    --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp \
    --http-proxy-temp-path=/var/tmp/nginx/proxy_temp \
    --http-scgi-temp-path=/var/tmp/nginx/scgi_temp \
    --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi_temp \
    --http-log-path=/var/log/nginx-access.log \
    --with-http_ssl_module \
    --with-file-aio \
    --with-pcre \
    --with-http_stub_status_module \
    --without-http_charset_module \
    --without-http_ssi_module \
    --without-http_userid_module \
    --without-http_autoindex_module \
    --without-http_geo_module \
    --without-http_map_module \
    --without-http_split_clients_module \
    --without-http_referer_module \
    --without-http_empty_gif_module \
    --without-http_browser_module \
    --without-http_upstream_hash_module \
    --without-http_upstream_ip_hash_module \
    --without-http_upstream_least_conn_module \
    --without-http_upstream_keepalive_module \
    --without-mail_pop3_module \
    --without-mail_imap_module \
    --without-mail_smtp_module

а) для CentOS:

Сначала устанавливаем пакеты, необходимые для сборки:

yum install gcc pcre-devel openssl-devel make

Приступаем к конфигурированию:

./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --pid-path=/var/run/nginx.pid \
    --error-log-path=/var/log/nginx/error.log \
    --lock-path=/var/run/nginx.lock \
    --user=nginx \
    --group=nginx \
    --http-log-path=/var/log/nginx-access.log \
    --with-http_ssl_module \
    --with-file-aio \
    --with-pcre \
    --with-http_stub_status_module \
    --without-http_charset_module \
    --without-http_ssi_module \
    --without-http_userid_module \
    --without-http_autoindex_module \
    --without-http_geo_module \
    --without-http_map_module \
    --without-http_split_clients_module \
    --without-http_referer_module \
    --without-http_empty_gif_module \
    --without-http_browser_module \
    --without-http_upstream_hash_module \
    --without-http_upstream_ip_hash_module \
    --without-http_upstream_least_conn_module \
    --without-http_upstream_keepalive_module \
    --without-mail_pop3_module \
    --without-mail_imap_module \
    --without-mail_smtp_module

* Данный список опций подойдет для большинства серверов, но не помешает узнать о всех возможностях при помощи команды ./configure --help

Теперь запустите сборку дистрибутива из исходника:

make

И установите nginx:

make install

Теперь можно запустить и проверить наш веб-сервер.

а) во FreeBSD необходимо разрешить запуск демона nginx:

echo 'nginx_enable="YES"' >> /etc/rc.conf

service nginx start

б) в CentOS действий больше.

Создаем учетную запись nginx и в качестве владельца каталога для его настроек:

useradd nginx

chown -R nginx:nginx /etc/nginx

Создаем юнит для systemd:

vi /etc/systemd/system/nginx.service

[Unit]
Description=nginx - high performance web server
Documentation=https://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/conf/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
Restart=on-failure

[Install]
WantedBy=multi-user.target

Применяем изменения в systemd:

systemctl daemon-reload

Разрешаем автозапуск сервиса и стартуем его:

systemctl enable nginx

systemctl start nginx

Читайте также

Другие инструкции, близкие по теме:

1. Ограничения и лимиты в NGINX.

2. Анализ нагрузки на веб-сервер Linux.

3. Установка и настройка модуля PageSpeed.

4. Балансировка нагрузки с помощью NGINX.

5. Кэширование ответа от backend с помощью NGINX.

# Linux # NGINX # UNIX # Интернет # Настройки # Серверы
Дмитрий Моск — частный мастер
Была ли полезна вам эта инструкция?

Да            Нет