Если вы уже настроили Nginx reverse proxy и увеличили memory_limit в PHP, но сайт всё ещё тормозит под нагрузкой — проблема скорее всего в PHP-FPM. Это не просто «ещё один способ запустить PHP», а мощный менеджер процессов, который при правильной настройке выдерживает в 3-5 раз большую нагрузку по сравнению со стандартным mod_php.
В этом руководстве мы разберём архитектуру PHP-FPM, настроим пул процессов под разные сценарии нагрузки и научимся мониторить производительность в реальном времени.
Что такое PHP-FPM и почему это важно
PHP-FPM (FastCGI Process Manager) — это альтернативная реализация PHP FastCGI с дополнительными возможностями для высоконагруженных сайтов. В отличие от mod_php, который создаёт новый процесс PHP для каждого запроса, PHP-FPM держит пул готовых процессов, что eliminates overhead на запуск интерпретатора.
Архитектура PHP-FPM:
- Master process — управляет пулом, слушает сокеты, создаёт/уничтожает worker’ы
- Worker processes — обрабатывают PHP-запросы от Nginx
- Socket — точка связи между Nginx и PHP-FPM (Unix socket или TCP)
Для WordPress это критично: каждый запрос к сайту (даже закэшированный) проходит через PHP-FPM для проверки авторизации, загрузки плагинов и генерации HTML. Оптимизированный пул = быстрый отклик.
Шаг 1: Базовая настройка пула процессов
Конфигурация PHP-FPM находится в /etc/php/8.2/fpm/pool.d/www.conf (для Ubuntu/Debian с PHP 8.2). Открываем файл:
sudo nano /etc/php/8.2/fpm/pool.d/www.confНаходим секцию с настройками пула и настраиваем под наш сервер:
; Базовые настройки пула
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; Настройки процессов (формулы ниже)
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500Шаг 2: Выбор стратегии управления процессами
Параметр pm определяет, как PHP-FPM управляет worker’ами. Есть три режима:
Dynamic (по умолчанию)
Количество процессов меняется динамически в зависимости от нагрузки. Подходит для большинства сайтов.
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20Static
Фиксированное количество процессов. Максимальная производительность, но требует точного расчёта. Рекомендуется для высоконагруженных проектов с стабильным трафиком.
pm = static
pm.max_children = 30Ondemand
Процессы создаются по запросу и уничтожаются после простоя. Экономит память, но добавляет задержку при первом запросе. Подходит для сайтов с низкой посещаемостью.
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10sШаг 3: Расчёт оптимального количества процессов
Главная формула для расчёта pm.max_children:
pm.max_children = (Общая RAM - RAM для системы - RAM для MySQL) / RAM на один процесс PHPПример расчёта для VPS с 4GB RAM:
- Всего RAM: 4096 MB
- Система + Nginx: 512 MB
- MySQL/MariaDB: 512 MB
- Redis: 256 MB
- Доступно для PHP: 4096 — 512 — 512 — 256 = 2816 MB
- Среднее потребление одного процесса WordPress: 64-128 MB
- pm.max_children = 2816 / 96 ≈ 29 процессов
Как узнать реальное потребление процесса PHP:
# Смотрим потребление всех PHP-FPM процессов
ps aux | grep php-fpm | awk '{print $6}' | paste -sd+ | bc
# Или через top
top -c | grep php-fpmШаг 4: Настройка для разных сценариев
Сценарий 1: Небольшой блог (до 1000 посетителей/день)
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 1000Сценарий 2: Средний сайт (1000-10000 посетителей/день)
pm = dynamic
pm.max_children = 30
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 500Сценарий 3: Высоконагруженный проект (10000+ посетителей/день)
pm = static
pm.max_children = 40
pm.max_requests = 1000Шаг 5: Дополнительные параметры производительности
Добавляем эти настройки в конец секции пула:
; Лимит времени выполнения (секунды)
request_terminate_timeout = 300
; Лимит памяти на процесс (должен совпадать с memory_limit в php.ini)
php_admin_value[memory_limit] = 256M
; Лог медленных запросов (для отладки)
slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 5s
; Ограничение ресурсов процесса
rlimit_files = 1024
rlimit_core = 0
; Catch workers output (для отладки)
catch_workers_output = yes
php_admin_flag[log_errors] = onШаг 6: Настройка Unix socket vs TCP
По умолчанию PHP-FPM использует Unix socket — это быстрее TCP на 10-15%. Но если Nginx и PHP-FPM работают на разных серверах, нужен TCP.
Unix socket (рекомендуется для одного сервера):
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660TCP (для распределённых систем):
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1В конфиге Nginx меняем accordingly:
# Для Unix socket
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
# Для TCP
fastcgi_pass 127.0.0.1:9000;Шаг 7: Мониторинг производительности
Включаем статусную страницу PHP-FPM для мониторинга:
; В конце www.conf добавляем
pm.status_path = /status
ping.path = /pingВ конфиге Nginx добавляем блок для доступа к статусу:
location ~ ^/(status|ping)$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Ограничиваем доступ по IP
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
}Теперь можно мониторить через:
# Базовая информация
curl http://127.0.0.1/status
# Подробная информация (JSON)
curl http://127.0.0.1/status?json
# Полная информация
curl http://127.0.0.1/status?fullКлючевые метрики для мониторинга:
- active processes — количество активных worker’ов (должно быть < max_children)
- idle processes — свободные worker’ы (должно быть > min_spare_servers)
- slow requests — медленные запросы (идеально 0)
- max active processes — пиковая нагрузка (если = max_children, нужно увеличивать)
Шаг 8: Интеграция с systemd для автозапуска
Убеждаемся, что PHP-FPM запускается автоматически и перезапускается при сбоях:
# Включаем автозапуск
sudo systemctl enable php8.2-fpm
# Настраиваем автоперезапуск при сбоях
sudo systemctl edit php8.2-fpmДобавляем:
[Service]
Restart=always
RestartSec=3
StartLimitInterval=60
StartLimitBurst=3Чек-лист оптимизации PHP-FPM
- ✅ Выбрана правильная стратегия (dynamic/static/ondemand)
- ✅ Рассчитано оптимальное количество процессов по формуле
- ✅ Настроены spare servers для динамического режима
- ✅ Установлен pm.max_requests для предотвращения утечек памяти
- ✅ Включён slowlog для отладки медленных запросов
- ✅ Настроен мониторинг через status page
- ✅ Проверены права на socket (для Unix socket)
- ✅ Настроен автозапуск и автоперезапуск через systemd
Что делать, если проблемы не решаются?
502 Bad Gateway от Nginx
Это значит, что Nginx не может достучаться до PHP-FPM. Проверяем:
- Работает ли PHP-FPM:
sudo systemctl status php8.2-fpm - Совпадает ли путь к socket в конфиге Nginx и PHP-FPM
- Права на socket:
ls -la /run/php/php8.2-fpm.sock(должен быть www-data) - Не превышен ли лимит процессов:
ps aux | grep php-fpm | wc -l
Процессы постоянно перезапускаются
Если в логах видите «WARNING: [pool www] server reached pm.max_children setting», значит не хватает worker’ов. Увеличиваем pm.max_children по формуле из Шага 3.
Высокое потребление памяти
Если PHP-FPM ест всю RAM, возможно:
- Слишком большой
pm.max_children— уменьшаем - Утечка памяти в плагинах — включаем
pm.max_requests = 500для периодического перезапуска worker’ов - Слишком высокий
memory_limit— проверяем реальные потребности через Redis Object Cache
Медленные запросы
Если slowlog показывает запросы > 5 секунд:
- Проверяем медленные SQL-запросы через Query Monitor
- Оптимизируем тяжёлые плагины
- Увеличиваем
request_terminate_timeout(но это костыль, лучше найти причину)
Best practices для продакшна
- Используйте static режим для стабильной высокой нагрузки
- Устанавливайте
pm.max_requestsмежду 500-1000 для предотвращения утечек - Мониторьте
slowlogрегулярно — это индикатор проблем - Настройте алерты на
max active processes = max_children - Используйте Unix socket вместо TCP, если всё на одном сервере
- Регулярно пересчитывайте
pm.max_childrenпри изменении нагрузки
Правильно настроенный PHP-FPM — это фундамент производительности WordPress. Потратив 30 минут на настройку, вы получите стабильный сайт, который выдерживает пиковые нагрузки без падений и тормозов.