php-fpm: server reached pm.max_children setting
Предупреждение о достижении предела рабочих процессов означает, что пул исчерпан и запросы встают в очередь. Служба остаётся активной, поэтому по её состоянию проблему не увидеть — только по журналу и по времени ответа.
Что это значит
Значение считают от памяти: сколько памяти занимает один рабочий процесс, умножить на предел — должно укладываться в доступную память с запасом. Ставить предел «на всякий случай» большим опасно: при наплыве запросов машина уйдёт в подкачку.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Предел рабочих процессов мал для нагрузки
Значения по умолчанию рассчитаны на скромный сайт. При росте посещаемости пул исчерпывается, и запросы ждут.
-
Медленные запросы держат процессы
Один долгий запрос занимает рабочий процесс целиком. Несколько таких запросов исчерпывают пул, хотя нагрузка невелика.
-
Предел упирается в память или в число задач службы
Рабочие процессы считаются задачами контрольной группы. При поднятии предела пула надо проверить
TasksMax=и память.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Предупреждения о пределе и о медленных запросах.
journalctl -u php8.3-fpm -n 50 --no-pager | grep -iE "max_children|slow"Число рабочих процессов и предел задач.
systemctl status php8.3-fpm --no-pager | grep -i tasksНастройки пула целиком.
grep -E "^pm" /etc/php/8.3/fpm/pool.d/www.confРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Значения по умолчанию рассчитаны на скромный сайт. При росте посещаемости пул исчерпывается, и запросы ждут.
- Как проверить
-
Посмотрите настройку пула и предупреждения в журнале.
grep -E "^pm|^pm\." /etc/php/8.3/fpm/pool.d/www.conf journalctl -u php8.3-fpm -n 40 --no-pager | grep -i max_children
- Как исправить
-
Поднимите предел, посчитав его от памяти: (доступная память минус запас) делить на память одного процесса.
sudo systemctl reload php8.3-fpm
- Почему происходит
- Один долгий запрос занимает рабочий процесс целиком. Несколько таких запросов исчерпывают пул, хотя нагрузка невелика.
- Как проверить
-
Включите журнал медленных запросов и посмотрите его.
grep -E "slowlog|request_slowlog_timeout" /etc/php/8.3/fpm/pool.d/www.conf sudo tail -30 /var/log/php8.3-fpm.log
- Как исправить
- Найдите и ускорьте медленные места. Поднятие предела тут лишь маскирует проблему.
- Почему происходит
- Рабочие процессы считаются задачами контрольной группы. При поднятии предела пула надо проверить
TasksMax=и память.
- Как проверить
-
Посмотрите пределы службы.
systemctl show php8.3-fpm -p TasksMax -p TasksCurrent -p MemoryMax -p MemoryPeak
- Как исправить
- Согласуйте пределы: пул не может быть больше того, что позволяют ограничения службы.
Пример вывода
Пул исчерпан, запросы ждут. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
php-fpm8.3[1200]: [WARNING] [pool www] server reached pm.max_children setting (10), consider raising it
# в это же время в журнале nginx:
nginx[1120]: [error] upstream timed out (110: Connection timed out) while reading response header from upstream
Связанные ошибки
- nginx 502 Bad Gateway: connect() failed к приложению nginx работает, а приложение недоступно: connect() failed, connection refused, no such file or directory для сокета. Разбор 502.
- Too many tasks: упор в предел TasksMax Служба не может создать новый процесс: достигнут предел TasksMax. Где он задан и как поднять правильно.
- Failed with result 'oom-kill' Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
- MySQL: Too many connections База отказывает в новых подключениях: исчерпан max_connections или предел дескрипторов службы.
- A start job is running: загрузка висит на одной службе Загрузка останавливается с обратным отсчётом: служба не укладывается в таймаут. Как найти виновника и не ждать.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Apache: Invalid command — не включён модуль Apache не запускается: директива требует модуль, который не подключён. Как найти нужный модуль и включить.
- Cannot assign requested address при привязке Ошибка 99 при привязке: адрес не принадлежит машине или ещё не поднят. Разбор с network-online.target и ip_nonlocal_bind.
Где встречается чаще всего
Источники
- Документация PHP: настройка пулов FPM
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено нагрузкой на пул с pm.max_children=2.