19 Сен 2017 16:09:59 | 0 comments
Перезапуск конкретного пула для php5-fpm
Традиционно сложилось, что при изменении конфигурации php5-fpm чтобы она вступила в силу выполняют команду reload для основного мастер-процесса php5-fpm, по сути — это отправка сигнала SIGUSR2, но как перезапустить только нужный дочерний процесс?
Исходные данные: Debian 8.9 (jessie), nginx 1.13.5, php5-fpm 5.6.30
Традиционно при изменении конфигурации php5-fpm чтобы она вступила в силу выполняют команду:
/etc/init.d/php5-fpm reload
аналогом может служить команда:
kill -USR2 `cat /var/run/php5-fpm.pid`
Но reload не поможет в тех случаях когда например мы установили новый php-модуль и необходимо его использование, для этого нужно выполнять restart, а это уже затронет все php5-fpm пулы. В большинстве случаев такое кардинальное решение не желательно, хочется перезагрузить лишь один конкретный пул на котором работает один конкретный сайт, которому нужен новый php-модуль, а полный restart сделать ночью, когда не так много людей используют сервер.
Как быть?
Решение есть.
Для начала как протестировать конфигурацию php5-fpm?
php5-fpm -t
Протестировать конфигурацию php5-fpm с выводом:
php5-fpm -tt
И собственно магия, gracefull restart a pool
pkill -QUIT -f "php-fpm: pool web1"
Или hard restart a pool
pkill -f "php-fpm: pool web1"
На этом все, до скорых встреч. Если у Вас возникли вопросы или Вы хотите чтобы я помог Вам, то Вы всегда можете связаться со мной разными доступными способами.
Менеджер процессов FastCGI (FPM)
FPM (FastCGI Process Manager, менеджер процессов FastCGI) является альтернативной реализацией PHP FastCGI с несколькими дополнительными возможностями обычно используемыми для высоконагруженных сайтов.
- Продвинутое управление процессами с корректной (graceful) процедурой остановки и запуска;
- Пулы, дающие возможность запуска воркеров с разными uid/gid/chroot/окружением, прослушивая разные порты и используя разные php.ini (замещение safe_mode);
- Настраиваемое ведение журнала потоков вывода (stdout) и ошибок (stderr);
- Аварийный перезапуск в случае внезапного разрушения opcode-кеша;
- Поддержка ускоренной загрузки (accelerated upload);
- «slowlog» — логирование необычно медленно выполняющихся скриптов (не только их имена, но также и их трассировки. Это достигается с помощью ptrace и других подобных утилит для чтения данных исполнения удалённых процессов);
- fastcgi_finish_request() — специальная функция для завершения запроса и сброса всех буферов данных, причём процесс может продолжать выполнение каких-либо длительных действий (конвертирование видео, обработка статистики и т.п.);
- Динамическое/по требованию/статическое порождение дочерних процессов;
- Базовая и расширенная информация о состоянии (аналогично Apache mod_status) с поддержкой различных форматов, таких как json, xml и openmetrics;
- Конфигурационный файл, основанный на php.ini.
User Contributed Notes 11 notes
10 years ago
PHP-FPM is FAST — but be wary of using it while your code base is stored on NFS — under average load your NFS server will feel some serious strain. I have yet to find a work around for this bug: https://bugs.php.net/bug.php?id=52312
5 years ago
php-fpm is not avaliable on Windows, but you can use IIS or Apache as the «fastcgi process manager».
If you have to use Nginx, here is a solution. Nginx provides a load balancing module. We can distribute the request to different php-cgi.exe process.
This is the origin nginx conf.
«`
location ~ \.php$ try_files $uri = 404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
>
«`
You can replace it by
«`
upstream php server 127.0.0.1:9000;
server 127.0.0.1:9001;
server 127.0.0.1:9002;
server 127.0.0.1:9003;
>
location ~ \.php$ try_files $uri = 404;
fastcgi_pass php;
fastcgi_index index.php;
include fastcgi.conf;
>
«`
php-cgi.exe process will die after several requests, so you have to restart the php-cgi.exe manually to keep a process listening the port.
DON’T USE THIS SOLUTION IN PRODUCTION!!
12 years ago
Init script setup
===
You will probably want to create an init script for your new php-fpm. Fortunately, PHP 5.3.3 provides one for you, which you should copy to your init directory and change permissions:
$ cp /sapi/fpm/init.d.php-fpm.in /etc/init.d/php-fpm
$ chmod 755 /etc/init.d/php-fpm
It requires a certain amount of setup. First of all, make sure your php-fpm.conf file is set up to create a PID file when php-fpm starts. E.g.:
—-
pid = /var/run/php-fpm.pid
—-
(also make sure your php-fpm user has permission to create this file).
Now open up your new init script (/etc/init.d/php-fpm) and set the variables at the top to their relevant values. E.g.:
—
prefix=
exec_prefix=
php_fpm_BIN=/sbin/php-fpm
php_fpm_CONF=/etc/php-fpm.conf
php_fpm_PID=/var/run/php-fpm.pid
—
Your init script is now ready. You should now be able to start, stop and reload php-fpm:
$ /etc/init.d/php-fpm start
$ /etc/init.d/php-fpm stop
$ /etc/init.d/php-fpm reload
The one remaining thing you may wish to do is to add your new php-fpm init script to system start-up. E.g. in CentOS:
$ /sbin/chkconfig php-fpm on
Disclaimer: Although I did just do this on my own server about 20 mins ago, everything I’ve written here is off the top of my head, so it may not be 100% correct. Also, allow for differences in system setup. Some understanding of what you are doing is assumed.
6 years ago
It is important to note that FPM is not built with the windows binaries. Many of the guides you may find online rely on php-cgi.exe. Unfortunately they call it FPM but this is incorrect!
The executable php-cgi.exe that is bundled with the windows binaries is a FastCGI interface but it is *not* FPM (Fastcgi Process Manager). php-cgi.exe does not have multi-threading or concurrent request support, nor support for any of the FPM configuration options.
Перезапустить докер контейнер с консольным PHP
И так далее. Если перечитывание не предусмотрено, то помогает kill 1 .
И вот столкнулся с непонятным поведением: kill 1 не работает. Итак, по порядку.
Есть докер-контейнер, в котором выполняется консольная команда php /var/www/artisan queue:work —sleep=1 , она держит соединение с Redis и обрабатывает очереди.
Я выполняю в этом контейнере kill 1 , и ничего не происходит. Сама программа продолжает успешно обрабатывать очереди.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.1 0.1 183592 50544 ? Ss 19:11 0:10 php /var/www/artisan queue:work --sleep=1
Почему такая ситуация? Из-за ожидания ввода-вывода? Или игнорирование сигналов?
PS. Конечно, я могу перезапустить контейнер средствами докера. Но интересно, почему такая ситуация.
Настройка PHP-FPM
Интерпретатор языка программирования PHP может работать в нескольких режимах. Он может быть интегрирован в веб-сервер в виде специального модуля или использоваться как отдельный сервис php-fpm. Аббревиатура FPM расшифровывается как Fastcgi Process Manager. Это сервис, который запускает несколько процессов, которые могут выполнять PHP скрипты. Процессы могут получить скрипты, которые надо выполнить по TCP или Unix сокетам.
Обычно php-fpm используется вместе с веб-сервером Nginx. В этой статье мы рассмотрим как выполняется настройка PHP-FPM для максимально эффективной работы на вашем сервере.
Настройка PHP-FPM
Менеджер процессов PHP-FPM может запускать несколько процессов обработчиков. Обычно для каждого отдельного сайта принято использовать отдельный обработчик, это позволяет распределить нагрузку и отслеживать статистику по каждому сайту. Поэтому есть общий конфигурационный файл php-fpm и конфигурационный файл для каждого обработчика, который обычно называется конфигурационным файлом пула. Обработчик принято называть пулом потому что на самом деле обработкой занимается не один процесс, а целая группа процессов, у каждого из которых есть несколько потоков. Всё это обеспечивает быстрое выполнение скриптов.
1. Установка компонентов
Сервис php-fpm поставляется вместе с интерпретатором php. Установка php-fpm Ubuntu выполняется такой командой:
sudo apt install php-fpm
Кроме того нам понадобится веб-сервер Nginx, потому что php-fpm чаще всего используется вместе с этим веб-сервером:
sudo apt install nginx
2. Конфигурационные файлы
В этой инструкции мы будем рассматривать настройку PHP-FPM на примере Ubuntu. Основной конфигурационный файл находится в такому пути:
Обратите внимание, что это не php.ini файл, а файл настройки именно FPM процессов. Файл php.ini находится в этой же папке:
А вот файлы конфигурации пулов находятся в каталоге /etc/php/7.4/fpm/pool.d/. По умолчанию там находится файл пула по умолчанию www.conf:

