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

核心导读:记录一次低配云服务器上 PHP-FPM 进程频繁打满 CPU 的排查过程,包括进程配置调优、慢日志定位以及恶意流量拦截的实际解决步骤。

这几天在维护一台 2G 内存的轻量云服务器,上面挂着两个 WordPress 博客。前天下午手机突然收到云监控报警,CPU 使用率直接飙到了 98%,前台页面也偶尔开始弹 502 Bad Gateway。SSH 登录服务器用 top 看了一眼,好几个 php-fpm: pool www 进程排在前面,每个都吃掉 30% 到 50% 的 CPU。

这类问题平时建站很常见,但如果不把排查链路理清楚,往往改完配置过几天又会崩。这里把处理过程和目前调校好的参数备忘下来,给遇到同样情况的朋友一个参考。

1. 临时恢复与紧急处置

排查前最重要的是让线上站点先恢复访问。如果此时 CPU 已经卡死、后台进不去,可以通过 SSH 终端快速平滑重载 PHP-FPM:

bash
# 查看具体运行的 PHP 版本,以 php 7.4 为例 systemctl reload php-fpm-74 # 或者在宝塔环境直接执行脚本重启 /etc/init.d/php-fpm-74 reload

重载之后,挂起僵死的 worker 进程会被强制释放,CPU 会立刻回落。但这只是指标不治本,接下来需要排查配置和具体触发原因。

2. 关键参数设置参考

宝塔安装 PHP 时给的默认进程配置往往比较通用,如果服务器配置本身就不高(1G-2G 内存),默认参数很容易在小并发下就把内存吃满,进而导致频繁换页或 CPU 暴涨。

在宝塔面板打开 软件商店 -> 对应 PHP 版本 -> 设置 -> 性能调整,这里重点调整几个参数:

  • pm(运行模式):建议选择 ondemand(按需分配)或 dynamic(动态进程)。低配小内存机型推荐 ondemand,空闲时自动回收内存。
  • pm.max_children(最大子进程数):单个 PHP-FPM 进程平均占用 20MB~40MB 内存,如果机器只剩 1G 内存给 PHP,最多开 20-30 个。设置过大会直接导致物理内存耗尽触发 Swap 甚至 OOM 杀进程。
  • pm.max_requests(每个进程最大请求数):建议设为 500 到 1000。PHP 代码或扩展难免有内存泄露,这个参数可以让 worker 进程处理满一定数量后自动退出重建,防止单个进程越来越大。

根据日常折腾经验,低配机器可以参考以下配置基准:

服务器配置pm 模式pm.max_childrenpm.start_serverspm.max_requests建议 Swap 大小
1核 1Gondemand1025001024 MB
2核 2Gdynamic2058002048 MB
2核 4Gdynamic401010242048 MB

修改完后点击保存,配置会自动重载生效。

3. 查看日志确认具体原因

调整了进程数只能保证系统不轻易被耗尽,如果 CPU 依旧高频居高不下,多半是代码里有死循环、慢查询,或者有恶意脚本在扫站。

开启 PHP 慢日志(Slow Log)
在 PHP 配置文件中确认开启慢日志,定位具体卡在哪个文件的哪一行代码:

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

保存后观察 slow.log,如果某个 SQL 查询没有加索引,或者某个插件在远程拉取数据超时,日志里会把函数调用栈写得清清楚楚,直接针对性排查对应代码即可。

检查 Nginx 访问日志
打开 /www/wwwlogs/你的域名.log,用命令看下最近的高频请求 IP:

bash
tail -n 5000 /www/wwwlogs/your_domain.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 10

如果发现某个 IP 在短时间内有上千次 POST /xmlrpc.php 或者暴力尝试后台登录,说明被扫了。直接在 Nginx 配置中把恶意路径禁掉,或者在宝塔自带的防火墙/安全规则里拉黑该 IP 即可。

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

有时候参数设得很保守,日志里也没有慢查询,但 CPU 依然每隔一阵子就爆满,这通常是因为缓存机制缺失或者后台任务积压:

  1. 未启用 OPcache:在 PHP 扩展中务必安装 opcache,能显著减少脚本重复解析的 CPU 开销,静态页面和重复代码直接从内存读取执行。
  2. WordPress 的 WP-Cron 机制:每次有用户访问,WordPress 都会尝试检查定时任务,并发一高就会造成重复执行。可以在 wp-config.php 中加入 define('DISABLE_WP_CRON', true);,改用系统 Crontab 每隔半小时通过命令行静默触发一次。
  3. 突发爬虫抓取:很多非主流搜索引擎爬虫(如 Bytespider、SemrushBot 等)频率极高,可以直接在 robots.txt 或 Nginx 层通过 user_agent 拦截掉,没必要浪费服务器算力给它们跑动态解析。

常见问题与解答 (FAQ)

Q 改完 PHP-FPM 性能参数后,必须重启 PHP 吗?

宝塔面板在保存配置时通常会自动执行 reload,不需要强行重启服务;如果不放心,在面板点击‘重载配置’即可平滑生效,不会中断已有访问。

Q 给小内存机器加 Swap 虚拟内存,会导致磁盘读写变卡吗?

Swap 主要是充当安全垫防止突发流量引发 OOM 崩溃,只要把 swappiness 降到 10 左右让系统优先使用物理内存,日常并不会产生明显的磁盘 IO 负担。

返回运维知识库