目录
故障现象
Java进程出现问题,通常表现出如下现象:
1.CPU使用率持续极高/低
2.内存占用持续极高,甚至出现OOM(例如:进程正常运行一段时间之后突然不再响应请求,但是进程依然存在)
3.Web应用响应时间很长/超时,甚至不响应直接出现502(使用nginx作为反向代理)
响应时间长、超时,甚至不响应,这是最直观的表现;而CPU使用率极高或极低,频繁出现Full GC甚至OOM,需要借助系统日志或者监控辅助发现。
原因分析
响应时间长、超时,甚至不响应,这是一个综合性的故障结果,可能并不单纯是应用程序本身的问题。
首先,需要排查网络连通性是否正常;
其次,如果后端还接了数据存储系统,除了排查应用程序本身的问题之外,还需要排查应用所依赖的第三方组件是否出现了性能瓶颈,这通常可以从应用程序日志中看到错误信息。
在直观的故障表象背后是对应的系统指标异常,排查思路如下。
CPU使用率极低
通常是线程Hang住了,或者是出现了死锁,通过线程堆栈日志可以进行定位。
CPU使用率持续极高
先使用jstack命令查看堆栈信息,结合线程堆栈信息分析可能的原因:
- 业务代码很忙,甚至出现了死循环,这个从线程堆栈日志中可以 定位到具体的代码块
- 频繁出现GC,特别是Full GC,从gc日志中可以得知
- TCP连接数很高,这通常是高并发导致的
- 系统日志输出很频繁也会导致CPU占用很高
内存占用很高
使用jmap命令将堆内存快照保存下来,使用工具“Memory Analyzer”分析定位可能的原因:
- 业务代码在频繁创建对象,并且没有及时销毁,甚至因为BUG原因根本就没有释放内存空间
- 如果不能定位到业务代码问题,有可能是Serlvet容器等服务组件出现了内存泄漏,从堆内存快照分析中可以确定
- 不恰当的垃圾回收器也会引起堆空间回收不及时,这可以从GC日志中找到一些蛛丝马迹
如果频繁出现Full GC,首先需要排查是否分配的堆内存空间太小,或者GC是否需要调优。
解决思路及处理方式
- 应用程序日志是首先排查的入口,可以直接排查日志文件,或者从日志中心进行检索,因此要求在系统开发的时候必须设计合理的日志输出规范。
- 如果是线上问题,先保存“线程堆栈”和“内存快照”,重启进程,及时恢复服务,进一步排查并复现问题。
- 如果是测试环境,需要增加监控,充分进行压测,排查问题并解决后上线。
常用工具
查看网络连接
连接数很多意味着并发很高。
$ netstat -anpt|grep <port>
线程堆栈日志分析
- jstack命令:线程dump,导出线程堆栈日志
- 可视化分析工具
- TMDA:https://www.ibm.com/support/pages/ibm-thread-and-monitor-dump-analyzer-java-tmda ,可以很直观地看到线程死锁等信息
- fastThread:https://gceasy.io/ft-index.jsp ,在线服务,免费使用有次数限制
堆内存快照分析
- jmap命令:保存堆内存快照
- 可视化分析工具
- mat:https://www.eclipse.org/mat/ ,可以定位到具体的代码块
线上问题诊断
- Arthas
https://alibaba.github.io/arthas/index.html
阿里开源的线上问题排查工具,可以不用重启进程进行问题定位。
【参考】
https://mp.weixin.qq.com/s/g8KJhOtiBHWb6wNFrCcLVg 面试官:如果你们的系统 CPU 突然飙升且 GC 频繁,如何排查?