博客
关于我
Netty堆外内存泄露排查与总结
阅读量:67 次
发布时间:2019-02-26

本文共 1170 字,大约阅读时间需要 3 分钟。

今天,我遇到了一个让人头疼的问题,Netty框架在运行过程中出现了堆外内存泄露,导致服务端 WebSocket 连接大量出现5xx错误。作为一个刚入行的开发人员,我对这种问题还不太熟悉,于是决定一步步深入排查,找到问题的根源并解决它。

首先,问题开始于Nginx出现大量5xx错误,这通常意味着服务端在处理请求时出现了问题。根据监控平台的日志,我注意到某台机器在同一时间点爆发了GC,并且 JVM 线程被阻塞。这让我怀疑是不是内存问题导致的。

接下来,我查看了日志,发现log4j2在大量打印日志,导致NIO线程被阻塞。这可能是因为log4j2的配置文件中没有正确注释掉控制台打印的日志模块,导致大量日志被同步打印,阻塞了线程。于是,我尝试注释掉这部分日志模块,但问题并没有解决,这让我开始怀疑还有其他隐藏的问题。

然后,我发现日志中出现了大量的failed to allocate 64(bytes) of direct memory错误,这表明堆外内存不足,Netty框架自己封装了一个OutOfDirectMemoryError。这让我意识到可能存在堆外内存泄露的问题,但之前的监控指标显示没有异常,我感到有些困惑。

进一步分析,我注意到Netty在分配堆外内存时使用了PlatformDependent.incrementMemory()方法,发现这是在堆外内存分配时触发的计数器检查。通过检查代码,我发现当堆外内存已使用超过用户指定的上限时,Netty会抛出自定义的OOM错误。这表明堆外内存确实没有被正确释放。

为了监控堆外内存的使用情况,我通过反射获取了DIRECT_MEMORY_COUNTER字段,并在控制台打印内存使用情况。初步发现内存在缓慢增长,随着时间的推移,内存使用量迅速升高,达到几百MB,最后导致OOM爆发。

为了找出内存泄露的具体原因,我在本地环境中模拟了客户端连接和关闭的过程,观察内存变化。发现每次客户端连接断开时,堆外内存会增加一段256B的内存,并且无法释放。这让我怀疑是在断开连接时发生了内存泄露。

通过使用Idea进行线上跟踪,我定位到在onDisconnect事件处理中,Netty框架在某个地方申请了堆外内存但没有正确释放。在进一步的调试中,我发现了一个潜在的NPE异常,发现了subType字段为null的情况,导致内存泄露。

最终,我修改了代码,确保在断开连接时subType字段被正确赋值,避免了NPE异常的发生。随后,我进行了本地和线上的验证,确认问题得到解决。

通过这次排查过程,我学会了如何一步步缩小问题范围,利用调试工具定位内存泄露的根源,并学会了如何通过反射监控堆外内存,确保框架的稳定性。这次经历让我对Netty框架的内存管理有了更深入的理解,也提升了我解决复杂问题的能力。

转载地址:http://aobz.baihongyu.com/

你可能感兴趣的文章
Node-RED中连接Mysql数据库并实现增删改查的操作
查看>>
Node-RED中通过node-red-ui-webcam节点实现访问摄像头并截取照片预览
查看>>
Node-RED中配置周期性执行、指定时间阶段执行、指定时间执行事件
查看>>
Node-RED安装图形化节点dashboard实现订阅mqtt主题并在仪表盘中显示温度
查看>>
Node-RED怎样导出导入流程为json文件
查看>>
Node-RED订阅MQTT主题并调试数据
查看>>
Node-RED通过npm安装的方式对应卸载
查看>>
node-request模块
查看>>
node-static 任意文件读取漏洞复现(CVE-2023-26111)
查看>>
Node.js 8 中的 util.promisify的详解
查看>>
node.js debug在webstrom工具
查看>>
Node.js RESTful API如何使用?
查看>>
node.js url模块
查看>>
Node.js Web 模块的各种用法和常见场景
查看>>
Node.js 之 log4js 完全讲解
查看>>
Node.js 函数是什么样的?
查看>>
Node.js 函数计算如何突破启动瓶颈,优化启动速度
查看>>
Node.js 切近实战(七) 之Excel在线(文件&文件组)
查看>>
node.js 初体验
查看>>
Node.js 历史
查看>>