php-fpm进程占用过高主因常是慢脚本卡死或配置错配,需启用slowlog并验证其有效性,结合单进程内存测算合理设置pm.max_children,同时排查数据库、redis等外部依赖阻塞及opcache校验等隐性瓶颈。

PHP-FPM 进程占用过高,八成不是“进程太多”,而是某些脚本卡住不退出、反复 fork 新进程,或配置参数与实际负载严重错配。光看 ps aux | grep php-fpm 数量没用,得先确认这些进程是真在干活,还是空转、卡死、或刚启动就挂了。
怎么确认是慢脚本拖垮了整个池子
宝塔默认关着慢日志,你看到 CPU 飙高、php-fpm 进程数暴涨,却找不到源头。必须手动启用并验证它是否真在记录:
- 检查路径:
/www/server/php/74/etc/php-fpm.d/www.conf(数字 74 替换为你实际 PHP 版本)里这三行是否生效:slowlog = /www/wwwlogs/php_slow.log、request_slowlog_timeout = 2s、request_terminate_timeout = 0 -
request_terminate_timeout = 0很关键——设成非零值(比如 30s)会导致慢日志还没写完,进程就被强杀,日志为空 - 权限要对:
ls -ld /www/wwwlogs/确保属主是www,否则静默失败 - 测试是否生效:放个
sleep(3)的脚本访问一次,再执行tail -n 10 /www/wwwlogs/php_slow.log,看到script_filename和duration才算真正跑通
pm.max_children 设多少才不会反复 fork 又不爆内存
这个值不是拍脑袋定的,它直接决定最大并发承载能力,也决定 OOM 的发生时机。设小了排队等进程,设大了内存瞬间见底:
- 先查真实内存占用:
ps --no-headers -o rss -C php-fpm | awk '{sum+=$1} END {print int(sum/NR/1024)" MB"}',得出单个 worker 平均 RSS(比如 36MB) - 留 30% 内存给系统和其他服务,剩余可用内存 ÷ 单进程 RSS ≈ 理论上限(如 2.8GB ÷ 36MB ≈ 77)
- 再打八折取安全值:
pm.max_children = 60,别直接拉到理论值 - 动态模式下,
pm.start_servers别设 2 或 5——看宝塔「PHP 设置 → 性能调整」里「当前运行中进程数」的 5 分钟低谷值,设为该值下限(比如常在 10–15 之间,就设pm.start_servers = 10) - 改完必须
php-fpm -t校验语法,再systemctl restart php-fpm-74(版本号别写错),仅「重载」可能不生效
为什么开了 slowlog 还是找不到卡点
慢日志只捕获「执行时间超阈值」的请求,但很多卡顿根本不是代码慢,而是被外部依赖堵死,这类请求甚至进不了 slowlog:
- 数据库连接卡住:MySQL 没配
wait_timeout或连接池耗尽,mysqli_connect会阻塞几十秒,但 slowlog 不记——它只从 PHP 脚本真正开始执行算起 - Redis 超时未设:
redis.timeout = 1没配,一个GET请求卡在 TCP 重传上,PHP 进程挂着不动,slowlog 不触发 - file_get_contents 或 cURL 没设超时:
stream_context_create(['http'=>['timeout'=>5]])缺失,外部 API 响应慢或无响应,进程就一直等 - OPcache 文件校验开着:
opcache.validate_timestamps = 1(生产环境必须为 0),每次请求都 stat 几十个文件,IO 拉满,但 slowlog 认为“执行快”,只记业务逻辑耗时
真正卡顿的根因往往藏在 slowlog 之外:先看 top -u www 找 RES 高的 PID,再 cat /proc/{PID}/stack 看它停在哪一行系统调用上——比盯着 pm.max_children 数字有效得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











