如何排查 PHP-FPM 进程数量异常减少导致请求排队问题?
核心结论:当 PHP-FPM 活跃进程数长期等于 pm.max_children 且接口响应时间从几百毫秒延长到 40 多秒时,90% 的情况是进程池耗尽导致请求在 accept 队列中排队等待。
原因分析
PHP-FPM 进程数量异常减少的本质是进程池管理失衡。根据 2024 年 12 月 11 日的技术文档记录,当进程数不足时会出现典型表现:接口响应时间从正常的几百毫秒逐渐延长到几秒甚至几十秒,最慢案例中单次请求响应时间达到 40 多秒。进程池耗尽时,PHP-FPM 日志中会出现明确告警信息:WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 17 total children。
从技术原理看,PHP-FPM 通过预启动多个 PHP 进程处理请求,进程数太少会导致并发低、排队等待、响应慢;进程数太多则会导致内存耗尽、频繁切换、服务器负载高。2026 年 4 月 6 日的实际案例显示,某 2G 内存服务器可用内存仅剩 70m,内存使用率高达 92%,其中 php-fpm 服务池开启了太多子进程,占用超过大半内存,最终导致数据库服务被挤掉。
解决方案
第一步:检查进程池状态
执行命令sudo systemctl status php-fpm或ps aux | grep 'php-fpm:'查看活跃子进程数是否接近 pm.max_children。更精确的方式是开启 pm.status_path 后执行curl -s http://127.0.0.1/status?full | grep 'processes$'。如果 active processes 长期等于 max children 且 slow requests 持续增长,说明 FPM 池已满。
第二步:调整进程管理参数
根据 2026 年 3 月 25 日的宝塔面板优化建议,以 2G 内存服务器为例,应将 pm 从 static 改为 dynamic 模式,并调整三行关键参数:pm.max_children = 20、pm.start_servers = 5、pm.min_spare_servers = 3。注意每个 PHP 进程常驻约 30–60MB 内存,若将 pm.max_children 设成 50 会直接吃掉 2GB+ 内存,反而触发 OOM Killer 杀进程。
配置文件位置通常在/etc/php/{version}/fpm/pool.d/www.conf,修改后执行sudo systemctl restart php{版本号}-fpm使配置生效。
第三步:排查慢脚本与死锁
根据 2026 年 2 月 20 日的排查指南,90% 的进程耗尽情况是某个接口死循环、没设超时的 cURL、或数据库锁表导致一个请求卡住整个 worker。应在 PHP 层埋点统计查询次数,Laravel 用户可开启DB::enableQueryLog(),原生 PDO 可封装 query() 方法全局记录查询次数。同时检查 slowlog 配置,位置如/var/log/php7.4-fpm-slow.log。
第四步:验证 OPcache 状态
OPcache 配置不当会导致脚本重复编译占用额外进程。执行临时脚本调用opcache_get_status(),关键看num_cached_scripts:新部署后首次访问应快速上升,若长期为 0 或只缓存个位数文件,需检查opcache.restrict_api是否误配。opcache.max_accelerated_files建议至少设为 20000,默认 2000 会导致 Composer 自动加载文件多的项目频繁淘汰缓存。
注意事项
1. 监听端口冲突:根据 2026 年 4 月 26 日的排查指南,检查 listen 配置(如 127.0.0.1:9000 或/run/php-fpm.sock),用ss -tulnp | grep 9000确认端口是否被占用,冲突会导致 502 Bad Gateway。
2. 权限问题:Permission denied(13) 访问 Unix 套接字是常见错误,需在 pool.d/www.conf 核对listen.owner / listen.group / listen.mode,必要时调整为 www-data:www-data 与合适权限(如 0660/0666)。
3. MySQL 版本陷阱:2026 年 3 月 25 日资料明确指出,query_cache 在 MySQL 8.0 已被彻底移除,强行添加会导致启动失败;MariaDB 10.3+ 也默认禁用。宝塔默认将 max_connections 锁在 151,建议调整为 300。
4. 系统资源限制:在/usr/lib/systemd/system/php-fpm.service的 [Service] 段添加LimitNOFILE=65535,随后执行systemctl daemon-reload并重启服务,避免文件描述符不足导致进程无法创建。
5. 进程假死识别:2025 年 9 月 29 日的案例指出,用ps aux|grep php-fpm查看进程状态,若看到状态是 D(不可中断睡眠) 或者 Z(僵尸进程),基本就是进程假死,此时进程存在但不响应新请求。
参考来源
来源:PHP 高并发性能故障排查指南 - 网站卡顿如何快速排查(2026 年 2 月 20 日)
来源:宝塔面板官方文档 - 排查并优化 PHP 与 MySQL 配置(2026 年 3 月 25 日)
来源:Nginx 技术社区 - Nginx 下 php-fpm 异常处理(2024 年 12 月 11 日)
来源:腾讯云开发者社区 - 解决 Linux 下 php-fpm 进程过多导致内存耗尽问题(2026 年 4 月 6 日)