Вы можете использовать его в своей конфигурации или копировать для создания новых пулов.
3. Создание пула
Скопируйте файл пула, например losst.conf в папке /etc/php/7.4/fpm/pool.d/ скопируйте в него содержимое файла www.conf. В конце статьи я приведу полностью рабочий конфигурационный файл, но лучше всё же использовать конфигурацию вашей версии PHP:
cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/losst.conf
Теперь откройте этот файл в текстовом редакторе, например в vim:
sudo vi /etc/php/7.4/fpm/pool.d/losst.conf
Первым делом вам нужно выбрать имя пула в квадратных скобках в самой верхней части файла, например, losst, это имя можно использовать в конфигурации с помощью переменной $pool, а ещё оно будет отображаться в менеджере процессов:

Далее надо изменить группу и пользователя, от имени которых будут запускаться процессы пула. Это важно, поскольку у процесса должен быть доступ к файлам PHP, которые надо выполнить. Обычно в Ubuntu для таких целей используется пользователь и группа www-data. От имени этого же пользователя обычно запускается веб-сервер:

Обычно, если вы получаете ошибку permission denied при интерпретации php файлов в php-fpm, означает, что процесс php-fpm запущен от имени не того пользователя или включена строгая политика SELinux.
4. Настройка сокета
Дальше нужно настроить каким образом Nginx или другой веб-сервер будет обращаться к PHP-FPM. Как я уже говорил выше, можно настроить ожидание соединений на TCP порту. Обычно используются порты 9000, 9001, 9002 и так далее. В данном случае надо передать IP адрес на котором следует слушать и порт. Лучше использовать локальный IP адрес 127.0.0.1, чтобы к сервису никто не мог подключится из интернета. Второй вариант — использовать файловый Unix сокет, тогда надо просто передать путь к файлу сокета. В данном примере используется сетевой сокет 127.0.0.1:9000. Вид сокета не имеет значения, но сетевой использовать удобнее:

