大文件下载内存溢出防护:拒绝全量加载,零拷贝流式输出抗住万级并发
朋友公司的文件服务,一到月底报表下载高峰期就崩。运维排查发现每次下载一个 200MB 的 Excel,后端代码里居然是 byte[] data = file.readAllBytes()——把整个文件加载到堆内存里再往外写。10 个人同时下载,就是 10 个 200MB 的数组在堆里,JVM 直接 OOM。重启后又崩,加内存也撑不住——因为下载峰值不是你能通过加内存解决的线性问题。 大文件下载的 OOM 问题本质就一句话:你把整个文件搬进了 JVM 堆里,但 JVM 堆不是为文件 IO 设计的。 文件应该从磁盘流到网卡,中间经过你的应用,但不要在你的堆里停留。 今天聊聊怎么用流式传输和零拷贝,让 X GB 的文件下载跟 X KB 的一样轻松。 错误姿势:全量加载 最常见的错误写法: @GetMapping("/download") public ResponseEntity<byte[]> download(String filePath) { byte[] data = Files.readAllBytes(Path.of(filePath)); // ❌ 全量加载到....