老 MES 系统里”导出”大概是最容易被低估的功能:早期数据量小,一个同步接口把数据查出来写成 Excel 直接回传,皆大欢喜。等到单表日志类数据涨到千万行、报表动辄几十万行时,这条链路开始连环爆雷。本文记录一次完整的导出链路改造:从同步超时丢文件,到「提交即返回 + 游标流式读取 + 异步写入 + 桌面通知取件」的全套架构,包括关键实现细节、踩过的每一个坑,以及清楚留着的优化债。
一、同步导出的四宗罪
改造前的链路是典型的”一把梭”:
1 | 用户点导出 → 请求线程分页循环查全量 → 攒成大 List → 写 Excel → HTTP 响应回传 |
数据量上来后暴露的问题按出现频率排序:
- 网关超时:内部走 Ribbon/Zuul 网关,读超时默认 10 秒,导出耗时一超,连接被网关掐断——用户拿到半个文件或一个报错页;
- 内存压力:全量行同时驻留 JVM 堆(
List<Map>+ 写缓冲),几个人并发导出大报表,堆直接见顶; - 体验差:用户必须挂着页面等,手一抖刷新就前功尽弃;
- 不可回溯:一旦超时,服务端即便把文件写出来了也没法交给用户,白白浪费一次全量查询。
期间打过一层补丁:同步导出超时后转后台继续写,完成后上传文件、发通知。这解决了一部分问题,但”用户先同步等 30 秒”的体验和分页翻页式读取的额外开销还在。于是有了这次彻底的改造。




