负载高不等于CPU高,需先用uptime或/proc/loadavg判断是否持续超CPU核心数;若4核机load长期>4即过载,>8则存在严重I/O或锁排队;配合nproc与uptime可确认真实过载。

负载高不等于 CPU 高,先看 uptime 或 cat /proc/loadavg 的三个值是否持续超过 CPU 核心数 —— 超了就得动手查,别急着杀进程。
怎么看负载是不是真高
Linux 的 load average 是「就绪态 + 不可中断态」进程的平均数,不是 CPU 使用率。4 核机器 load 长期 > 4 就得警惕;> 8 基本说明有严重排队(I/O 或锁)。
用这条命令一次性看清:
nproc && uptime比如输出
4 和 load average: 6.21, 5.88, 7.03,就确认是真实过载。如果
top 里 %CPU 总和才 30%,但 load 却是 12,那大概率是磁盘或网络 I/O 卡住了进程,不是代码慢。
快速筛出 PHP-FPM 是否失控
PHP-FPM 进程泛滥是最常见原因,尤其在宝塔、LNMP 等一键环境里容易配错。
执行这三步:
- 查当前总进程数:
ps -ef | grep php-fpm | grep -v grep | wc -l—— 如果远超pm.max_children(通常在/etc/php-fpm.d/www.conf),说明 spawn 失控 - 查活跃连接:
netstat -anp | grep php-fpm | grep ESTABLISHED | wc -l—— 若接近或等于进程总数,说明请求积压,不是空闲进程多 - 查配置实际生效值:
php-fpm -t && systemctl show php-fpm | grep LimitNOFILE—— 有时pm.max_children=100,但系统级文件描述符限制(LimitNOFILE)只有 1024,会导致 fork 失败+重试风暴
用 strace 定位卡死的 PHP 进程
当某个 php-fpm 子进程 CPU 占用低但状态长期为 D 或 R,它很可能卡在系统调用里。
挑一个可疑 PID(比如 17487),运行:
sudo strace -tt -p 17487 -e trace=epoll_wait,poll,read,write,connect,accept
观察输出:
- 反复出现
poll([{fd=9, ...}, ...且无返回 → 卡在等待某个 socket 或缓存连接(如 Redis、MySQL) - 长时间停在
read(3,→ 卡在读取文件、日志或慢响应的上游 API - 完全没输出 → 很可能在纯 PHP 层死循环(比如递归没出口、正则回溯爆炸)
lsof -p 17487 看 fd=9 对应什么资源,比盲猜快得多。立即学习“PHP免费学习笔记(深入)”;
别漏掉 nginx 和 slowlog 的协同线索
单看 PHP 进程容易误判。nginx 的 $request_time 和 PHP 的 slowlog 必须对照看:
- 开
slowlog:在www.conf加slowlog = /var/log/php-fpm-slow.log和request_slowlog_timeout = 2s - nginx access log 必须含
$request_time,否则看不出是 PHP 慢还是 upstream 慢 - 如果 nginx 日志里
$request_time高但 slowlog 没记录 → 问题在 nginx 到 php-fpm 的通信(如 socket 权限、超时、backlog 溢出) - 如果两者都高且集中在某 URL → 直接去查那个脚本里的数据库查询、file_get_contents 或第三方 SDK 调用
request_slowlog_timeout 设太短(如 100ms)会刷屏,设太长(>5s)可能错过真实瓶颈。
真正难的不是找到哪个进程在耗资源,而是判断它为什么不能及时释放 —— 是等磁盘?等网络?等锁?还是自己写了个停不下来的循环?每条 strace 输出、每个 lsof fd、每行 slowlog 里的栈帧,都是指向具体阻塞点的路标。别跳过它们。



















