HSSFWorkbook
:它是早期使用最多的工具,支持Excel2003以前的版本,Excel的扩展名是.xls 。只能导出65535条数据 , 如果超过最大记录条数会报错,但不会出现内存溢出 。XSSFWorkbook
:它可以操作Excel2003-Excel2007之间的版本,Excel的扩展名是.xlsx 。最多可以导出104w条数据,会创建大量的对象存放到内存中,可能会导致内存溢出 。SXSSFWorkbook
:它可以操作Excel2007之后的所有版本,Excel的扩展名是.xlsx 。SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的rows在内存里供查看,以前的rows都会被写入到硬盘里 。用磁盘空间换内存空间 , 不会导致内存溢出 。那个引起OOM问题的功能,刚好使用了XSSFWorkbook处理excel , 一次性创建了大量的对象 。
关键代码如下:
XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(file));XSSFSheet sheet = wb.getSheetAt(0);
我们通过MAT内存分析工具,已经确定OOM问题的原因了 。接下来,最关键的一点是:如何解决这个问题呢?5. 如何解决问题?根据我们上面的分析,既然
XSSFWorkbook
在导入导出大excel文件时,会导致内存溢出 。那么 , 我们改成SXSSFWorkbook
不就行了?关键代码改动如下:
XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(file));SXSSFWorkbook swb = new SXSSFWorkbook(wb,100);SXSSFSheet sheet = (SXSSFSheet) swb.createSheet("sheet1");
使用SXSSFWorkbook将XSSFWorkbook封装了一层,其中100表示excel一次读入内存的最大记录条数,excel中其余的数据将会生成临时文件保存到磁盘上 。这个参数,可以根据实际需要调整 。还有一点非常重要:
sheet.flushRows();
需要在程序的结尾处加上上面的这段代码 , 不然生成的临时文件是空的 。这样调整之后,问题被暂时解决了 。
此外,顺便说一句,在使用WorkBook接口的相关实现类时,用完之后,要记得调用6. 后续思考其实,当时我建议过使用阿里开源的close
方法及时关闭喔,不然也可能会出现OOM问题 。
EasyExcel
解决OOM的问题 。但同事说,excel中有很多样式 , 在导出的新excel中要保留之前的样式,同时增加一列,返回导入的结果 。
如果使用
EasyExcel
不太好处理,使用原始
的Workbook
更好处理一些 。但是使用mq异步导入excel文件这套方案,如果并发量大的话,任然可能会出现OOM问题,有安全隐患 。
因此 , 有必要调整一下mq消费者 。
后来,mq消费者的
线程池
,设置成4
个线程消费,避免mq消费者同时处理过多的消息,读取大量的excel,导致内存占用过多的问题 。当然线程个数参数,可以根据实际情况调整 。此外,使用阿里的
arthas
也可以定位线上OOM问题,后面会有专门的文章介绍,感兴趣的小伙伴可以关注一下 。最后说一句(求关注 , 别白嫖我)如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下 , 您的支持是我坚持写作最大的动力 。
【糟了,线上服务出现OOM了】求一键三连:点赞、转发、在看 。
关注公众号:【苏三说技术】,在公众号中回复:面试、代码神器、开发手册、时间管理有超赞的粉丝福利,另外回复:加群,可以跟很多BAT大厂的前辈交流和学习 。
推荐阅读
- Docker | 部署nginx服务
- 线上服务宕机,码农试用期被毕业,原因竟是给MySQL加个字段
- .NET 6 跨服务器联表查询
- 一个C#开发者学习SpringCloud搭建微服务的心路历程
- 基于Netty的TCP服务框架
- 【.NET 6+Loki+Grafana】实现轻量级日志可视化服务功能
- 一篇文章带你掌握主流服务层框架——SpringMVC
- gin项目部署到服务器并后台启动
- 结合springboot实现,这里对接的是easy版本,工具用的是IDEA,WebStrom 支付宝沙箱服务
- gRPC+Protocol Buffer Go微服务实战 - 用户服务开发