网关服务压测十分钟后报 OutOfMemoryError: Direct buffer memory,堆只用了 1.2G,进程 RSS 却到 5.8G,重启才能恢复。日志里能对上时间点,这种反而好排。
Netty 的 PooledByteBufAllocator 从堆外分配内存,默认上限等于堆最大值。堆外不计入 -Xmx,但算在进程 RSS 里,泄漏时只看堆监控发现不了。这一点先确认清楚,后面就不用反复试。
java -XX:MaxDirectMemorySize=512m \ -Dio.netty.leakDetection.level=paranoid -jar gateway.jar jcmd 21455 VM.native_memory summary
围绕「直接内存溢出」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
报错里带路径的,先去看那个路径在不在、权限对不对。同一份配置存在多处的,先确认改的是被加载的那一份。
新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
处理上按这个顺序:显式设 -XX:MaxDirectMemorySize 让它有上限;打开 -Dio.netty.leakDetection.level=paranoid 定位未释放的 ByteBuf;检查所有 ByteBuf 是否 release 或走 SimpleChannelInboundHandler;用 NMT 的 Internal 和 Other 两项观察堆外增长。
结果对不对很好判断,压测一小时不再抛 Direct buffer memory RSS 稳定在 3G 以下 泄漏日志里没有未释放的 ByteBuf。
