会员登录|免费注册|忘记密码|管理入口 返回主站||保存桌面|手机浏览|联系方式|购物车
线上CPU100%及应用OOM的排查和解决过程
2024-12-29IP属地 湖北0

点击上方☝,轻松关注

及时获取有趣有料的技术文章

最近工作又遇到几次线上告警的问题,排查基本上就是cup100%以及内存OOM问题,再分享一下之前遇到这类问题排查的一些思路和过程,希望对你有所帮助,感谢你的阅读。

Spring Cloud F版。

这一步可忽略/跳过,与实际公司的的健康检查相关,不具有通用性。

①查看服务的进程是否存在。

ps -ef | grep  服务名 ps -aux | grep 服务名

②查看对应服务健康检查的地址是否正常,检查 ip port 是否正确

是不是告警服务检查的url配置错了,一般这个不会出现问题


③验证健康检查地址

这个健康检查地址如:http://192.168.1.110:20606/serviceCheck 检查 IP 和 Port 是否正确。

oracle官方给出了这个错误产生的原因和解决方法:Exception in thread thread_name: java.lang.OutOfMemoryError: GC Overhead limit exceeded Cause: The detail message "GC overhead limit exceeded" indicates that the garbage collector is running all the time and Java program is making very slow progress. After a garbage collection, if the Java process is spending more than approximately 98% of its time doing garbage collection and if it is recovering less than 2% of the heap and has been doing so far the last 5 (compile time constant) consecutive garbage collections, then a java.lang.OutOfMemoryError is thrown. This exception is typically thrown because the amount of live data barely fits into the Java heap having little free space for new allocations. Action: Increase the heap size. The java.lang.OutOfMemoryError exception for GC Overhead limit exceeded can be turned off with the command line flag -XX:-UseGCOverheadLimit.

上面tips来源:java.lang.OutOfMemoryError GC overhead limit exceeded原因分析及解决方案


top -H -p pid 保存文件:top -H -n 1 -p pid > /tmp/pid_top.txt

查看 PID:11441 下面的线程,发现有几个线程占用cpu较高。


1、打印系统负载快照
top -b -n 2 > /tmp/top.txt
top -H -n 1 -p pid > /tmp/pid_top.txt


2、cpu升序打印进程对应线程列表
ps -mp-o THREAD,tid,time | sort -k2r > /tmp/进程号_threads.txt


3、看tcp连接数 (最好多次采样)
lsof -p 进程号 > /tmp/进程号_lsof.txt
lsof -p 进程号 > /tmp/进程号_lsof2.txt


4、查看线程信息 (最好多次采样)
jstack -l 进程号 > /tmp/进程号_jstack.txt
jstack -l 进程号 > /tmp/进程号_jstack2.txt
jstack -l 进程号 > /tmp/进程号_jstack3.txt


5、查看堆内存占用概况
jmap -heap 进程号 > /tmp/进程号_jmap_heap.txt


6、查看堆中对象的统计信息
jmap -histo 进程号 | head -n 100 > /tmp/进程号_jmap_histo.txt


7、查看GC统计信息
jstat -gcutil 进程号 > /tmp/进程号_jstat_gc.txt

8、生产对堆快照Heap dump
jmap -dump:format=b,file=/tmp/进程号_jmap_dump.hprof 进程号

堆的全部数据,生成的文件较大。

jmap -dump:live,format=b,file=/tmp/进程号_live_jmap_dump.hprof 进程号

dump:live,这个参数表示我们需要抓取目前在生命周期内的内存对象,也就是说GC收不走的对象,一般用这个就行。

拿到出现问题的快照数据,然后重启服务。


根据上述的操作,已经获取了出现问题的服务的GC信息、线程堆栈、堆快照等数据。下面就进行分析,看问题到底出在哪里。

转换线程ID

从jstack生成的线程堆栈进程分析。

将 上面线程ID 为
11447 :0x2cb7
11444 :0x2cb4
11445 :0x2cb5
11446 :0x2cb6
转为 16进制(jstack命令输出文件记录的线程ID是16进制)。
第一种转换方法 :

第二种转换方法 :  在转换的结果加上 0x即可。

查找线程堆栈

发现这些线程都是在做GC操作。

  • S0:幸存1区当前使用比例

  • S1:幸存2区当前使用比例

  • E:Eden Space(伊甸园)区使用比例

  • O:Old Gen(老年代)使用比例

  • M:元数据区使用比例

  • CCS:压缩使用比例

  • YGC:年轻代垃圾回收次数

  • FGC:老年代垃圾回收次数

  • FGCT:老年代垃圾回收消耗时间

  • GCT:垃圾回收消耗总时间


FGC 十分频繁。

使用 Eclipse Memory Analyzer 工具。下载地址:https://www.eclipse.org/mat/downloads.php

分析的结果


问题大致原因InMemoryReporterMetrics 引起的OOM。
zipkin2.reporter.InMemoryReporterMetrics @ 0xc1aeaea8
Shallow Size: 24 B Retained Size: 925.9 MB

也可以使用:Java内存Dump(https://www.perfma.com/docs/memory/memory-start)进行分析,如下截图,功能没有MAT强大,有些功能需收费。

因为出现了这个问题,查看出现问题的这个服务  zipkin的配置,和其他服务没有区别。发现配置都一样。

然后看在试着对应的 zipkin 的jar包,发现出现问题的这个服务依赖的 zipkin版本较低。

有问题的服务的 zipkin-reporter-2.7.3.jar
其他没有问题的服务 依赖的包 :zipkin-reporter-2.8.4.jar

修复后使用 这个key :Class<? extends Throwable>  替换  Throwable。

小建议:配置JVM参数的时候还是加上下面参数,设置内存溢出的时候输出堆栈快照.

记一次sleuth发送zipkin异常引起的OOM
https://www.jianshu.com/p/f8c74943ccd8

亿级系统的Redis缓存如何设计

由浅入深逐步讲解Java并发的半壁江山AQS

ThreadLocal内存溢出代码演示和原因分析

欢迎关注微信公众号互联网全栈架构,收取更多有价值的信息。