Linux 服务器 CPU 占用飙高:从 top 到定位代码的排查思路
【摘要】 从 load 与 us/sy/wa 判断方向,用 top -Hp 定位线程,再借助 jstack、py-spy、perf 定位热点代码,并总结常见原因与预防措施。
一、先判断现象:是真忙还是假忙
收到 CPU 告警后,不要急着杀进程。先执行 uptime 看 load average,再用 top 看 CPU 行各项占比:
- us 高:用户态计算多,多是业务代码热点、死循环、正则回溯。
- sy 高:内核态开销大,常见于频繁系统调用、上下文切换、锁竞争。
- wa 高:在等磁盘或网络 IO,CPU 并不忙,应转去查 iostat。
- si 高:软中断多,常见于网卡小包风暴,可看 /proc/softirqs。
load 高而 CPU 不高,多半是 IO 等待或线程排队,思路完全不同。
二、找到进程和线程
top -c # 按 P 按 CPU 排序
top -Hp <pid> # 查看该进程内各线程的 CPU 占用
记下最耗 CPU 的线程号(TID),按 1 可查看每个核心,判断是单核打满还是整体饱和。
三、把线程号映射到代码
Java:线程号转 16 进制,在 jstack 输出中匹配 nid。
printf '%x\n' 12345 # 得到 3039
jstack <pid> | grep -A 20 'nid=0x3039'
连续抓三次 jstack 对比,反复出现在同一方法栈的就是热点。若线程名是 GC task thread,说明 GC 频繁,应看 jstat -gcutil。
Python:py-spy dump --pid <pid>,无需重启即可看调用栈。
C/C++:perf top -p <pid> 采样查看热点函数。
四、常见原因
- 死循环或空转:条件写错,或无退避的重试循环。
- GC 频繁:内存泄漏或堆过小,Full GC 反复触发。
- 正则回溯:嵌套量词遇到特殊输入,耗时指数增长。
- 锁竞争:线程频繁切换,sy 与上下文切换同时升高,可用 pidstat -w 确认。
- 软中断:网络包集中在单核,需开启 RPS/RSS 分散,或排查异常流量。
五、处理与预防
止血:先限流、降级或摘除异常节点,保留现场(jstack、火焰图)后再重启。
根治:修复热点代码,给正则和循环加超时与上限,为线程池和队列设边界。
预防:
- 监控告警:对 CPU 占比、load、GC 次数、线程数设置分级告警。
- 常态化压测:上线前压测,提前暴露热点和锁竞争。
- 灰度发布:新版本先小流量观察,异常即回滚。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)