宝塔PHP-FPM占用CPU过高排查与参数优化记录

核心导读:记一次宝塔面板中 PHP-FPM 进程频繁占满 CPU 导致网站卡顿甚至 502 的排查过程,附上针对小内存机器的进程参数调整与定位思路。

这几天在维护一台 2G 内存的云服务器时,监控频频发来报警,看后台发现几个 php-fpm 进程常年把单核 CPU 吃满,偶尔还会连带出现 Nginx 502 Bad Gateway 报错。

PHP-FPM 占用 CPU 偏高通常就两个大方向:要么是并发请求上来了,进程配置不合理导致系统在频繁创建/销毁进程;要么是代码里有死循环、慢查询,把单个进程长时间卡在执行状态。把这次的定位步骤和目前比较稳的配置随手记下来,省得以后换机器又得重头翻文档。

1. 临时应急与现场观察

登录服务器后第一件事不要盲目重启,先用终端连上去看看实际开销:

bash
top -c

输入大写 P 让进程按 CPU 排序。如果看到好几个类似 php-fpm: pool www 的子进程 CPU 占用都在 90% 以上,记下对应的 PID。

如果站点已经卡死,可以在宝塔面板的【软件商店】->【已安装】-> 找到对应的 PHP 版本点击【重启】,或者命令行执行 systemctl restart php-fpm-74(根据实际版本修改)。但这只能救急,几分钟后请求一多大概率还会满载。

2. 关键参数设置参考

宝塔默认安装完 PHP 后,PHP-FPM 的进程管理模式(pm)通常是 dynamic。如果给的 max_children 设得太大,小内存机器在并发进来时会迅速耗尽物理内存,系统开始大量走 Swap,导致 CPU 的 iowait 和系统开销瞬间暴增。

在宝塔【PHP设置】->【性能调整】里,可以参考以下针对常规配置服务器的调整值:

服务器配置建议运行模式 (pm)max_childrenstart_serversmin_spare_serversmax_spare_serversSwap 大小
1核 1Gondemand / dynamic102251024 MB
2核 2Gdynamic2055152048 MB
2核 4Gdynamic401010302048 MB
4核 8Gdynamic / static80202060不需要或 2G

几个参数的简要解释:

  • max_children:同时处理请求的最大子进程数。一个 PHP-FPM 进程平均占用 20MB~40MB 内存(如果有图片处理库可能会更高)。2G 内存扣除 MySQL 和系统常驻,留给 PHP 的一般在 800MB 左右,给到 20-25 是比较安全的上限。
  • max_requests:强烈建议不要设为 0。可以设为 1024 或 2048。它的作用是让子进程处理完指定数量的请求后自动退出并释放内存,有效防止第三方扩展或代码内存泄漏导致的资源积压。

3. 查看慢日志确认具体脚本

参数改小只能防止机器被直接打死,如果依然有单个进程持续占满 CPU,必须找出到底是哪一行代码在卡死进程。

打开宝塔对应的 PHP 配置文件,检查或开启慢日志(Slowlog):

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

这里的 request_slowlog_timeout = 3 表示任何执行超过 3 秒的请求都会被记录到慢日志中。保存后在宝塔面板平滑重载一次 PHP。

等 CPU 再次飙升时,直接在终端 tail 慢日志:

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

通常慢日志里会直接标出具体的 PHP 文件名以及卡住的行数。常见的坑点包括:

  • WordPress 插件调用了外部不可达的 API 接口,没有设置超时时间;
  • 数据库单表十几万行数据没有建索引,执行了全表扫描排序;
  • 文件上传目录中被注入了死循环执行的后门脚本。

4. 为什么改完参数后还是偶尔会被打崩?

如果代码本身没有死循环,但某一时段 CPU 突然被打高,多半是遇到了扫描器或者流氓爬虫。

  1. 高频爬虫抓取动态搜索页
打开网站的 Nginx 访问日志,看看有没有大量针对 /search/?s= 等动态查询接口的高频请求。这种接口不走静态缓存,一秒来几个就能把数据库和 PHP-FPM 全拖慢。这种情况建议在 Nginx 层通过 limit_req 模块限制单 IP 访问频率,或者直接在 Nginx 配置里屏蔽常见恶意 User-Agent(如 ScrapySemrushBot 等)。
  1. 检查 Opcache 是否开启
宝塔安装的 PHP 通常默认包含了 Zend Opcache,但在个别精简安装中可能没开。进入【PHP管理】->【安装扩展】,确认 opcache 处于已安装状态。开启它可以避免每次请求都重复编译 PHP 文件,能直接砍掉 30% 到 50% 的脚本 CPU 消耗。
  1. 利用日志分析插件辅助观察
如果不想每次都去翻命令行看 access.log,也可以在宝塔里安装【网站监控报表】或者使用 Nginx 自带的访问状态,重点看 CPU 飙升时段的 Top IP 和请求 URL。先定位到源头流量,再配合限制策略,基本上就能把 PHP-FPM 的负载稳定在安全区间了。

常见问题与解答 (FAQ)

Q 修改了 PHP-FPM 的配置参数后,需要重启 Nginx 吗?

不需要重启 Nginx,只需要在宝塔后台对应的 PHP 设置中点击“重载配置”或“重启”即可使进程参数生效。

Q 小内存服务器设置了 Swap,会导致 CPU 占用更高吗?

如果物理内存严重不足导致频繁读写 Swap,磁盘 I/O 阻塞会转化为 CPU 的 iowait 升高;因此 Swap 只是防崩兜底,核心还是要通过调小 max_children 避免把物理内存耗尽。

返回运维知识库