背景

存在一个业务场景,通过前端点击事件,须要到Mongo数据库外面取数据并整顿成excel表格并发送给前端,数据量没有破十万的时候,所有还是比拟美好的。然而导出的量持续减少时前端页面间接卡死,后端也产生oom报错

问题定位

间接先说论断,就是后端在拿到数据生成excel表格时,将查问到的所有的数据定义一次性写入由POI定义在内存中的一个长期excel文件从而导致了oom报错。

解决办法

为解决问题先钻研(bai du)了一下Poi生成Excel文件的几种形式

HSSF:Excel97-2003版本,扩大名为.xls。一个sheet最大行数65536,最大列数256。
XSSF:Excel2007版本开始,扩大名为.xlsx。一个sheet最大行数1048576,最大列数16384。
SXSSF:是在XSSF根底上,POI3.8版本开始提供的反对低内存占用的操作形式,扩大名为.xlsx。
采纳Hssf或者Xssf模式都会导致同样的问题产生,其根本原因是结构形式的不同
SXSSF在结构时,会设置一个默认值a,内存中最多只有a行数据,当超过这个数据时,就将内存之前的数据删除,并且会在硬盘中生成临时文件。不过也因为该个性,导致其生成数据的速度会比其余俩种形式慢,同时因为Excel版本兼容性是向下兼容。所以其实最优的形式是量大用SXSSF,量小用XSSF.

SXSSFWorkbook workbook= new SXSSFWorkbook(Int a);

新问题产生

刚刚有提到一点,SXSSF模式的生成Excel文件比较慢。这又产生了一个新问题,批改了模式后,在理论前后端交互的时候,前端发送申请过去,常常在期待后端将文件生成再回应的过程中逐步失去急躁从而导致申请失败。

解决问题的几个思路

  1. 优化后端生成文件工夫。
    间接开始硬性医治,既然你后端处理速度慢就优化速度,例如优化Mango查问代码,应用多线程并发写Excel等等.
    该计划的长处是缩小了对外的整体查问的工夫。毛病是后端容易掉头发,而且多线程减少了开发和保护的难度;高并发压力转移到外部的服务器上,对其QPS响应提出了更高的要求。
  2. 将数据查问和下载的流程异步化。
    浏览器申请下载后,服务端立刻返回报表的惟一标识Key同时开始近程查问数据,客户端能够凭借该Key查问报表的生成进度,报表实现后就能够下载;或者应用另一种计划,服务器在报表生成实现后通过一些渠道(如Long-Polling、WebSocket、即时通信软件、邮件等)告诉客户端下载。
    该计划的长处是并发能力强,不会阻塞服务器的Web连接池。毛病是须要开发Key的CRUD操作和相应的UI;还须要在服务器端存储生成的报表文件。
  3. 服务端边生成文件,浏览器边下载报表。
    就像下载大文件一样,浏览器一直开和服务器的Http连贯,同时服务器一直向浏览器追加Http体数据直到报表生成完结。
    该计划的长处是开发难度低、速度快。毛病是数据查问是单线程的,速度较慢;而且文件下载会始终占用服务器的Web连接池,如果并发下载量较大可能会阻塞其余的Http申请。