线上 CPU 飙升排查
2022年双十一凌晨2点,监控大屏突然报警:订单服务的CPU使用率从30%飙升到95%,持续了5分钟。
技术团队紧急拉起线上会议,10分钟后才定位到问题:某个开发同学在代码里加了一个性能测试脚本,每秒打印10万次日志。
这个小脚本在测试环境没问题,但上了生产环境,日志输出直接占满了CPU。
5分钟CPU打满,影响了约2000个订单的创建,直接损失约5万元。
这是一个典型的"代码问题导致线上故障"的案例。
【面试官手记】
CPU飙升是最常见的线上问题之一。我面试过很多候选人,能完整描述排查路径的不超过30%。大多数候选人只能说"用top看看",但问到"top里看到的是什么"、"怎么定位到具体代码"就卡壳了。CPU排查的关键是层层定位:先定位进程,再定位线程,最后定位代码。
一、CPU飙升的常见原因 🔴
1.1 五大原因
1.2 量化指标
1.3 面试追问
面试官:线上CPU打满了,怎么排查?
候选人:首先用top命令看看是哪个进程CPU高。
面试官:top里显示的PID是什么?怎么进一步定位?
候选人:用top -Hp pid,看看是哪个线程CPU高。
面试官:找到了高CPU的线程后,怎么定位到代码?
候选人:把线程ID转成16进制,然后用jstack打印线程栈,找到对应线程。
【面试官心理】
CPU排查的追问通常很深入。能回答出"top -Hp"的候选人,说明有过实际排查经验;能回答出"转16进制"的候选人,说明知道Java线程ID和系统线程ID的对应关系;能回答出"用arthas trace"的候选人,说明知道更高级的排查工具。
二、排查流程 🔴
2.1 第一步:top定位进程
2.2 第二步:top定位线程
2.3 第三步:jstack定位代码
2.4 第四步:arthas精确定位
三、常见问题定位 🟡
3.1 死循环
3.2 正则表达式灾难
3.3 频繁GC
四、生产避坑 🟡
4.1 CPU排查的五大坑
坑1:只看user%不看sys%
坑2:忽略load average
坑3:只抓一次jstack
坑4:忽略GC线程
坑5:只看当前时刻
4.2 快速止血方案
五、排查工具速查 🟢
六、真实面试回放 🟡
面试官:线上Java服务CPU打满,怎么排查?
候选人(大张):分四步走。
第一步:用 top 看看是哪个进程CPU高。
第二步:用 top -Hp pid 看看是哪个线程CPU高,记下线程ID。
第三步:用 printf '%x\n' 线程ID 转成16进制,然后用 jstack pid | grep 16进制 找到对应的线程栈。
第四步:看线程栈里的代码,找出问题。
面试官:jstack里看到的线程状态有哪些?
大张:有五种:
- RUNNABLE:正在运行
- BLOCKED:被阻塞等待锁
- WAITING:等待被唤醒
- TIMED_WAITING:限时等待
- NEW/TERMINATED:创建/结束状态
CPU高通常看 RUNNABLE 状态的线程。
面试官:如果jstack里看到大量线程处于BLOCKED状态呢?
大张:说明有锁竞争。很多线程在等待同一个锁。
要看线程栈里等待的是什么锁,然后看持有锁的线程在做什么。
如果持有锁的线程在执行耗时操作(如数据库查询、网络IO),其他线程就会长时间BLOCKED。
【面试官手记】
大张这场面试的亮点:
排查流程完整:top → top -Hp → jstack
知道线程ID转换:10进制转16进制
知道线程状态含义:BLOCKED说明有锁竞争
知道进一步分析:看持有锁的线程
CPU排查是P6工程师必备技能,能完整回答的候选人,说明有生产环境排查经验。
CPU飙升排查的核心是层层定位:进程 → 线程 → 代码。记住四步排查法:
- top:定位高CPU的进程
- top -Hp:定位高CPU的线程
- jstack:打印线程栈,定位代码
- arthas:精确定位方法耗时
快速止血:限流 → 重启 → 扩容 → 降级。