PHP-FPM 进程僵死导致 CPU 占用 100% 怎么定位问题?

文章导读
定位 PHP-FPM 进程僵死且 CPU 占用 100% 的问题,最推荐直接使用 top 命令锁定高占用进程 PID,结合 PHP-FPM 慢日志(slowlog)分析代码执行栈,必要时使用 strace 追踪系统调用。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

定位 PHP-FPM 进程僵死且 CPU 占用 100% 的问题,最推荐直接使用 top 命令锁定高占用进程 PID,结合 PHP-FPM 慢日志(slowlog)分析代码执行栈,必要时使用 strace 追踪系统调用。

先说结论:PHP-FPM 进程 CPU 满载通常由代码死循环、外部依赖超时重试或进程管理配置不当引起,需优先隔离故障进程再分析日志。

  • 先确认:使用 top 命令区分是单个 worker 进程占用高还是 master 进程占用高,确认是否伴随负载(load average)飙升。
  • 先处理:对持续占用 CPU 的特定 PID 执行 kill 操作止血,避免影响其他请求,同时保留现场日志。
  • 再验证:调整 php-fpm.conf 中的 pm 最大子进程数及 request_terminate_timeout 参数,观察重启后 CPU 是否回落。

命令速用版

以下命令用于快速定位高 CPU 占用的 PHP-FPM 进程及其父进程关系,适用于大多数 Linux 发行版。

# 1. 查找 CPU 占用最高的进程
 top -c -o %CPU

# 2. 确认进程是否为 php-fpm
 ps -ef | grep php-fpm

# 3. 查看进程树,确认子进程归属
 pstree -p | grep php-fpm

# 4. 追踪卡顿进程的系统调用(需替换 PID)
 strace -p <PID> -o /tmp/php_strace.log

# 5. 优雅重启 PHP-FPM(不同系统路径不同)
 systemctl reload php-fpm

为什么会这样

PHP-FPM 进程 CPU 占用 100% 的核心原因是进程处于持续计算状态或频繁上下文切换,而非单纯的 I/O 等待。

当 PHP 代码中存在死循环、正则回溯灾难或未设置超时的外部 API 请求重试时,Worker 进程会一直占用 CPU 时间片。另一种情况是 pm.max_children 配置过大,导致系统频繁进行进程调度,Master 进程 CPU 升高。如果进程状态为 D 态(不可中断睡眠)但 CPU 高,通常涉及驱动或内核级问题,但 PHP 层面多见于逻辑死锁。

分步处理

按照以下顺序操作,确保每一步都有明确的检查点,避免误杀 Master 进程导致服务全部中断。

第一步:锁定异常进程
登录服务器执行 top 命令,按 Shift+P 按 CPU 排序。观察占用最高的进程命令是否为 php-fpm: pool www 之类的_worker 进程。记录该进程 PID。

第二步:检查慢日志
查看 php-fpm 配置文件(通常在 /etc/php-fpm.d/www.conf 或 /etc/php/8.x/fpm/pool.d/www.conf),确认 request_slowlog_timeout 已开启。读取 slowlog 文件(通常在 /var/log/php-fpm/slow.log),找到对应时间点的堆栈信息,定位具体 PHP 文件行号。

第三步:系统调用追踪
如果慢日志无记录,说明代码未执行完或卡在底层。使用 strace -p <PID> 查看进程卡在哪个系统调用上。如果看到反复的 connect 或 read,说明是外部依赖阻塞。

第四步:调整超时配置
在 PHP-FPM 池配置中设置 request_terminate_timeout = 30s(根据业务调整),防止单个请求无限占用资源。修改后执行 systemctl reload php-fpm 生效。

怎么验证是否生效

执行完处理后,需通过以下指标确认问题是否解决。

PHP-FPM 进程僵死导致 CPU 占用 100% 怎么定位问题?

1. CPU 指标:使用 top 命令观察 5 分钟,PHP-FPM 进程 CPU 占用率应回落到正常水平(通常单个核的 10%-50% 以下)。

2. 日志指标:检查 php-fpm.log 中不再出现 child exited on signal 9 以外的异常退出日志,slowlog 中不再频繁出现相同堆栈。

3. 业务指标:网站响应速度恢复,监控系统中请求耗时(RT)曲线不再出现持续高位。

常见坑

在处理 PHP-FPM 高 CPU 问题时,以下场景容易导致故障扩大,需谨慎操作。

1. 误杀 Master 进程:kill 命令若指向了 php-fpm 的 Master PID,会导致所有 Worker 进程终止,服务瞬间不可用。务必通过 pstree 确认 PID 角色。

2. 忽略 OPcache:某些情况下 OPcache 缓存损坏会导致进程异常,重启 PHP-FPM 无效时需尝试清除 OPcache 缓存文件或重启 Web 服务器。

3. 盲目调大进程数:CPU 高时增加 pm.max_children 会加剧上下文切换,导致负载更高。应先降低并发数排查代码,再逐步调优。

常见问题

PHP-FPM 进程 CPU 高可以直接 kill 吗?

可以 kill 具体的 Worker 进程 PID,但不要 kill Master 进程。PHP-FPM 机制会自动补充新的 Worker,单独杀死高占用 Worker 能快速释放 CPU 资源。

开启慢日志会影响性能吗?

仅在请求超过设定阈值时才会记录,正常请求无影响。建议生产环境设置 request_slowlog_timeout 为 5s 以上,避免日志写入过频。

strace 追踪会不会加重 CPU 负担?

会。strace 会显著降低被追踪进程的速度,仅建议在测试环境或问题复现时短时使用,生产环境长时间开启可能导致服务不可用。

参考来源

  • PHP Official Documentation, "FPM Configuration", php.net.
  • Linux Man Pages, "top", "strace", "pstree".