一、背景
- 数据表导出
excel
时,数据量大于65w
行,excel
分为多个文件
;测试导出200w
数据出现内存溢出(java.lang.OutOfMemoryError: Java heap space
),导致rcapi
服务直接崩溃重启
二、目标
- 让数据表
200w
数据可以顺利导出
三、引发的思考
- 导出的逻辑挺复杂的,到底是哪块代码出现了问题,想着
debug
来排查,但是debug
过程中,发现有很多地方的代码用时都挺长的,不好定位 - 堆空间不足,是不是有哪里的代码不够规范,导致该释放的对象,一直没有被释放掉,
debug
过程中,对象太多了,还是不好判断 - 对于内存占用这个地方只靠
debug
来看的话,不好判断,就想着JVM调优
,别人是如何排查?之前只是听说过,没有实践过,理论也只会一丢丢 - 百度发现
jconsole
命令有一个图形化界面可以帮助看堆变化情况,但是这个只观察到了变化,但是具体哪个对象引起的,哪地方的代码引起的还是不清楚 - 又去查资料,发现
jvisualvm
命令可以打开一个图形化界面,这个界面比较友好,可以看到对象的实例化
占用空间情况,这样就可以看看哪些对象占用了很多的空间 - 又想知道是哪个地方的代码引起的,百度了一下,都是
linux
上的命令,本地不好使用,这时候找到了阿里巴巴一个工具arthas
,通过这个工具可以观察到占用cpu
过高的线程,然后可以看到线程的堆栈信息 - 经过以上的过程,下边主要使用了
idea
的debug
功能,jvisualvm
观察内存变化和对象实例情况,然后通过arthas
来观察线程的堆栈信息
四、排查过程:
1.启动rcapi
服务,设置启动参数-Xms256m -Xmx8192m
,然后运行程序
2.postman
请求
- 请求url:http://localhost:5002/rcapi/v1/xxxx/queryAndExportExcel
- 请求参数:(省略)
- 请求头:x-sso-fullticketid:xxxxxxxx
3.使用java VisualVM
工具(主要用来观察堆变化和实例数)
4.使用阿里巴巴工具arthas
(主要用来查看占用cpu
的比较高的线程堆栈信息)
#打开浏览器,输入地址,下载arhas,放入指定目录
https://arthas.aliyun.com/arthas-boot.jar
#打开powershell 运行arhas
java -jar arthas-boot.jar
5.postman
进行请求,查看堆内存的变化和实例数
6.当堆内存不断上升的时候,使用arthas
查看线程占用cpu
最高是哪个,以及对应的堆栈信息
7.结论:根据堆空间的变化,可以得出最高峰为7.5G
左右;根据实例的变化,可以得出excel
导出过程中产生了大量的Xobj$ElementXobj
和Xobj$AttrXobj
对象占用了空间
8.根据步骤6
、7
中得信息,进行debug
调试
- 全局搜索
ElementXobj
、AttrXobj
打上断点,观察什么时候,创建这些对象 - 根据步骤6中的堆栈信息,作为思路排查
9.根据调试结果,可以得出创建excel
内的一个小单元格
内容,会产生一个Cell
对象,setCellValue()
、setCellStyle()
过程中产生的大量的Xobj$ElementXobj
和Xobj$AttrXobj
对象,只有sheet
节点转化为流之后,对象才会被释放掉
五、处理方案
-
1.三种思路
- 调整堆内存,调整线上
jvm
参数-Xmx
为8192m
- 修改导出限制,
65w
修改为20w
- 调整基础导出类
- 调整堆内存,调整线上
-
2.选择
修改导出限制,65w修改为20w
,并且把启动参数修改为-Xms256m -Xmx4096m
(已在dev3环境进行线上测试过,可以导出成功)
附录:
- 阿里巴巴Arthas 用户文档
- 以上分享,如有不足之处,欢迎指正