К основному содержимому

PHP-FPM: пулы, воркеры и оптимизация

PHP · 19.04.2026 · 5 мин чтения
Иллюстрация к статье «PHP-FPM: пулы, воркеры и оптимизация»

Что такое 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 = 500
Формула расчёта pm.max_children: Разделите доступную RAM на средний размер одного PHP-процесса. Пример: 2 ГБ RAM, средний процесс 80 МБ → max_children = 2048 / 80 ≈ 25. Проверьте средний размер процесса командой: ps -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-fpm
Не перезапускайте PHP-FPM во время высокой нагрузки — используйте reload, который применяет конфиг без обрыва активных соединений.

Конфигурация 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 в состоянии покоя обычно близок к нулю, поскольку процессы не держатся запущенными без надобности.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке