网站在高峰时变慢,PHP-FPM日志出现 server reached pm.max_children,说明对应进程池已达到允许的子进程上限。它指出的是并发处理槽位用满,原因可能是流量增长,也可能是单个请求长时间占着进程。
先确认发生告警的进程池、时间和当时的请求表现,再决定是优化慢请求还是调整容量。直接把进程数翻倍,可能让小内存VPS更快进入OOM。

先定位进程池和告警时间
journalctl -u php*-fpm --since "1 hour ago" --no-pager
ps -eo pid,rss,comm,args | grep '[p]hp-fpm'
服务名与日志位置依发行版和PHP安装方式而变。对照Nginx访问日志的请求高峰,区分持续繁忙和短时突刺。不要仅凭一次告警就调整全机所有进程池;各站点可能有各自的pool配置。
读懂pm模式与子进程上限
在对应pool配置中查找 pm 和 pm.max_children。PHP官方手册说明,static模式下它决定进程数,dynamic和ondemand模式下它是最大进程数,也就是该pool同时服务请求的上限。
grep -R -nE '^(pm|pm\.max_children|pm\.start_servers|pm\.min_spare_servers|pm\.max_spare_servers)' /etc/php/*/fpm/pool.d/
上面的路径是Debian/Ubuntu常见布局,其他系统应先定位实际配置文件。dynamic模式还要让初始进程与空闲进程参数相互匹配,不要只改一个数字就结束。
用状态页判断是否持续排队
PHP-FPM可通过 pm.status_path 暴露状态页,观察active processes、listen queue与max children reached等指标;主进程池被长请求占满时,还可评估独立的 pm.status_listen。状态端点必须限制访问,不能直接暴露给公网。
队列持续增长意味着进来的请求超过处理能力。此时结合访问日志和应用慢日志找出最耗时的请求,比单纯提高上限更有价值。
按内存预算调整,而不是照搬数值
先记录FPM工作进程在真实流量中的内存占用,再扣除系统、数据库、缓存和突发余量,评估可承受的并发子进程数。进程RSS会包含共享页,不能把单个RSS直接当作精确独占内存;应结合全机内存和swap变化验证。
修改前保存pool配置,使用当前PHP版本对应的 php-fpm -t 或发行版提供的版本化命令检查语法,再按服务管理方式重载。出现OOM或交换区频繁写入时应撤回过大的上限。
检查慢请求和数据库依赖
即使进程上限合理,数据库锁等待、外部HTTP接口或未设置超时的脚本也会让worker长时间无法释放。PHP-FPM提供 request_slowlog_timeout 和 slowlog 用于定位慢请求,启用前应确认日志路径可写并注意敏感数据。
先处理确实拖慢请求的依赖,再复核队列和处理时间。修复慢请求与增加进程数解决的是不同问题,不能用扩容掩盖持续阻塞。
重载并验证实际高峰
变更后检查服务状态、状态页峰值、错误日志与内存曲线,并在接近真实流量的条件下确认排队不再持续增长。不要用未经测试的压测数字代替线上验收。
需要隔离复现网站负载时,可在 萤光云 或 LightNode 的独立实例中验证配置,避免直接在生产站点大幅调高上限。验收应同时看到告警减少、队列受控且没有新增OOM。
FAQ
达到 pm.max_children 就必须升级服务器吗?不一定。先确认慢请求、队列和内存,再决定是否需要更多计算资源。
只调大Nginx超时会有效吗?它可能延长客户端等待,却不会释放被占用的FPM进程,仍需处理后台瓶颈。
温馨提示
记录改动前后的进程数、内存和队列指标,并保留旧配置以便回滚。状态页只向可信网络开放。


