导出excel 大数据量分页_解决大批量Excel导出OOM问题

1、背景介绍:最近一直被OOM问题缠绕,原因是表单下载功能访问量比较大,数据量相当多,表单数据存储在mongodb,数据总量2亿多,每个实例总内存限制1.5G左右,线上部署了5个实例,但是最大承受时间也不过3天,于是决定逐步优化解决此问题

2、环境介绍:

2.1、vm: openjdk:8-jre-alpine

2.2、docker 部署,k8s管理

3、问题呈现:

3.1、导出大批量Excel时,nginx 504

3.2、访问量高 && 导出大批量Excel,出现OOM

4、问题分析:

4.1、nginx 504 问题,服务器长时间无响应,根本原因是同步操作,mongodb查询慢

4.2、数据保存在mongodb,mongodb分页是深分页,会全表扫描

5、解决办法:

5.1、导出采用异步操作,多线程异步处理

5.2、大批量的Excel采用下载到磁盘,统一压缩为zip文件上传到腾讯云,

5.3、能尽量用基本类型的不使用引用类型异步操作如图示

d1ba835ed629a7d76b2ff0720c4996b5.png

具体代码如下:

设置线程池,核心线程数不是越大越好,具体文章请参考

https://blog.csdn.net/wang123459/article/details/82079250

线程池资料参考

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html

8bc02610c99e6f27cdc0a88ed7b7ab38.png

代码逻辑具体实现:

87b56f61b59072a897cb829fc0a1e208.png
3c6d9eb02e5bbeedbb4275f680dd17f3.png

优化完之后,遗憾的是只能在线上坚挺了不到2天,某一个实例又爆出OOM了,由于添加了jvm监控,异常监控截图如下:

da1dd7c724be9173e76df5b2e313da74.png
8b2c965b5702c9a737640c5e1a92d327.png

经过分析是由于Eden space 无法为新生对象开辟新的空间,发生了OOM,java堆内存划分如下:

ad167e319c49102897cd3757c62ac144.png

从以下几点分析:(1)内存中加载的数据量过于庞大,如一次从数据库取出过多数据;

(2)集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;

(3)代码中存在死循环或循环产生过多重复的对象实体;

(4)使用的第三方软件中的BUG;

(5)启动参数内存值设定的过小;

受到启发:1、 代码中尽量少使用引用类型2、增大java堆内存3、设置合理的垃圾回收器

验证结果:

1、模拟大批量数据导出:并发请求10-20次,每个请求的数据导出下载量是30w条左右,结果如下:

416f914cbbb3bdcdeaa3b1a6a647dd0f.png
cbcbaaddd88ec67527ff90472b7031a6.png

30w条数据异步导出执行大概需要2-3秒就可以完成,

JVM堆运行情况如下:

1f658237c3d879a778316aee14690f48.png

其实在极限的条件下,选用合适的方法,而不是现在的服务器配置都很高,而不注重性能相关的问题,程序员的经验不能以工作年限而一味的判定,而是凭处理问题的思路和应变能力,

个人理解牛逼的高手都是在发现问题,解决问题的过程中历练出来的,而不是无谓的代码堆积,那就真正把自己变成的搬砖的了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值