Настройка пулов PHP-FPM
Что такое пул
Пул — набор процессов PHP, готовых обрабатывать запросы. Один PHP-FPM может держать несколько пулов — для разных сайтов или с разными настройками.
По умолчанию — один пул www.
Файл пула
/etc/php/8.5/fpm/pool.d/www.conf:
[www]
user = www-data
group = www-data
listen = /var/run/php/php8.5-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500
Ключевые параметры
user и group
user = www-data
group = www-data
От кого работают процессы.
Важно: файлы Laravel должны принадлежать www-data. Иначе storage/ не пишется, права не читаются.
listen
listen = /var/run/php/php8.5-fpm.sock
Unix-сокет или TCP-порт (127.0.0.1:9000).
Сокет быстрее (нет сетевого стека), но только локально.
TCP — если PHP-FPM на другом сервере.
pm — стратегия управления
pm = dynamic — процессы создаются/убиваются по нагрузке. Стандарт.
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm = static — фиксированное число процессов. Быстрее, но жрёт RAM постоянно.
pm = static
pm.max_children = 20
pm = ondemand — процессы создаются только при запросе. Экономит RAM, но медленный старт.
pm = ondemand
pm.process_idle_timeout = 10s
Когда что:
- Много RAM, стабильная нагрузка →
static - Средний сервер →
dynamic - Мало RAM, редкие запросы →
ondemand
pm.max_children
Максимум процессов. Критичный параметр.
Формула:
max_children = доступная_RAM / память_одного_процесса
Сколько памяти ест процесс Laravel:
ps -ylC php-fpm8.5 --sort:rss | awk '{sum+=$8; count++} END {print "Средний: " sum/count/1024 " MB"}'
Обычно 30-60 МБ на процесс Laravel. С учётом кешей — до 80 МБ.
Пример: сервер 2 ГБ RAM, отдаём под PHP-FPM 1.5 ГБ, процесс по 60 МБ:
1500 / 60 = 25 процессов
Ставь 20-25 — с запасом на ОС, БД, Nginx.
pm.start_servers
Сколько процессов при старте:
pm.start_servers = 4
Формула: max_children / 4 или max_children / 2.
pm.min_spare_servers
Минимум свободных процессов. Если меньше — создаются новые.
pm.min_spare_servers = 2
pm.max_spare_servers
Максимум свободных процессов. Если больше — убиваются лишние.
pm.max_spare_servers = 6
pm.max_requests
После скольких запросов процесс перезапускается.
pm.max_requests = 500
Защита от утечек памяти. Laravel может течь — после 500 запросов процесс пересоздаётся.
Для прода: 500-1000. Для тяжелых приложений: 200-500.
Реальный расчёт
Сервер: 4 vCPU, 4 ГБ RAM.
Что отдать:
- ОС: 500 МБ
- PostgreSQL: 1 ГБ
- Nginx: 100 МБ
- PHP-FPM: 2 ГБ
Процесс Laravel: 60 МБ.
max_children:
2000 / 60 = 33
Ставь 25 — с запасом.
Конфиг:
pm = dynamic
pm.max_children = 25
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm.max_requests = 500
Несколько пулов
Для нескольких сайтов с разной нагрузкой — разные пулы:
/etc/php/8.5/fpm/pool.d/skills.conf:
[skills]
user = www-data
group = www-data
listen = /var/run/php/php8.5-fpm-skills.sock
pm = dynamic
pm.max_children = 30
pm.start_servers = 6
pm.max_requests = 500
/etc/php/8.5/fpm/pool.d/nobleweb.conf:
[nobleweb]
user = www-data
group = www-data
listen = /var/run/php/php8.5-fpm-nobleweb.sock
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s
В Nginx — свой fastcgi_pass для каждого сайта.
Плюс: сайты изолированы — падение одного не затрагивает другой.
Slow log
Медленные запросы (> N секунд):
request_slowlog_timeout = 5s
slowlog = /var/log/php8.5-fpm-slow.log
Что попадает: PHP-стек вызовов, где задержка.
Смотреть:
tail -f /var/log/php8.5-fpm-slow.log
Огромная польза — сразу видно, где тормозит приложение.
Пинг-страница
Для проверки пула:
В www.conf:
ping.path = /ping
ping.response = pong
Проверка:
cgi-fcgi -bind -connect /var/run/php/php8.5-fpm.sock
Или через curl к Nginx, если настроен роут.
Status-страница
Мониторинг состояния пула:
В www.conf:
pm.status_path = /status
В Nginx:
location ~ ^/(status|ping)$ {
fastcgi_pass unix:/var/run/php/php8.5-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
allow 127.0.0.1;
deny all;
}
Проверка:
curl http://127.0.0.1/status
Вывод:
pool: www
process manager: dynamic
accepted conn: 12345
pool: www
idle processes: 5
active processes: 3
total processes: 8
max active processes: 15
max children reached: 0
Что важно:
active processes— сколько сейчас работаютidle processes— сколько свободныmax children reached— если > 0,max_childrenне хватило — увеличивай
Мониторинг
Процессы:
ps aux | grep php-fpm | wc -l
Память каждого:
ps -ylC php-fpm8.5 --sort:rss
Кто сколько ест:
ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/1024 " MB"}'
Перезагрузка конфига
sudo systemctl reload php8.5-fpm
⚠️ reload не пересоздаёт процессы — только перечитывает конфиг. Для применения max_children нужно:
sudo systemctl restart php8.5-fpm
На проде — делай в низкую нагрузку или через graceful reload (по одному процессу).
Частые ошибки
1. 502 Bad Gateway — сокет не совпадает. Проверь listen в пуле и fastcgi_pass в Nginx.
2. max children reached — увеличь pm.max_children.
3. Процессов больше, чем задумано — min_spare_servers и start_servers тоже регулируют.
4. Память кончается — уменьши max_children.
Итог
Правила настройки:
max_children— по формуле RAM / 60 МБpm = dynamic— для средних серверовmax_requests = 500— защита от утечек- slow log — обязательно
- status page — для мониторинга
Дальше — OPcache.