1. 项目概述
这是一个关于Netty堆外内存泄露问题的实战排查案例。某API网关节点在生产环境中出现内存持续增长直至OOM(Out Of Memory)的故障现象。表面上看JVM堆内存使用正常,但物理内存却不断被占用,最终导致服务崩溃。本文将详细记录从问题发现到最终解决的完整过程,包括排查思路、工具使用和修复方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题现象分析
2.1 初始症状描述
凌晨3点,监控系统发出警报,显示生产环境中的API网关节点内存使用率超过95%。该节点配置为4核CPU和16GB内存。服务重启后,内存使用呈现线性增长趋势,每小时约增加500MB,直至耗尽所有物理内存。
2.2 JVM配置检查
服务启动时的JVM参数配置如下:
bash复制-Xmx4g -Xms4g -XX:MaxDirectMemorySize=8g
这个配置表明:
- 堆内存上限为4GB
- 直接内存上限为8GB
- 理论上JVM进程总内存使用不应超过12GB(堆+直接内存)
2.3 异常现象分析
通过监控工具观察到以下矛盾现象:
- 使用
jstat -gcutil <pid> 1000命令查看,堆内存使用率非常健康,Old区长期稳定在30%左右 - 使用
top命令查看,进程的RES(常驻物理内存)却高达12GB - 简单计算:12GB(RES) - 4GB(Heap) - 256MB(Metaspace) ≈ 7.75GB的"失踪"内存
3. 排查工具与方法
3.1 基础工具链
3.1.1 JVM内置工具
jstat:监控堆内存使用情况jcmd:获取JVM内部详细信息- Native Memory Tracking (NMT):追踪JVM原生内存使用
3.2.2 系统级工具
top/htop:查看进程整体内存使用pmap:分析进程内存映射gdb:高级内存分析工具
3.2.3 Netty专用工具
io.netty.buffer.ByteBufUtil:检测Netty缓冲区使用情况io.netty.util.ResourceLeakDetector:内存泄露检测器
