ECS CPU 使用率飙高排查实战:从 top 到线程栈、perf 的六步流程
云服务器监控里 CPU 使用率突然拉到 90% 以上,是运维里最常见的告警之一。很多人的第一反应是重启或者直接升配,结果问题过一阵又回来。这篇文章整理我在 ECS(Linux)上排查 CPU 飙高时用的一套固定流程,每一步都有对应命令,可以边看边在自己的机器上试。
一、先看整体:是谁在吃 CPU,吃的是哪一类
登录服务器后先执行 top,并按 1 展开每个核心。重点看顶部一行的几个数值:
- us 高:用户态进程在计算,多半是业务代码、死循环、正则回溯或频繁序列化。
- sy 高:内核态占用大,常见于系统调用过多、频繁创建线程或进程、网络小包很多。
- wa 高:CPU 在等磁盘 IO,进程看起来慢,但真正的瓶颈是磁盘,需要转去查 iostat。
- si 高:软中断多,常见于单个网卡队列被打满。
- st 高:被宿主机或其他实例抢占,说明资源被争用,应考虑更换规格或联系技术支持。
先判断类型,再决定往哪个方向查,可以少走很多弯路。
二、定位到具体进程和线程
在 top 里按 P 按 CPU 排序,记下占用最高的 PID。如果是多线程程序,进程总占用往往掩盖了真正的热点,需要继续看线程:
top -H -p <PID> pidstat -t -p <PID> 1 5
pidstat 来自 sysstat 包,可以看到每个线程在用户态和内核态各占多少。找到最高的线程号 TID 后,下一步才有针对性。
三、Java 程序:把线程号对应到代码
如果业务是 Java,把 TID 转成十六进制,再到线程栈里查找:
printf "%x\n" <TID> jstack <PID> | grep -A 20 "nid=0x<十六进制TID>"
看栈顶是业务方法、锁竞争,还是 GC 线程。如果是名为 GC task thread 的线程占满 CPU,说明频繁 Full GC,要回头检查堆大小和内存泄漏,而不是继续看业务逻辑。建议间隔几秒多抓几次 jstack,只出现一次的栈不一定是热点。
四、其他语言:用 perf 或 strace 看热点
对 C/C++、Go、Python 等程序,可以用 perf 采样:
perf top -p <PID> perf record -g -p <PID> -- sleep 30 perf report
perf top 能直接看到最耗时的函数。如果怀疑是系统调用太多(sy 偏高),可以用 strace -c -p <PID> 统计一段时间内各系统调用的次数和耗时,再按 Ctrl+C 结束查看汇总。注意 strace 本身有开销,线上使用时间不要太长。
五、别忘了排除不是业务进程的情况
有几类情况和业务代码无关,但也会让 CPU 飙高:
- 异常进程:名字陌生、从 /tmp 或隐藏目录启动的进程,要检查是否被入侵,同时核对安全组是否把管理端口暴露给了公网。
- 定时任务:用 crontab -l 和 /etc/cron.d 检查是否有日志压缩、备份脚本在业务高峰期同时运行。
- 日志风暴:某个错误被不断重试,每次都打印大量日志,CPU 和磁盘同时升高,修复根因后才会恢复。
- 连接数暴涨:用 ss -s 看连接状态,TIME_WAIT 或 SYN_RECV 异常多时,要联系网络与应用一起排查。
六、处理与复盘
止血时优先限流或下线问题实例,不要一上来就 kill 进程,否则现场没了,原因就查不出来。可以先保存 top、jstack、perf 的输出再处理。事后建议做三件事:给 CPU 使用率设置分级告警,配置 80% 先预警;把关键命令的输出定时落盘,下次出问题有历史可比;对热点代码做压测并补上超时与限流。
总结一下顺序:先看 top 判断是哪类 CPU,再定位进程和线程,Java 用 jstack,其他用 perf 或 strace,最后排除异常进程、定时任务和日志风暴。按这个顺序走,大多数 CPU 飙高问题都能在半小时内找到方向。
- 点赞
- 收藏
- 关注作者
评论(0)