Java服务-CPU过载问题复盘

上周公司的服务有一个大版本上线,上线后服务器频繁出现CPU使用率长时间百分之三四百,服务不可用。因为公司系统目前单机运行,出现问题后只能麻烦运营同学一次又一次重启Tomcat,不能保留现场,一时间手忙脚乱。目前问题已经解决,在这里做一下记录已便以后遇见问题快速解决。

1、首先确定机器卡死是不是Java服务的问题,用“top”命令看一下机器整体进程情况

窗口观察一段时间,发现Java进程一直cpu占用率很好,内存占用也很大。

2、定位异常线程,“top -H -p78066”

记下几个长时间占用率高的线程。 通过命令“jstack 78066 > jstack.txt ”可以打印Java进程当前各个线程的堆栈,文本信息中nid是线程id的十六进制。我们把定位到的几个线程线程ID转化十六进制,“printf “%x\n” 2777”。搜索jstack.txt如下图
基本上确定是GC占用cpu过多。命令“jstat -gcutil 78066” 可以查看具体GC情况。

3、查看内存情况,命令“jmap -histo:live 78066 | more ” 查看当前线程当前存活的对象,看排在前几位的对象。

可以看见排在前面的两个业务对象异常,order对象和user对象有几百万个,由此猜测肯定有错误代码将大量的库记录加载到内存里面。但是我们还是不知道该改哪个代码。

4、下载一个内存镜像,具体分析,命令“jmap -dump:live,format=b,file=/data/0223.bin 78066”。使用mat软件 ,下载地址:www.eclipse.org/mat/downloa… 下载一个独立运行版本即可。

把bin文件导入,分析工具提供的报表比较多,比较用的三个是Histogram可以列出内存中的对象,对象的个数以及大小。Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。Leak Suspects通过MA自动分析泄漏的原因。我们直接打开Leak Suspects可见如下
下面是推荐的可以代码,点开堆栈就可以定位问题代码。

最终根据mat报告中的堆栈信息定位到了代码错误,是有一个查询把一个超大的查询结果加载到内存中,导致内存吃紧,GC拼命回收,最终导致服务假死不可用。

结语:在代码中出现空条件查询肯定会出现问题,一般可以在mybatis层面设置拦截器,出现空条件查询就抛出错误(www.cnblogs.com/cmfwm/p/802… 另外遇到此类问题还可以考虑的方向还有就是数据库连接问题,我们连接池用的是druid,它自带一个监控界面“druid monitor”,可以关注下图中两个参数,看看有没有未关闭的连接。

参考资料:https://www.cnblogs.com/xiaoL/p/9774095.html
https://www.cnblogs.com/AloneSword/p/3821569.htm
https://www.cnblogs.com/loong-hon/p/10475143.html
复制代码

猜你喜欢

转载自juejin.im/post/5e535255f265da575918d7d8
今日推荐