Spring WebFlux项目ByteBuf未释放内存泄漏问题求助
问题分析与解决方案
核心原因
从泄漏日志的调用栈可以看出,ByteBuf泄漏发生在r2dbc-mssql驱动的RpcEncoding类处理null值编码的逻辑中,属于驱动内部资源未正确释放的问题,同时Netty版本不兼容、异常处理不当会加剧这类问题的出现。
具体解决步骤
1. 修复Netty版本冲突
你的POM中手动指定了netty-resolver-dns-native-macos版本为4.1.110.Final,但Spring Boot 3.3.0默认管理的Netty版本是4.1.111.Final,版本不一致会导致Netty资源管理逻辑异常。
修改方式:
移除手动添加的该依赖,让Spring Boot父依赖自动管理版本:
<!-- 移除以下手动指定的依赖 --> <!-- <dependency> <groupId>io.netty</groupId> <artifactId>netty-resolver-dns-native-macos</artifactId> <version>4.1.110.Final</version> <classifier>osx-aarch_64</classifier> </dependency> -->
如果确实需要原生DNS解析依赖,添加时不指定版本,继承Spring Boot的管理版本:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-resolver-dns-native-macos</artifactId> <classifier>osx-aarch_64</classifier> </dependency>
2. 升级r2dbc-mssql驱动版本
r2dbc-mssql 1.3.x早期版本存在ByteBuf泄漏的已知问题,升级到修复后的版本即可解决。Spring Boot 3.3.0兼容的最新稳定版本为1.3.4,在POM中明确指定:
<dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-mssql</artifactId> <version>1.3.4</version> <scope>runtime</scope> <exclusions> <exclusion> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty-http-brave</artifactId> </exclusion> </exclusions> </dependency>
3. 修正异常处理逻辑
当前代码中onErrorResume直接返回Mono.empty(),会吞掉所有异常,包括可能导致资源未释放的连接异常。正确做法是:
- 不吞掉异常,返回明确的错误响应;
- 确保异常发生时上游资源能被正确释放。
修改后的代码示例:
return myRepository.findItems(itemType, fromDate, toDate) .collectList() .switchIfEmpty(Mono.error(buildError(404, ITEM_NOT_FOUND))) .flatMapMany(Flux::fromIterable) .flatMap(this::aggregateItemsData) .map(itemBuilder::toItemData) .onErrorResume(throwable -> { log.error("getItems failed: {}", throwable.getMessage(), throwable); // 打印完整栈信息便于排查 return Mono.error(buildError(500, "Internal Server Error")); // 返回标准错误响应 });
4. 检查aggregateItemsData方法
该方法包含额外DB调用,需确保:
- 所有Reactor流使用正确操作符,避免嵌套订阅(如
block()/subscribe()); - 使用
using/usingWhen等操作符管理DB连接或资源的生命周期; - 不在方法中创建未被正确释放的资源。
验证方法
- 启动应用后,观察日志是否再出现ByteBuf泄漏提示;
- 对接口进行压测,检查是否还有连接关闭异常;
- 查阅
r2dbc-mssql官方发布日志,确认升级版本已修复对应泄漏问题。
内容的提问来源于stack exchange,提问作者ElephantLove
相关产品推荐
相关产品推荐

