产品需求
产品经理需要导出一个页面的所有的信息到 EXCEL 文件。
需求分析
对于 excel 导出,是一个很常见的需求。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
最常见的解决方案就是使用 poi 直接同步导出一个 excel 文件。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
客户体验 & 服务性能
- 客户体验
如果导出的文件比较大,比如几十万条数据,同步导出页面就会卡主,用户无法进行其他操作。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
- 服务性能
导出的时候,任务比较耗时就会阻塞主线程。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
如果导出的服务是暴露给外部(前后端分离),这种大量的数据传输十分消耗性能。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
解决方案
使用异常处理导出请求,后台 MQ 通知自己进行处理。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
MQ 消费之后,多线程处理 excel 文件导出,生成文件后上传到 FTP 等文件服务器。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
前端直接查询并且展现对应的任务执行列表,去 FTP 等文件服务器下载文件即可。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
EXCEL 导出需要考虑的问题
OOM
正常的 poi 在处理比较大的 excel 的时候,会出现内存溢出。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
网上的解决方案也比较多。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/17643.html
比如官方的 SXSSF (Since POI 3.8 beta3) 解决方式。
当然,这种写法比较麻烦。
可以选择一些封装好的 excel 工具,解决 oom 问题:
iexcel excel 更加优雅地读取和写入,解决 excel OOM 问题
FULL GC
如果一次查询 100W 条数据库,然后把这些信息全部加载到内存中,是不可取的。
建议有2个:
- 限制每一次分页的数量。比如一次最多查询 1w 条。分成 100 次查询。(必须)
- 限制查询得总条数。比如限制为最多 10W 条。(根据实际情况选择)
虽然使用者提出要导出类似于 3 个月的所有信息,但是数量太多,毫无意义。(提出者自己可能体会不到)
尽量避免 FULL-GC 的情况发生,因为目前的所有方式对于 excel 的输出流都会占用内存,100W 条很容易导致 FULL-GC。
数据库的压力
去数据库读取的时候一定要记得分页,免得给数据库太大的压力。
一次读取太多,也会导致内存直线上升。
比如 100W 条数据,则分成 100 次去数据库读取。
网络传输
传统的 excel 导出,都是前端一个请求,直接 HTTP 同步返回。导出 100W 条,就在那里傻等。
这客户体验不友好,而且网络传输,系统占用多种问题。
建议使用异步处理的方式,将文件上传到文件服务器。前端直接去文件服务器读取。
编程的便利性
对于上面提到的工具,比如 Hutool,在表头的处理方面没法很方便的统一。
你可以自己定义类似于 easypoi/easyexcel 中的注解,自己反射解析。
然后统一处理表头即可。
评论