宝塔 PHP-FPM 进程 CPU 飙高排查思路与参数优化记录

核心导读:记录一次服务器 PHP-FPM 进程把 CPU 打满的排查过程。整理了进程爆满时的应急命令、不同内存规格下的参数配置建议,以及利用慢日志定位卡顿脚本的方法。

前几天深夜收到云监控报警,一台跑 WordPress 和几个自用小工具的 2G 内存轻量服务器 CPU 突然拉到 100%,进宝塔后台一看,系统负载飘红,十几个 php-fpm 进程把 CPU 核心吃得死死的,前台直接报 502 Bad Gateway。

类似的问题之前也踩过几次坑,通常要么是进程配置不合理导致系统频繁调度,要么是有恶意爬虫在刷动态接口,或者是某个 PHP 脚本陷入了死循环。这里把当时的排查步骤和调优参数整理一下,留个备忘。

1. 紧急处置与现场确认

CPU 飙到 100% 且站点已经打不开时,首要任务是让业务先恢复,再找原因。

先通过 SSH 连上服务器,用 top 命令看一眼资源占用情况:

bash
top -c

在进程列表中按键盘大写 P,可以看到按 CPU 占用排序的进程。如果看到一长串 php-fpm: pool www,且单进程占用都在 80%-100% 之间,基本可以确认是 PHP 处理逻辑卡住或者并发积压了。

此时直接在终端重载或重启 PHP 服务,先释放资源:

bash
# 以 PHP 7.4 为例,执行重载 /etc/init.d/php-fpm-74 reload

如果 reload 之后几秒钟 CPU 又立刻飙满,说明正在有外部请求持续打进来,可以先暂时切断访问或者重启 Nginx 配合排查。

2. 关键参数设置与机器配置参考

宝塔安装完 PHP 后,默认的并发配置往往比较通用,小内存机器跑起来很容易爆。

在宝塔面板的【软件商店】->【已安装】->【PHP 设置】->【性能调整】中,重点调整这几个核心参数:

  • pm(运行模式):推荐设为 dynamic(动态),让系统按需创建和回收进程,避免静态模式常驻占用过多内存。
  • max_children(最大子进程数):这是最关键的阀值。单个 PHP-FPM 进程一般占用 20MB - 40MB 内存。如果设得太大,超出物理内存就会疯狂使用 Swap,进而导致 CPU 发生严重的上下文切换并飙升。
  • request_terminate_timeout(脚本超时时间):默认可能是 0(不限制)或一个很大的数值。建议设置在 3060 秒之间,强制结束卡死超时的请求,防止僵尸进程常驻。

根据不同内存规格,我平时比较习惯使用下面这套相对稳妥的参数配置:

服务器配置max_childrenstart_serversmin_spare_serversmax_spare_servers建议 Swap 大小
1核 1G102251024 MB
2核 2G2555152048 MB
2核 4G501010302048 MB
说明:Swap(虚拟内存)的作用是作为安全缓冲垫,在突然并发高峰时防止系统直接触发 OOM 强杀进程。小内存机器一定要在宝塔【Linux 工具箱】里建一个大小相当的 Swap 分区。

3. 开启慢日志抓出具体卡死的文件

参数改好了,只是限制了并发上限,并不能从根本上解决“为什么个别脚本会吃满 CPU”。如果某个页面有慢查询或者死循环,单次请求就能把一个 CPU 核心占满 30 秒。

排查这类问题,最有效的方法就是开启 PHP 慢日志(Slow Log):

在宝塔对应 PHP 版本的【配置文件】(php-fpm.conf)中,找到以下两行并取消注释(或修改数值):

ini
request_slowlog_timeout = 3 slowlog = /www/server/php/74/var/log/slow.log

这里的意思是:只要执行时间超过 3 秒的请求,都会把完整的 PHP 堆栈调用栈记录到 slow.log 中。修改后平滑重启 PHP。

等再次出现卡顿或运行一段时间后,查看该日志:

bash
tail -n 50 /www/server/php/74/var/log/slow.log

日志里会明确写出是哪个网站的哪一行代码执行超时。常见的元凶通常有两类:

  1. 远程 API 调用超时:比如调用微信支付、海外第三方接口,网络卡住导致进程挂起。
  2. 复杂的无索引 SQL 查询:数据库被拖慢,导致 PHP 进程一直阻塞等待。

4. 为什么参数改完还是会偶尔爆满?

在实际运维中,经常有人反馈:“参数已经压得很低了,脚本也没问题,怎么还是会被打崩?”

这种情况绝大部分是由于恶意爬虫抓取针对搜索接口的小规模恶意请求造成的。

在宝塔的 Nginx 日志中,看一眼最近的访问记录:

bash
tail -f /www/wwwlogs/你的域名.log

如果发现大量的海外 IP 在狂刷 /?s=xxx 这类站内搜索,或者某个爬虫不遵守 robots.txt 每秒发起几十次动态请求,PHP 就会因为短时间内大量唤醒子进程而迅速耗尽算力。

对于这种情况,单靠改 PHP 已经不够用了,需要把防御前置到 Nginx 层:

  • 在 Nginx 中对频繁请求的 IP 做限速(limit_req 模块)。
  • 禁止未知的爬虫 User-Agent 访问动态页面。
  • 如果平时不想频繁手工翻日志过滤 IP,也可以配合宝塔自带的 Nginx 防火墙插件或网站监控报表,查看 IP 访问频次并直接做封禁拦截。

把高频无效请求挡在 Nginx 外层之后,PHP-FPM 的负载自然就会恢复正常。

常见问题与解答 (FAQ)

Q 改完 PHP 性能参数后,必须要重启服务器吗?

不需要重启服务器。在宝塔面板的 PHP 设置界面点击「重载配置」即可平滑生效,正在处理的请求不会中断。

Q 云服务器加了 Swap 之后,会导致磁盘性能下降吗?

正常情况下物理内存足够用时,系统不会频繁读写 Swap,对磁盘没有影响;只有在内存瞬间爆满时才会写入,起到防止系统死机崩盘的缓冲保护作用。

返回运维知识库