Как PHP‑FPM распределяет запросы при pm.max_requests
В режиме pm=static PHP‑FPM распределяет запросы по процессам в Round‑Robin. После 1000‑го запроса процесс перезапускается, но без задержек для новых запросов.
Как PHP‑FPM распределяет запросы между процессами, когда включён pm=static? Я слышал, что это делается по принципу Round‑Robin, но не совсем уверен. Если задать pm.max_requests=1000, что происходит после обработки 1000‑го запроса? Менеджер перезапускает процесс сразу после завершения текущего запроса, до того, как начнётся следующий? И как реагирует система, если в момент перезапуска поступает новый запрос: ждёт ли менеджер его, или сразу отдаёт другому процессу? Эти нюансы важны, потому что перезагрузка может влиять на обработку входящих запросов.
Запросы в режиме pm=static распределяются по потокам‑процессам, используя простую схему Round‑Robin: каждый новый запрос посылается на следующий свободный процесс в кольце, а после последнего – цикл начинается сначала. Когда pm.max_requests достигает заданного значения (например, 1000), завершённый процесс сразу «съедается» менеджером: после окончания текущего запроса он завершается и заменяется новым процессом, но до начала следующего запроса никаких задержек в обслуживании не возникает. Если в момент перезапуска поступает новый запрос, менеджер просто перенаправляет его в кольцо, пока не будет освобожден нужный процесс; запрос не «застревает» в ожидании.
Содержание
- Как распределяются запросы при pm=static
- Влияние pm.max_requests на цикл жизни процесса
- Обработка новых запросов во время перезапуска
Как распределяются запросы при pm=static
В режиме static PHP‑FPM создаёт фиксированное число дочерних процессов, равное значению pm.max_children. После запуска менеджер назначает каждому из них собственный «пул» памяти и открывает сокет FastCGI, на который Nginx (или другой веб‑сервер) посылает запросы.
Распределение реализовано по принципу Round‑Robin. При поступлении нового запроса менеджер просто выбирает следующий свободный процесс в очереди. Если все процессы заняты, запрос помещается в очередь до тех пор, пока один из процессов не освободится. Это гарантирует равномерное использование ресурсов и избавляет от «горячих» точек, которые могут возникнуть при случайном распределении.
См. подробности в официальной документации: PHP‑FPM Configuration.
Влияние pm.max_requests на цикл жизни процесса
Параметр pm.max_requests определяет, сколько запросов может обработать один дочерний процесс, прежде чем он будет перезапущен. После обработки 1000‑го запроса менеджер закрывает процесс только после завершения текущего запроса. Он не «прыгнет» в середине выполнения, потому что это может привести к непредсказуемому состоянию памяти и файловых дескрипторов.
После завершения запроса процесс завершается и сразу создаётся новый «заменитель» с тем же конфигурационным окружением. Время перезапуска обычно занимает несколько миллисекунд, но в критических нагрузках это время может быть ощутимо, если количество процессов очень велико.
Подробное объяснение можно найти в статье от DigitalOcean: How to Configure PHP‑FPM.
Обработка новых запросов во время перезапуска
Когда менеджер инициирует перезапуск процесса, он не блокирует очередь запросов. Новый запрос поступает в FastCGI‑слот, и менеджер быстро определяет, какой из свободных процессов его обслужит. Если текущий процесс, который собирается перезапустить, был единственным свободным (т.е. все остальные заняты), новый запрос будет ждать в внутренней очереди FPM до тех пор, пока не освободится другой процесс.
Таким образом:
- Нет паузы в обслуживании, если есть свободный процесс;
- Минимальная задержка (пока не освободится процесс) в случае, когда все процессы заняты;
- Никакой «потери» запросов, потому что они помещаются в очередь, а не отклоняются.
Эти нюансы важны при настройке масштабируемости: если вы ожидаете пиковые нагрузки, стоит увеличить pm.max_children или использовать pm=dynamic, чтобы FPM мог динамически масштабировать пул процессов.
Заключение
- При pm=static запросы распределяются по процессам по схеме Round‑Robin, что обеспечивает простое и предсказуемое поведение.
pm.max_requests=1000заставляет каждый процесс завершить работу после 1000‑го запроса, но только после завершения текущего запроса; новый процесс запускается сразу же.- В момент перезапуска новые запросы не блокируются; они ставятся в очередь и обслуживаются, как только освободится свободный процесс, что минимизирует потери и задержки.
- Для высоких нагрузок рекомендуется тщательно подобрать сочетание
pm.max_children,pm.max_requestsи, при необходимости, перейти наpm=dynamic, чтобы обеспечить гибкую масштабируемость.