Spring Cloud Gateway应用年轻代内存分配突增10倍问题排查求助
问题背景
基于Reactive Netty的Spring Cloud Gateway应用部署在多台GCP GCE虚拟机上,单台虚拟机平均流量为500TPS。平稳运行数周后,所有虚拟机在数小时内先后随机出现年轻代GC内存分配突增10倍的情况。内存突增后的数分钟到数小时内,应用出现严重性能退化:
- 服务器响应时间(
spring.cloud.gateway.requests)和后端调用时间(http.client.requests)升至正常值的20倍 - CPU使用率从约10%小幅升至25%
- 内存使用率从43%小幅升至54%
重启应用可解决该问题,7个月内已发生两次,尝试复现未成功,已查阅相关指标及GC、内存泄漏资料仍无法定位原因。
环境信息
- Java版本:21
- Spring Cloud Gateway版本:4.1.5
- Netty版本:1.1.21
- JVM GC设置:使用G1和Parallel GC均出现该问题
- 流量/负载:流量和负载大小稳定
观测到的异常指标
jvm/gc/memory/allocated:流量和负载不变的情况下突增10倍,为首个症状reactor/netty/bytebuf/allocator/active/direct/memory:从100k升至7Mreactor/netty/eventloop/pending/tasks:从0/1升至300以上reactor/netty/http/client/address/resolver:从2ms升至500msreactor/netty/http/client/tls/handshake/time:从5ms升至1500msjvm/threads/states:阻塞线程数从0增至80- TCP连接数:活跃连接数从20升至300
排查思路与建议
聚焦DNS解析与TLS握手延迟:从指标看,域名解析和TLS握手耗时大幅飙升,这会直接导致请求阻塞、事件循环任务积压。建议检查:
- GCP内部DNS服务是否存在间歇性故障,或域名解析策略是否有变动(如本地缓存失效、强制走远程DNS查询)
- TLS证书是否存在链不完整、过期预警,或后端服务TLS配置变更(如启用高耗时加密套件)
- 确认Netty的DNS缓存配置,是否因缓存过期导致频繁触发重复解析
分析ByteBuf与内存分配关联:直接内存活跃量上升伴随GC分配突增,可能是请求阻塞后ByteBuf无法及时释放,或分配策略异常:
- 开启Netty的ByteBuf泄露检测(设置
-Dio.netty.leakDetection.level=PARANOID),在下次异常发生时捕获泄露轨迹 - 检查Spring Cloud Gateway路由配置,是否存在某个路由的后端服务响应缓慢,导致请求上下文(含ByteBuf)堆积
- 开启Netty的ByteBuf泄露检测(设置
事件循环线程阻塞排查:事件循环待处理任务暴增、阻塞线程数上升,说明事件循环被阻塞:
- 配置自动触发线程dump,当阻塞线程数超过阈值时采集调用栈,定位是DNS解析、TLS握手还是自定义逻辑导致的阻塞
- 检查自定义过滤器/全局过滤器中是否存在同步阻塞操作(如阻塞式IO、锁等待),高负载下积累引发事件循环拥堵
长期监控与快照采集:由于问题间隔数月发生,需配置自动快照机制:
- 设置JVM参数,当GC分配率突增或事件循环待处理任务超过阈值时,自动触发线程dump、heap dump和Netty事件循环状态快照
- 持续监控
reactor/netty相关指标趋势,捕捉异常发生前的细微变化(如DNS解析耗时逐步上升)
版本兼容性与已知问题验证:
- 核对Spring Cloud Gateway 4.1.5、Netty 1.1.21在Java 21环境下的已知bug,是否有内存分配、事件循环阻塞相关的修复记录
- 尝试升级至较新的Netty版本(如1.1.25+)或Spring Cloud Gateway版本,验证是否能规避问题
内容的提问来源于stack exchange,提问作者Nicolás Acosta
相关产品推荐
相关产品推荐