Если вы используйте файловый сокет, к нему должен быть доступ у веб-сервера, поэтому надо сделать владельцами файла того пользователя и группу, от имени которых запущен веб-сервер, в данном случае www-data и дать им все права на него:
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Если сокет сетевой, то в этом нет необходимости. Для сетевого сокета можно дополнительно указать с каких адресов можно к нему подключаться. Например, только от 127.0.0.1:
5. Настройка процессов
С помощью параметра pm можно настроить сколько дочерних процессов будет запускаться для этого пула и когда. Есть три режима работы:
- dynamic — процессы создаются в зависимости от нагрузки и настроек, если нагрузки нет, всё равно работает определённое количество процессов;
- ondemand — процессы создаются как только возникает нагрузка;
- static — количество процессов всегда одинаковое, указанное в настройках.
Режим static не выгоден, потому что вне зависимости от нагрузки потребляется много памяти и процессорного времени на поддержание работы процессов. Более интересны режимы ondemand и dynamic. Давайте будем использовать режим dynamic. Этот режим имеет три настройки:
- pm.max_children — очень важный параметр, который работает для всех трёх режимов, означает максимально возможное количество дочерних процессов, если значение будет слишком маленьким, то при возрастании нагрузки, лимит исчерпается и ваш сайт начнёт тупить, если слишком большим — исчерпается оперативная память и что-то упадёт;
- pm.start_servers — указывает сколько процессов запускать при старте сервиса;
- pm.min_spare_servers — минимальное количество процессов в режиме ожидания (ничего не обрабатывающих), если количество процессов меньше, будет создан ещё один;
- pm.max_spare_server — максимальное количество процессов в режиме ожидания, если количество процессов будет больше, лишние будут завершены;
Для режима static надо указать только pm.max_children. Для режима ondemand кроме pm.max_children надо указать pm.process_idle_timeout этот параметр означает через какой промежуток времени простоя процесс будет завершен.
Давайте разберемся с режимом dynamic. Запускать много дочерних процессов при старте не надо, в большинстве случаев 2-3 будет достаточно:
Минимальное количество процессов в режиме ожидания тоже большое не нужно, это запас, чтобы php-fpm смог быстро обработать новые запросы не тратя время на запуск новых процессов. Однако это значение должно быть не меньше pm.start_servers, иначе ничего не заработает:
Максимальное количество процессов определяет как быстро процессы будут завершаться при падении нагрузки, можно оставить 10 процессов:
Параметр pm.max_children настройте под себя, обычно достаточно 20-30 процессов, но всё зависит от нагрузки и количества оперативной памяти, если памяти мало лучше пожертвовать производительностью и установить меньшее значение:

