ondemand模式下空闲进程不回收,首要确认pm.process_idle_timeout是否显式配置(默认不生效),其次检查pm.max_children是否过大导致系统误判需保持冗余,再排查slowlog/error_log中是否存在阻塞或异常,php 7.3还存在保留至少1个空闲进程的设计行为。

ondemand 模式下空闲进程不回收,先确认 pm.process_idle_timeout 是否生效
ondemand 模式依赖 pm.process_idle_timeout 控制子进程空闲多久后被杀掉。如果进程长期驻留、不释放,大概率是这个参数没设或设成了 0 / 注释状态。它默认值为空(即不启用),**不是 10 秒也不是 60 秒**——必须显式配置才起作用。
实操建议:
- 检查你的 pool 配置段(如
www.conf)里是否有pm.process_idle_timeout = 60s这样的行;没有就加上,单位支持s、m,不能写成60(无单位会被忽略) - 该参数只在
pm = ondemand时有效,pm = dynamic下完全不读取 - 设得太小(如
5s)会导致频繁启停,尤其在低频但偶发 burst 请求时,反而增加延迟
确认 pm.max_children 是否卡住了进程生命周期
pm.max_children 在 ondemand 模式下限制的是「最多允许存在的子进程总数」,但它**不直接控制回收逻辑**。不过如果当前活跃 + 空闲进程数已达到 pm.max_children,PHP-FPM 就不会主动回收空闲进程——因为系统认为“可能马上还要用”,优先保连接数。
常见错误现象:明明设置了 pm.process_idle_timeout = 30s,但 ps aux | grep 'php-fpm: pool www' 一直显示 10+ 个进程不减少。
排查与调整:
- 用
php-fpm7.3 -t验证配置语法是否正确,避免因配置加载失败导致参数未生效 - 临时把
pm.max_children调低(比如从 30 改成 5),观察空闲进程是否开始按pm.process_idle_timeout回收——能回收说明原值过大,系统误判为“需保持冗余” - 注意:该值过低会导致并发请求被拒绝,日志中会出现
WARNING: [pool www] server reached pm.max_children setting
检查 slowlog 和 error_log 是否掩盖了实际问题
有些情况下进程看似“不回收”,其实是卡在慢请求或阻塞调用里,根本没进入空闲状态。ondemand 的回收只针对状态为 idle 的进程,而 slow 或 running 的进程不会被 pm.process_idle_timeout 触发清理。
实操建议:
- 打开
slowlog = /var/log/php-fpm7.3-slow.log并设置request_slowlog_timeout = 2s,抓取长时间未返回的脚本 - 查
error_log里有没有unable to kill process或failed to remove pid file类报错,这类底层异常可能导致进程状态同步失败 - 用
strace -p $(pgrep php-fpm | head -1)抽样看一个 worker 是否真在 idle(等待 accept())还是卡在某次 system call 上
PHP-FPM 7.3 的 ondemand 兼容性细节
PHP 7.3 对 ondemand 的实现比 8.x 更保守:它不会在极低负载下把所有 worker 彻底清空到 0,通常会保留至少 1 个空闲进程,即使过了 pm.process_idle_timeout。这不是 bug,是 7.3 的设计行为——主进程为防冷启动抖动,会做最小兜底。
所以如果你看到始终剩 1 个 php-fpm: pool www 进程,只要它不再增长、内存稳定、且新请求能正常处理,就属于预期行为。强行通过信号杀掉它,主进程会在下一个请求来时立刻拉起,反而增加首字节延迟。
真正要警惕的是:进程数持续增长、不回落、伴随内存缓慢上涨——那大概率是 pm.process_idle_timeout 未生效,或存在未关闭的资源句柄(如 MySQL 长连接、curl handle 未 unset)让进程无法真正进入 idle 状态。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











