NGINX: настройка сервера и PHP-FPM

Автор: | 02/10/2014
 

nginx_logo

Настройки NGINX

Основные параметры конфигурации

Первым запускается “мастер” процесс /usr/sbin/nginx, который открывает необходимые порты и запускает количество worker_processes, указанное в конфигурации от имени пользователя, который указан там же. Кроме того, он записывает свой PID в файл /var/run/nginx.pid:

# ps aux | grep "nginx: master" | grep -v grep
root      7599  0.0  0.0  47488   556 ?        Ss   13:47   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
# cat /var/run/nginx.pid
7599

Таким образом, “ветвь процессов” NGINX выглядит как: master_process > worker_processes * N, где N – количество worker_processes в конфигурации:

# ps aux | grep nginx | grep -v grep
root      7599  0.0  0.0  47488   556 ?        Ss   13:47   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     7601  0.0  0.2  48700  2632 ?        S    13:47   0:05 nginx: worker process
# cat /etc/nginx/nginx.conf | grep worker
worker_processes  1;
    worker_connections  1024;

Worker-ы не являются multi-threaded процессами, поэтому они не могут перераспределять потоки, обрабатывающие подключения по разным процессорам.

worker_processes можно установить либо по количеству ядер/процессоров, либо в auto – тогда NGINX попытается сам определить оптимальное значение:

worker_processes auto;

worker_connection – количество соединений, которые будут обрабатывать worker_processes (т.е. max_connection для вашего NGINX будет worker_connections * worker_processes):

Так же учитываются соединения с “локальными” ресурсами – например, PHP-FPM или Apache HTTP.

По соображениям безопасности – можно отключить server_tokens:

server_tokens off;

В таком случае – NGINX не будет передавать свою версию в сообщениях об ошибках и в поле “Server” заголовка ответа.

client_max_body_size – если у вас возникает ошибка “Request Entity Too Large” (413) – увеличьте значение client_max_body_size, т.к. по умолчанию оно только 1 МБ:

client_max_body_size 20m;

Для ускорения загрузки файлов – можно увеличить client_body_buffer_size (по-умолчанию 16KB в х64):

client_body_buffer_size 128k;

Подробнее – тут>>>.

Кеширование статических файлов браузерами

Что бы браузеры хранили файлы в своём кеше, вместо загрузки их с сервера каждый раз, можно передать HTTP-заголовок Expires:

location ~*  .(jpg|jpeg|png|gif|ico|css|js)$ {
   expires 365d;
}

Подробнее – тут>>>.

Запрет доступа к файлам

Что бы запретить доступ к файлам, начинающимся с точки – добавьте:

location ~ /. {
    deny all;
}

Например, что бы запретить доступ к .htaccess и .htpasswd:

location ~ /.ht {
    deny all;
}

Запретить доступ к файлам php в каталогах uploads и files:

        location ~* /(?:uploads|files)/.*.php$ {
                deny all;
        }

Настройки для PHP-FPM

Перезапуск потоков

emergency_restart_threshold – указывает количество процессов-потомков (или “дочерних процессов”, кому как нравится) PHP-FPM, которые в случае получения сигналов SIGSEGV или SIGBUS за промежуток времени, заданный в emergency_restart_interval вызовут перезагрузку PHP-FPM.

Например:

emergency_restart_threshold = 10
emergency_restart_interval = 1m

Если 10 дочерних процессов PHP-FPM в течении 1 минуты получат ошибку SIGSEGV (Segmentation fault) или SIGBUS (Bus error) – то PHP-FPM будет перезапущен.

По-умолчанию отключено.

process_control_timeout – задаёт интервал в секундах, в течении которого потомки ждут ответа от PHP-FPM-мастера. Если ответа не будет – процесс будет пересоздан. По-умолчанию отключено:

process_control_timeout = 10

Эти настройки необходимо добавлять в основной файл настроек PHP-FPM , в CentOS это /etc/php-fpm.conf.

Настройки PHP-FPM Process Manager (pm)

Сам PM (pm)  может запускаться по-разному:

  • static – фиксированное число дочерних процессов (pm.max_children).
  • ondemand – число процессов, порождающихся по требованию (когда появляются запросы, в отличии от опции dynamic, когда стартует определенное количество процессов, равное pm.start_servers, вместе с запуском службы.
  • dynamic – динамически изменяющееся число дочерних процессов, задается на основании следующих директив: pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers.

Например:

pm dynamic

pm.start_servers – количество дочерних процессов, которые будет создавать PM при старте PHP-FMP (только если pm dynamic);
pm.min_spare_servers – количество процессов, которые должны оставаться в idle, как “запасные”, ожидая задач на выполнение, если количество меньше – будут созданы новые;
pm.max_spare_servers – наоборот, максимальное количество процессов, которые должны оставаться в idle,если количество больше – некоторые потомки будут уничтожены;
pm.max_requests – количество запросов процесса, после которого он будет пересоздан, полезно для предотвращения утечек памяти (memory-leak);
pm.max_children – максимальное количество процессов-потомков, которое будет создано PM.

Оптимальное значение для max_children приблизительно можно подсчитать так:

запустить NGINX; выполнить обращение к самой “тяжёлой” странице PHP; открыть top или посмотреть в ps количество занятой RSS памяти, например:

# while true; do curl http://rtfm.co.ua &> /dev/null; sleep 1; done

теперь – получаем значение занятой памяти:

# ps aux | grep -E 'rtfm.*php-fpm' | head -n 1 | awk '{print $6}'
54796

53 МБ на один процесс.

Далее, предположим вы готовы выделить под PHP-скрипты 1 гигабайт памяти, тогда:

1024 МБ / 53 МБ = 19 pm.max_children.

Это, конечно, очень неточное решение.

К примеру, реально занятая память PHP-FPM процессами на самом деле будет меньше, например из данных ps_mem:

571.4 MiB +   8.1 MiB = 579.5 MiB       php-fpm (23)

Т.е. 25 МБ в среднем на каждый.

Некоторые полезные опции PHP-FPM

security.limit_extensions – ограничение типов файлов (по расширению), которые будут обрабатываться PHP-FPM.

Значение по-умолчанию – .php.

chroot и chdir – “корневая” директория для php-скриптов, и директория, с которой будут начинать выполнение скрипты. Хорошо описаны тут>>>.

Использование unix-сокетов вместо TCP-портов – хорошо описано тут>>>, но не забудьте добавить listen.owner, listen.group и listen.mode.

Указать отдельный лог-файл для ошибок PHP:

php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on

Записывать “медленные запросы” PHP можно указав лог в строке:

slowlog = /var/log/nginx/rtfm.co.ua-slow.log

А задать время, по истечении которого запрос будет считать “медленным” – с помощью:

request_slowlog_timeout = 5

Убить процесс, который выполняется больше 300 секунд:

request_terminate_timeout = 300s

Надеюсь, будет время добавить отдельный пост по настройке производительности и безопасности NGINX/PHP-FPM.

Ссылки по теме:

http://php.net
http://codex.wordpress.org
http://wiki.nginx.org/Main
http://www.if-not-true-then-false.com
https://stephentanner.com
http://help.ubuntu.ru
http://ae.koroglu.org
http://myjeeva.com