Почти готово. Но есть ещё одна проблема. Если дочерние процессы работают слишком долго, в них накапливаются утечки памяти, и рано или поздно на сервере память закончится. Чтобы этого избежать можно настроить автоматическое завершение процесса после выполнения определённого количества запросов, например, 1000:

6. Настройка статистики
Для подбора оптимального значения pm.max_children вам может понадобиться посмотреть статистику в реальном времени сколько процессов запущено, сколько из них находится в ожидании, а также какая длина очереди ожидающих выполнения запросов. Для включения вывода статистики просто добавьте такую строчку:
7. Настройка php.ini
Несмотря на то, что есть общий файл php.ini для всех пулов, вы можете менять настройки прямо в файле пула, для этого используются директивы php_admin_value и php_admin_flag. Первая используется для установки строковых значений, а вторая — для флагов. У директив есть альтернативы: php_value и php_flag, они отличаются только тем, что их можно перезаписать с помощью функции ini_set, а значения заданные с помощью директив с приставкой admin перезаписать нельзя.
php_admin_flag[display_errors] = off
php_admin_value[error_log] = /var/log/fpm-php.losst.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 32M

Когда все настройки завершены, не забудьте сохранить изменения и перезапустить php-fpm:
sudo systemctl restart php7.4-fpm
8. Настройка веб-сервера
Для того чтобы всё протестировать придётся настроить ещё и веб-сервер. В конфигурационный файл виртуального хоста Nginx надо добавить такие строки:
location /status fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
>
location ~ \.php$ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) return 404;
>
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
>

Первая секция позволяет смотреть статистику работы php-fpm открыв в браузере ссылку /status, которую мы ранее указали в настройках. Вторая секция обрабатывает всё остальные файлы php. Первая строка второй секции разбивает путь к скрипту по регулярному выражению на две части: $fastcgi_script_name и $fastcgi_path. Первая переменная нам понадобится в следующей же строчке, где с помощью условия проверяется существует ли такой файл, и если нет, то возвращается 404.
Дальше надо импортировать файл fastcgi_params, в котором передаются все переменные, которые потом будут доступны в массиве $_SERVER из скрипта. В следующей строчке объявляется ещё один важный параметр, которого нет в fastcgi_params, потому что он использует переменную $fastcgi_script_name, полученную ранее. Именно по нему php-fpm определяет путь к скрипту, который надо выполнить, если его не передать, вы получите пустой экран.
Последняя директива fastcgi_pass указывает как надо передавать данные php-fpm, сюда можно передать путь к файлу сокету, на котором слушает сервис или IP адрес и порт. В данном случае используется ранее настроенный 127.0.0.1:9000. После завершения настройки перезапустите Nginx:
sudo systemctl restart nginx
Теперь вы можете открыть в браузере страницу статистики, как видите всё работает:

Можно ещё создать файл phpinfo.php с текстом в каталоге веб-сервера и посмотреть настройки php, например, memory_limit, заданный в файле конфигурации пула работает:

Настройка веб-сервера может очень сильно отличаться в зависимости от ваших требований. Здесь приведен только общий пример, чтобы проверить работоспособность и верность настройки.
Выводы
В этой небольшой статье мы рассмотрели как выполняется настройка PHP-FPM с Nginx для оптимальной обработки PHP скриптов на сайте. Как видите, несмотря на довольно сложную архитектуру, с программой вполне можно разобраться. Подобрав верное значение pm.max_children вы сможете обеспечить максимальную производительность вашему сайту и предотвратить потребление всей оперативной памяти.
