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

Spring Boot gRPC客户端报Direct buffer memory内存溢出问题咨询

问题结论

你遇到的Netty直接内存溢出不属于grpc-java #6910的已知问题,是线程池配置和ManagedChannel资源管理的配置遗漏导致。

核心原因

  1. 自定义线程池配置不合理导致ByteBuf泄漏
    你定义的线程池核心线程数为0,队列使用无缓冲的SynchronousQueue,最大线程数仅为CPU核数*2。对接超过100台双向流服务端时,服务端并发推送的数据会产生大量处理任务,线程数不足时会触发自定义丢弃策略直接丢弃任务。grpc的流处理任务被丢弃后,Netty已经接收的ByteBuf不会被上层逻辑消费释放,持续累积就会占满直接内存。
  2. ManagedChannel资源未共享导致直接内存预留过高
    默认每个独立创建的ManagedChannel会生成专属的Netty EventLoopGroup,默认EventLoop线程数为CPU核数*2,100多个Channel会创建上百个IO线程,每个IO线程默认预留16MB的直接内存池,光这部分的预留内存就可达数GB,很容易超出JVM默认的直接内存上限。
  3. 与grpc-java #6910无关
    该issue是TLS握手场景下的直接内存泄漏,你使用非加密模式完全不涉及该场景,且你使用的Netty v4.1.65.Final已经修复了相关的泄漏点。

解决方案

  • 调整自定义线程池配置:核心线程数调整为CPU核数2,最大线程数调整为CPU核数4,队列替换为容量1000~10000的ArrayBlockingQueue,拒绝策略替换为CallerRunsPolicy,避免任务丢弃导致的ByteBuf泄漏。
  • 共享Netty EventLoopGroup:创建全局公用的NioEventLoopGroup/EpollEventLoopGroup,构造NettyChannelBuilder时通过channelBuilder.eventLoopGroup(globalEventLoopGroup)传入,所有ManagedChannel共用同一个IO线程组,减少不必要的内存预留。
  • 调整JVM直接内存上限:启动参数新增-XX:MaxDirectMemorySize=4G,可根据业务消息量级向上调整,避免默认值不足。
  • 增加流控限制:构造Channel时配置channelBuilder.maxInboundMessageSize(10*1024*1024),限制单条消息的最大大小,避免超大消息占满内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:45:05