cpu使用率过高和jvm old占用过高排查过程

cpu使用率过高和jvm old占用过高排查过程
最新回答
理想

2026-02-13 21:25:47

CPU使用率过高和JVM Old区占用过高排查过程如下:

一、报警信息确认
  • CPU使用率过高报警:接近100%。
  • JVM Old区占用过高报警:老年代内存使用率异常升高。
二、CPU使用率过高排查
  1. 定位高CPU进程

    使用 top 命令查看占用CPU最高的进程ID(PID)。

    示例结果:PID为1469的进程占用CPU最高。

  2. 定位高CPU线程

    使用 top -Hp <PID> 查看该进程中占用CPU高的线程ID(TID)。

    示例结果:发现两个高CPU线程,一个为打印异常日志的线程,另一个为GC线程。

  3. 转换线程ID并分析堆栈

    使用 printf '%xn' <TID> 将线程ID转换为十六进制。

    使用 jstack <PID> | grep <十六进制TID> -A 30 定位线程堆栈信息。

    关键发现:

    打印异常日志的线程频繁调用 ExceptionUtils.getFullStackTrace(e)(commons-lang包),导致大量对象创建。

    GC线程因频繁Full GC(FGC)占用高CPU。

三、JVM Old区占用过高排查
  1. 监控GC状态

    使用 jstat -gcutil <PID> <时间间隔> 查看JVM内存和GC情况。

    关键指标:

    E(伊甸园区)和O(老年代)使用率均接近100%。

    FGC(Full GC次数)频繁,说明老年代内存不足。

  2. 导出堆内存Dump文件

    使用 jmap -dump:format=b,file=<文件名>.dump <PID> 导出堆内存快照。

    示例命令:jmap -dump:format=b,file=heap.dump 1469

    注意:Dump文件可能较大(如2.94G),需通过 sz 等工具下载到本地分析。

  3. 分析Dump文件

    使用JDK自带的 jvisualvm 工具打开Dump文件,查看大对象和对象引用链。

    关键发现:

    大对象主要为 ElasticSearchStatusException 相关对象。

    异常堆栈指向ES查询代码,进一步定位到 RestClientFactory.getRestClient().search(searchRequest) 方法。

  4. 定位ES异常原因

    检查ES索引状态,发现部分索引未创建,导致ES查询抛出异常。

    进一步排查发现索引创建任务已停止,需重启任务并修复数据。

四、问题根源总结
  1. 直接原因:

    ES索引缺失导致查询抛出 ElasticSearchStatusException。

    异常日志打印代码未做流控,频繁调用 getFullStackTrace() 创建大量对象,填满老年代。

    老年代内存不足触发频繁FGC,进一步加剧CPU占用。

  2. 根本原因:

    缺乏对ES索引创建任务的监控和容错机制。

    异常日志处理未考虑性能影响,未限制异常打印频率。

五、解决方案
  1. 修复ES索引问题:

    重启索引创建任务,确保索引正常生成。

    修复丢失的索引数据,恢复ES查询功能。

  2. 优化异常日志处理:

    引入流控机制(如Guava RateLimiter),限制异常日志打印频率。

    避免在高频代码路径中调用 getFullStackTrace(),改用简化日志或异步记录。

  3. JVM调优(可选):

    根据业务需求调整JVM堆内存大小(如 -Xmx、-Xms)。

    优化GC策略(如改用G1 GC),减少FGC对性能的影响。

六、排查方法总结CPU占用过高排查思路
  1. top 定位高CPU进程PID。
  2. top -Hp <PID> 定位高CPU线程TID。
  3. printf '%xn' <TID> 转换线程ID为十六进制。
  4. jstack <PID> | grep <十六进制TID> -A 30 分析线程堆栈。
JVM Old区占用过高排查思路
  1. top 确认高CPU进程(通常伴随高内存使用)。
  2. jstat -gcutil <PID> <时间间隔> 监控GC和内存状态。
  3. jmap -dump:format=b,file=<文件名>.dump <PID> 导出堆内存。
  4. 使用 jvisualvm 或MAT分析Dump文件,定位大对象和内存泄漏点。

通过以上步骤,可系统性解决CPU和JVM Old区占用过高问题,并预防类似故障再次发生。