Что такое PHP-FPM и зачем его настраивать
PHP-FPM (FastCGI Process Manager) — менеджер процессов PHP, который запускает PHP как отдельный сервис. В связке с Nginx он обеспечивает высокую производительность: Nginx обрабатывает статику, а PHP-FPM — динамические запросы. Правильная настройка PHP-FPM позволяет обслуживать в 2–5 раз больше запросов без увеличения RAM.
Файл конфигурации пула
Основной файл пула находится в /etc/php/8.x/fpm/pool.d/www.conf. Откройте его для редактирования:
sudo nano /etc/php/8.2/fpm/pool.d/www.confРежимы управления процессами (pm)
Параметр pm определяет, как PHP-FPM управляет дочерними процессами:
| Режим | Описание | Когда использовать |
|---|---|---|
static | Фиксированное число процессов | Высоконагруженные серверы с достаточной RAM |
dynamic | Число процессов меняется динамически | Большинство VPS (рекомендуется) |
ondemand | Процессы создаются по запросу | Сервер с малым трафиком, экономия RAM |
Оптимальные значения pm для dynamic
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500ps -o rss= -C php-fpm8.2 | awk '{ sum+=$1 } END { print sum/NR/1024 " MB" }'Slow Log — анализ медленных скриптов
Включите slow log для диагностики узких мест:
slowlog = /var/log/php8.2-fpm-slow.log
request_slowlog_timeout = 5sПросматривайте лог командой: tail -f /var/log/php8.2-fpm-slow.log
Страница статуса PHP-FPM
Добавьте в конфиг пула:
pm.status_path = /statusВ Nginx добавьте location:
location ~ ^/status$ {
allow 127.0.0.1;
deny all;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}Применение настроек
sudo systemctl reload php8.2-fpm
sudo systemctl status php8.2-fpmreload, который применяет конфиг без обрыва активных соединений.Конфигурация Nginx для PHP-FPM
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_read_timeout 300;
}Реальные ошибки PHP-FPM
Достигнут pm.max_children
[27-Sep-2026 14:02:11] WARNING: [pool www] server reached pm.max_children setting (20), consider raising itВсе 20 воркеров пула заняты обработкой запросов, новые запросы встают в очередь ядра ОС на сокете. Если очередь тоже переполняется, Nginx получает отказ в соединении и отдаёт клиенту 502 или 504. Само по себе предупреждение — не авария, но частое его появление в логе означает, что pm.max_children занижен относительно реального трафика либо скрипты стали выполняться дольше обычного.
Воркер убит OOM killer’ом
Out of memory: Killed process 18432 (php-fpm) total-vm:512000kB, anon-rss:245000kB, file-rss:0kBЭта строка — из системного журнала ядра (dmesg или journalctl -k), не из лога PHP-FPM. Значит суммарная память всех процессов превысила физическую RAM сервера, и ядро принудительно завершило один из воркеров. Формула расчёта pm.max_children без учёта пиковой нагрузки — прямой путь к этой ошибке.
Между этими двумя записями в логах есть прямая связь: если воркеры регулярно упираются в pm.max_children, администратор в панике поднимает лимит без пересчёта доступной памяти — и получает уже не очередь запросов, а падение сервера целиком по нехватке RAM.
Когда типовые значения pm не подходят
staticдержит фиксированное число процессов постоянно — на сервере с редким трафиком это чистая трата RAM в простое.ondemandэкономит память, но добавляет задержку на форк нового процесса при первом запросе после простоя — для API с жёсткими SLA по времени ответа это может быть неприемлемо.pm.max_children, посчитанный только по среднему размеру процесса, не учитывает всплески: тяжёлый отчёт или экспорт может временно раздуть один воркер в разы — закладывайте запас, а не работайте впритык к лимиту RAM.
Проверка результата
| Поле статуса | О чём говорит |
|---|---|
| active processes | Сколько воркеров занято обработкой запроса прямо сейчас |
| idle processes | Сколько воркеров простаивает в ожидании |
| listen queue | Запросы, ожидающие свободного воркера — в норме 0 |
| max children reached | Сколько раз с момента старта упирались в pm.max_children |
curl "http://127.0.0.1/status?full"Ненулевой и растущий max children reached — сигнал поднять pm.max_children или сначала разобраться, почему запросы стали выполняться медленнее, прежде чем просто увеличивать лимит.
Частые вопросы
Что произойдёт, если изменить pm.max_children на работающем сервере через reload — прервутся ли активные соединения?
Reload применяет новую конфигурацию без обрыва уже установленных соединений — именно поэтому статья рекомендует использовать его вместо полного перезапуска во время нагрузки. Новые значения pm.max_children и других параметров пула начинают действовать для новых запросов, а уже выполняющиеся скрипты успевают завершиться по прежним правилам.
Нужно ли менять max_requests, если сайт написан на фреймворке с утечками памяти в скриптах?
Да, при утечках памяти в скриптах фреймворка каждый процесс со временем накапливает всё больше занятой памяти, поэтому параметр max_requests, принудительно перезапускающий воркер после заданного числа обработанных запросов, становится особенно важным. Без него утечка постепенно съедает RAM у каждого процесса и приближает сервер к ошибке нехватки памяти, описанной в статье.
Как узнать, что текущих значений pm действительно не хватает, а не сервер просто временно перегружен другим процессом?
Нужно смотреть на поле listen queue и счётчик max children reached на странице статуса за продолжительный период, а не разово: единичный всплеск может объясняться соседним фоновым процессом, а устойчивый рост именно этих показателей говорит о нехватке воркеров для реального трафика. Полезно сопоставить время всплесков с логами других служб на том же сервере перед тем, как менять конфигурацию пула.
Можно ли использовать режим ondemand вместе со страницей статуса PHP-FPM?
Да, режим ondemand и страница статуса pm.status_path совместимы — статус отображает текущее состояние пула независимо от того, как создаются процессы: динамически, статично или по запросу. Разница лишь в том, что при ondemand счётчик idle processes в состоянии покоя обычно близок к нулю, поскольку процессы не держатся запущенными без надобности.