Настройка связки nginx + php-fpm

Классической связкой для работы сайтов написанных на php считается apache + mod_php. Так как mod_php по умолчанию требует prefork_mpm, то apache для обработки каждого отдельного соединения создает отдельный процесс, что сильно не экономно с точки зрения расходования оперативной памяти.

Потом появился nginx - легковесный проксирующий веб-сервер и его начали ставить перед apache чтобы он занимался выдачей статики и не беспокоил apache по мелочам. Следующим логичным шагом является выключение из цепочки nginx - apache - php посредника в лице apache, чем мы и займемся.

php-fpm позволяет демонизировать php дабы избежать затрат на запуск процессов (чем страдает CGI) что умеет и FastCGI. Но php-fpm дает также другие полезные возможности:

  • запуск пулов обработчиков от имени заданных пользователей,
  • динамическое управление количеством запущенных обработчиков,
  • возможность перезапуска обработчиков в случае, если с ними что-то не так,
  • ведение лога медленных запросов по аналогии с mysql,
  • страницы статуса и пинга,
  • прочее.

Установка php-fpm в Debian крайне проста:

aptitude install php5-fpm

После чего можно править два конфигурационных файла, которые достаточно хорошо документированы сами по себе, но большое количество слов может также мешать найти за ними суть. Первый (/etc/php5/fpm/php-fpm.conf) позволяет задать общие настройки:

include - из какой директории инклудить дополнительные конфиги,
pid - путь до файла с идентификатором процесса,
error_log - путь до лога ошибок,
syslog.facility - позволяет указать в какой лог писать,
syslog.ident - каким именем помечать записи в системном логе,
log_level - уровень лога от алерта до дебага,

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

emergency_restart_threshold - позволяет задать при каком количестве вылетов процессов с сигналами SIGSEGV или SIGBUS за указанный промежуток времени необходимо мягко перезапустить php-fpm,
emergency_restart_interval - заданный промежуток времени.
process_control_timeout - как долго потомкам ждать от мастера реакции на сигналы,
process.max - максимальное количество процессов для всех пулов,
process.priority - можно указать приоритет мастер-процесса,
daemonize - демонизировать или нет. Может пригодиться для дебага,
rlimit_files - количество доступных для мастер-процесса файловых дескрипторов,
rlimit_core - не осознал,
events.mechanism - в linux однозначно epoll,
systemd_interval - если ваша ос использует systemd, то можно задать периодичность отчетов о состоянии процессов. Будет актуально в Debian 8.

Второй конфиг является базовым для настройки пулов и находится по пути /etc/php5/fpm/pool.d/www.conf. В этом файле можно задать еще больше параметров и все они хорошо документированы в нем. Мы же удалим или переименуем этот файл и создадим свой конфигурационный файл.

Интересно, что в конфиге пула можно использовать имя пула в виде переменной $pool. За счет этого можно создать унифицированный конфигурационный файл и использовать его в качестве основы для новых пулов. Имя пула задается в квадратный скобках и предваряет собой блок параметров. Фактически все пулы можно описать в одном файле, но, кажется, так делать не стоит. Пример конфигурационного файла:

[webpanels]
prefix = /var/www/$pool

user = $pool
group = $pool

listen = /var/run/phpfpm-$pool.sock
listen.owner = $pool
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 16
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4

pm.status_path = /fpmstat

request_slowlog_timeout = 3s
slowlog = /var/www/logs/$pool.slow.log

При необходимости:

access.log = /var/www/logs/$pool.access.log

Разберем параметры:

