You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebFlux Web服务DirectByteBuffer分配OOM后恢复相关问题咨询

WebFlux文件上传堆外内存OOM问题解决方案

异常表现的核心原因

你遇到的两类问题均属于框架、JVM的默认行为,不属于Bug,是遗漏了大文件上传场景的适配配置导致的。

1. 首次OOM后持续不稳定问题

原因

  • 你当前配置-Dio.netty.maxDirectMemory=0会让Netty直接复用JDK的-XX:MaxDirectMemorySize阈值,Netty池化分配器触发OOM后不会主动回收内存池中的空闲缓存块,也不会做碎片整理,只有新请求的缓冲区大小刚好匹配残留空闲块时才能分配成功,否则直接抛OOM,就会出现部分请求正常、部分请求失败的表现。
  • @RequestPart注解接收Part参数时,Spring WebFlux默认会把整个上传文件的内容全量加载到内存中,大文件请求很容易快速占满堆外内存。

修复配置

  • 新增参数-Dio.netty.allocator.cacheTrimIntervalMillis=30000,定期清理Netty线程本地的空闲缓存块,降低内存碎片化概率。
  • 调整内存阈值配置:将-Dio.netty.maxDirectMemory设为比JDK堆外内存上限小20%的值,比如你设置-XX:MaxDirectMemorySize=1g,同步配置-Dio.netty.maxDirectMemory=800m,避免Netty占满所有堆外内存后触发不可恢复的JDK层面OOM。
  • 代码层面改造:将@RequestPart入参改为@RequestBody Flux<Part> parts,采用流方式边接收文件内容边转发到上游服务,不要全量缓存文件内容到内存。

2. 非池化模式下内存未归还操作系统问题

原因

该问题是JDK11默认使用的glibc内存分配器的特性,不是Netty问题:glibc默认会缓存释放的内存块用于后续分配,不会立即归还给操作系统,尤其是大内存分配场景下产生的内存碎片会被glibc长期持有,就会出现NMT显示内存已释放、htop显示RES内存居高不下的表现。

修复配置

  • 新增JVM参数-XX:+UseMallocRelease,JDK11及以上版本支持该参数,会强制glibc在内存释放后主动归还给操作系统。
  • 调整-Djdk.nio.maxCachedBufferSize参数到1m~2m,适配文件上传场景的大缓冲区分配需求,减少频繁的内存分配回收操作。
  • 若使用Alpine基础镜像,可替换为jemalloc作为默认内存分配器,内存释放效率更高。

内容的提问来源于stack exchange,提问作者JCMS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 23:27:01