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