prefix - позволяет задать путь по умолчанию, который может использоваться в параметрах slowlog, listen, chroot, chdir, php_values, php_admin_values.
user и group - задает владельца и группу запускаемых процессов.
listen - указывает на каком сокете слушать. Поддерживаются как UNIX, так и TCP-сокеты. В случае, если веб-сервер и php-обработчики находятся на одном сервере, то лучше использовать UNIX-сокеты, так как это потенциально быстрее, так как нет оверхеда связанного с генерацией пакетов.
listen.owner, listen.group, listen.mode - позволяют задать параметры доступа к сокету. В качестве владельца указано имя совпадающее с именем пула. Необходимо создать соответствующего пользователя и убедиться, что для него нет ssh-доступа, конечно, если у вас не виртуальный хостинг. Группа указана www-data вследствие того, что под ней работает nginx и необходимо предоставить ему доступ к файлу сокета. Закрыть доступ остальным позволяют права 660.
pm - указывает как менеджер процессов будет управлять количеством дочерних процессов. Может быть статическим (постоянное количество процессов), динамическим (количество процессов может варьироваться в заданных пределах) и по требованию (когда нужно процесс запускается и убивается по истечении таймаута).
pm.max_children - максимальное количество дочерних процессов.
pm.start_servers - сколько процессов запускается при запуске php-fpm.
pm.min_spare_servers - минимальное количество ожидающих процессов. Если процессов меньше, чем значение параметра, то новые процессы будут созданы.
pm.max_spare_servers - максимальное количество ожидающих процессов. Если ожидающих процессов больше, чем значение параметра, то лишние процессы будут убиты.
pm.status_path - путь к странице статуса.
request_slowlog_timeout - время по прошествии которого запрос считается медленным.
slowlog - путь до файла лога медленных запросов.
access.log - путь до файла с логом доступа.

Другие интересные параметры:

pm.max_requests - количество обработанных запросов после которых процесс нужно перезапустить. Позволяет бороться с утечками памяти.
process.priority - задает приоритет процессов данного пула.
chroot - позволяет зачрутить процессы в указанную директорию. Однако все пути используемые php будут действовать относительно указанной директории, что требует дополнительной настройки.
security.limit_extensions - позволяет указать список расширений файлов для обработки php-fpm.

Также можно переопределять переменные окружения, к примеру:

env[TMP] = /tmp

и переопределять параметры из php.ini почти как это делается в .htaccess:

php_flag[display_errors] = off

То есть мы можем настраивать множество параметров php индивидуально для каждого пула.

Кстати говоря, для изменения параметров php можно использовать файл .user.ini в директории сайта.

Реализация

Материал выше изложен как-то сумбурно. Попробуем посмотреть конкретный простой пример реализации.

Исходим из того, что nginx и php-fpm у вас уже установлены.

Теперь вам необходимо настроить виртуальный хост в nginx так чтобы запросы к статике обрабатывал сам nginx, а запросы к php-скриптам передавал на обработку php-fpm. Пример:

server {
listen 80;
server_name webpanels.spb.ru;

root /var/www/webpanels;
index index.php;

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass unix:/var/run/phpfpm-webpanels.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    include fastcgi_params;
}

location ~ ^/(fpmstat|ping)$ {
    access_log off;
    allow 127.0.0.1;
    allow 123.123.123.123; #your-ip
    deny all;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /fpmstat;
    fastcgi_pass unix:/var/run/phpfpm-webpanels.sock;
}

location ~* ^.+.(html|jpg|jpeg|gif|css|png|js|ico|txt)$ {
    expires 60d;
}
}

Здесь указано куда перенаправлять запросы. В нашем случае используется unix-сокет. Также указываем индексный файл и путь до файла. Как видно, все довольно просто. Данный пример можно использовать как формулу.

Теперь настроим php-fpm. В Debian общие настройки находятся в файле /etc/php5/fpm/php-fpm.conf:

pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
process.max = 64
process.priority = -5
rlimit_files = 1024
events.mechanism = epoll
include=/etc/php5/fpm/pool.d/*.conf

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

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

useradd -m -d /var/www/webpanels -s /usr/sbin/nologin -c "webpanels site" -U webpanels

Кроме того, говорят, что для нормальной работы в файле /etc/php5/fpm/php.ini должен быть установлен следующий параметры:

cgi.fix_pathinfo = 0

Так же из-за отказа от Apache может понадобится сконвертировать правила mod_rewrite в правила понятные для nginx. Сделать это можно, к примеру, с помощью конвертеров доступных по адресам:

http://winginx.com/en/htaccess
http://www.anilcetin.com/convert-apache-htaccess-to-nginx/

Наверх

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