频繁GC导致CPU飙高,排查笔记实战
一、问题场景
测试环境突然报警CPU飙高,查看日志发现不停的在做GC操作,8个GC线程把CPU打爆。
二、问题排查
首先就是保留现场,打印堆栈信息。
1.打印线程运行信息
jstack 85090 > code-api.log
2.打印堆信息
jmap -dump:format=b,file=heapdump1.hprof 85090
3.分析dump文件

图中可以看到,StackTraceElement的数量非常惊人。
StackTraceElement每个元素表示单独的一个堆栈帧。所有的堆栈帧(堆栈顶部的那个堆栈帧除外)都表示一个方法调用。
因此可以确定是某个方法做了无限递归调用,不停的开启新的栈帧
4.分析线程运行日志

发现所有的工作线程不停的调用AlarmService中的这个方法,那问题基本就定位到了。
5.查看AlarmService
发现方法是调用了一个RPC请求,原来是测试环境服务器迁移,导致没法调通原有ip,将ip改为域名后即可。
三、问题分析
1.查看Feign配置
RPC调用使用了Feign,经排查配置了NEVER_RETRY(从不重试)参数,为什么还会不停的重新请求呢。
2.AOP
查看了告警机制的实现,是通过AOP切面来捕获异常进行处理。
也就是说告警Service连接告警中心服务器,5秒后超时报了超时异常,这个超时异常也被AOP捕获了,之后告警Service要将超时异常报给告警中心,但告警中心无法连接还是会报超时异常,就导致了不停递归打开新方法,问题到这里就完全搞清了。
四、解决方法
这里发现了潜在的坑,就是告警中心服务器如果不稳定,势必会影响线上服务的正常运行,这是不可接受的,因此要想办法避免这种情况的再次发生。
1.try-catch
- 对alermService中的方法添加try-catch,发现居然并不生效,并不能catch到异常。
- 后来分析是Service下层调用RPC接口时产生的异常,被catch之前就被aop先捕获到了。
- 把try-catch加到rpc层,问题解决。
不过这种解决方式不够优雅,不能把每rpc调用都try-catch处理。
2.aop
通过aop配置来解决。
原有为
@Pointcut(execution(* com.qbq.test..*.*(..)))
修改为
@Pointcut(execution(* com.qbq.test..*.*(..)) && !execution(* com.qbq.test.alarm..*.*(..)))
即aop的切面不再且alarm包,不会再捕获alarm包中的异常了。
经验证,问题解决。
我曾七次鄙视自己的灵魂:
第一次,当它本可进取时,却故作谦卑;
第二次,当它在空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。
时间仓促,如有错误欢迎指出,欢迎在评论区讨论,如对您有帮助还请点个推荐、关注支持一下
作者:博客园 - 角刀牛
出处:https://www.cnblogs.com/jiaodaoniujava/
该文章来源互联网,本博仅以学习为目的,版权归原作者所有。
若内容有侵犯您权益的地方,请公告栏处联系本人,本人定积极配合处理解决。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)