本文来自网易云社区
作者:苏鹏
最近部门的某产品周末时候测试服务器下会无故宕机,周一测试的同学来问具体原因,综合周末收到的哨兵系统的报警,简单分析了现象,应该是后台服务的原因。
1.首先登录哨兵系统,查看我们部署的服务的状态
此处内存、硬盘等指标都是比较正常的水平,但是CPU在某一个时间段非常高,所以初步判断是CPU异常导致了服务宕机(此处应有CPU状态异常图,但是当时没有把事故现场保存下来)
2.登录服务器,查看服务器状态
(1) 查看日志
登录部署服务的两台服务器,查看我们部署的两台服务器的日志,果然发现日志里报了oom的错误
(2)使用top命令
使用top命令,也能看到本服务的CPU占用率会井喷
图略,现象是该服务的CPU占用率为99%
结论:已经能定位到是内存溢出的问题,时间点也比较符合服务宕机的时间,这时候就该寻找具体是什么原因造成了oom
3. dump内存文件
在项目部署的时候需要加上一个参数,即-XX:+HeapDumpOnOutOfMemoryError,等OOM的时候会把内存文件DUMP出来
这时候我们发现内存文件已经生成在我们设置的路径下了
4.使用java visualVM分析该内存文件
(1)使用scp命令把该内存文件下载到本地,具体操作略
(2)打开java visualVM应用
我用的是mac系统,不熟悉的小伙伴可能不知道它存在的位置,这里也给大家写一下jdk自带工具的路径
/Library/java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin
(3)导入内存文件后,在java visualVM中可以看到该文件的简介
我们可以看到我们的visualVM已经为我们展示了各个线程的状态。
然后搜索一下状态为BLOCK状态的线程
我们发现BLOCK状态的线程,它们所指向的代码都是同一个,MMLogger是我们封装的日志文件,难道会出什么问题?
5.分析代码
定位到我们具体的代码问题,那我们接下来就来分析代码,我们发现了两个问题
(1)在AOP中我们配置了所有进入接口都会打印一个日志
execution(public * com.netease.ai.ar.dongjian.web..*.* (..))"
(2)使用日志的方式不正确
我们使用的是org.apache.log4j.LogManager;
其中跟踪代码下去,就会发现会进入到这个方法
会有这样的一个代码段有关键字,在并发量比较高的情况下可能会出现死锁的情况
总结:综合以上两个原因,就会造成同时会有很多线程在打印日志,而打印日志又会进入到synchronize代码段,造成很多的线程都在等待这段代码执行完,导致了BLOCK的产生
以上两个方面,我们分别解决
(1)把进入所有接口日志配置去除,改成有需要的接口加日志注解的方式
(2)修改日志类,改为org.slf4j.LoggerFactory;
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区。