由于公司扩展海外业务,开放了日本、韩国市场,服务器也就部署在日本。但是最近却出现频繁应用挂掉、CPU动不动就飙升到100%的问题,只能让运维重启服务器。问题还是需要根治。

1、首先,一般是操作人员发现,系统无法登录、操作任何菜单,点击界面跟后端交互的接口一直毫无响应。这时,我们在服务器查看,使用命令:top ,发现一个java进程一直处于100%;

2、第二步,本来按照问题查找的一般过程,我们接下来是需要通过top -Hp <pid>命令查看当前进程的各个线程运行情况,找出CPU过高的线程之后,将其线程id转换为十六进制的表现形式,然后在jstack日志中查看该线程主要在进行的工作。但是问题在于cpu已经100% 了,操作命令效率极低,况且用户就是上帝 ,他们不会给你这么多时间去排查问题,需要尽快重启系统。这里,采用命令

-XX:+HeapDumpOnOutOfMemoryError 

-XX:HeapDumpPath=/path/heap/dump 

将dump日志输出到指定文件夹内,然后在使用工具对 对象数量,内存占用,线程情况等进行分析查看。

3、经过上面的操作,我们已经完成了日志文件的记录。但是问题又来了,服务器不方便对日志进行直接分析,需要下载到本地,而服务器部署在国外 ,文件大小超过5个G

记一次CPU 100%问题排查过程

使用服务器动不动就下载失败,还无法支持断点续传,此时,我们借用了OSS(阿里云存储服务)工具,每当生成了dump文件,就自动上传到OSS,我们再从OSS下载进行分析,完美解决该问题。

4、日志文件成功下载,我们开始进行分析。一开始我们使用eclipse的mat图形化工具打开dump,但是工具都会内存溢出

对于比较小的dump,eclipse可以打开,但一旦dump文件太大,eclipse就有点束手无策。这里我推荐使用一款神器JProfiler,

装上使用版一用,发现果然是神器,特此推荐给大家。先声明,这个软件是商用的,网上有很多关于lisence的帖子,我这里转发,但是绝不推荐大家用**版!

[email protected]#36573-fdkscp15axjj6#25257
[email protected]#5481-ucjn4a16rvd98#6038
[email protected]#99016-hli5ay1ylizjj#27215
[email protected]#40775-3wle0g1uin5c1#0674
[email protected]#7009-14frku31ynzpfr#20176
[email protected]#49604-1jfe58we9gyb6#5814
[email protected]#25531-1qcev4yintqkj#23927
[email protected]#96496-1qsu1lb1jz7g8w#23479
[email protected]#20948-11amlvg181cw0p#171159

5、工具也就位了,现在我们开始进行分析,我们选择离线分析(关于JProfiler的更多使用教程可以参阅:https://www.cnblogs.com/jpfss/p/8488111.html)。结果如下:

记一次CPU 100%问题排查过程

我们可以看到Xobj实例对象竟达到了4987832个,占用接近3个G的内存,导致频繁full gc,CPU100%。至于对象为何如此巨大,我们回归代码发现,有一个导出Excel没有对条数进行限制,直接全表导出,数据库数据全部加载到了内存,是导致问题的根本原因。

6、问题已经确定,剩下的就是优化代码的问题了。我这里作了两个操作:

  1)、限制一次性导出数据的行数,对查询sql使用limit,大于limit数据分批次导出到多个Excel文件,给web返回zip压缩包;

  2)、导出工具转换,从单纯的使用POI到使用阿里巴巴的 开源项目 easyExcel,它重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。感兴趣的请戳 https://github.com/alibaba/easyexcel 。

 

相关文章: