线上 CPU 飙升,如何排查分析处理?

遇到cpu突然飙高,要快速止血。

  • 若CPU持续100%且严重影响核心业务,及时重启实例,但需先保存现场信息(如堆栈、内存快照)

1. 快速定位高 CPU 进程

目标:确认是哪个进程导致 CPU 使用率过高。
工具tophtopps
操作

# 查看实时 CPU 使用情况(按 P 按 CPU 排序)
top -c
# 或使用精简版
ps -eo pid,ppid,cmd,%cpu,%mem --sort=-%cpu | head -n 10

输出示例

PID   USER  PR  NI    VIRT    RES    SHR S  %CPU %MEM  TIME+   COMMAND
1234  app   20   0   10.2g   3.2g   1.1g R  98.6 20.3  10:30.1 java

结论:确认目标进程(如 PID=1234 的 Java 进程)。

2. 定位进程内高 CPU 线程

目标:找到进程内消耗 CPU 最高的线程。
工具top(线程模式)、ps
操作

# 进入 top 后按 H 切换线程模式,或直接查看线程
top -H -p 1234
# 或使用 ps
ps -T -p 1234 -o tid,pcpu,state,cmd --sort=-pcpu | head -n 5

输出示例

TID   %CPU  STATE  COMMAND
4567  95.2  R      java

结论:记录高 CPU 线程 ID(如 TID=4567),需转换为 16 进制(0x11D7)。

3. 获取线程堆栈信息(以 Java 为例)

目标:分析线程正在执行的代码。
工具jstackArthas
操作

# 生成线程快照
jstack 1234 > thread_dump.txt
# 或使用 Arthas 实时监控
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar 1234  # 附加到目标进程
thread -n 3                     # 查看最忙的 3 个线程

分析
在 thread_dump.txt 中搜索 nid=0x11D7,找到对应线程的堆栈:

"HighCpuThread" #32 daemon prio=5 os_prio=0 tid=0x00007f8a4410a800 nid=0x11d7 runnable [0x00007f8a2c4f0000]
   java.lang.Thread.State: RUNNABLE
        at com.example.App.loopMethod(App.java:20)  // 死循环代码位置

4. 分析问题根源

常见原因及排查方法

问题类型排查方法
死循环/无限递归检查堆栈中频繁执行的代码(如 while(true)、未退出的递归调用)。
频繁 GC检查 GC 日志(jstat -gcutil 1234 1000),观察是否因 Full GC 导致 CPU 飙升。
锁竞争查看线程是否处于 BLOCKED 状态(如 synchronized 或 ReentrantLock 竞争)。
外部依赖阻塞检查网络或 IO 操作(如数据库慢查询、HTTP 请求超时)。

5. 解决方案与优化

根据原因针对性处理

  1. 代码逻辑问题(如死循环)
    • 修复代码逻辑,避免无限循环或递归。
    • 示例// 修复前(无退出条件)
      while (true) { processData(); }

      // 修复后(添加退出条件)
      while (isRunning) { processData(); }
  2. GC 问题
    • 调整 JVM 参数(如增大堆内存、优化垃圾回收器)。
    • 示例# 使用 G1 垃圾回收器并增加堆内存
      java -Xms4g -Xmx4g -XX:+UseG1GC -jar app.jar
  3. 锁竞争
    • 优化锁粒度(如缩小同步代码块)、使用无锁数据结构(如 ConcurrentHashMap)。
    • 示例// 缩小锁范围
      synchronized (this) {  // 原锁整个方法
          updateSharedResource();
      }
  4. 外部依赖问题
    • 优化慢查询(如添加数据库索引)、设置超时与熔断(如 Hystrix、Resilience4j)。

6. 预防措施

  • 监控告警:部署 Prometheus + Grafana 监控 CPU、GC、线程状态。
  • 压测与 Profiling:定期使用 JMeter 压测,结合 Async Profiler 生成火焰图分析热点代码。
  • 代码审查:避免循环内阻塞操作、确保资源释放(如关闭连接)。

高频问题场景及诊断方法

场景诊断工具/方法典型case
线程池爆炸jstack查看线程前缀 + 监控线程池指标(如DynamicTP)未配置拒绝策略导致创建数千线程
热key问题Redis集群代理层监控(如自研proxy) + redis-cli --hotkeys突发新闻导致缓存击穿
RPC链路异常全链路Trace中筛选高耗时调用 + 下游服务熔断日志下游超时引发上游线程阻塞
JIT编译风暴-XX:+PrintCompilation日志 + JFR录制高频部署导致反复编译
内核态CPU高perf top -k查看内核调用 + systemtap分析容器网络插件软中断不均

总结流程图

CPU 飙升 → top 定位进程 → 线程分析 → 堆栈快照 → 代码/资源分析 → 修复优化

声明:来自程序员千羽,仅代表创作者观点。链接:https://eyangzhen.com/2092.html

程序员千羽的头像程序员千羽

相关推荐

关注我们
关注我们
购买服务
购买服务
返回顶部