博客
关于我
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/

你可能感兴趣的文章
nginx添加模块与https支持
查看>>
Nginx用户认证
查看>>
Nginx的Rewrite正则表达式,匹配非某单词
查看>>
Nginx的使用总结(一)
查看>>
Nginx的使用总结(二)
查看>>
Nginx的可视化神器nginx-gui的下载配置和使用
查看>>
Nginx的是什么?干什么用的?
查看>>
Nginx访问控制_登陆权限的控制(http_auth_basic_module)
查看>>
nginx负载均衡器处理session共享的几种方法(转)
查看>>
nginx负载均衡的5种策略(转载)
查看>>
nginx负载均衡的五种算法
查看>>
Nginx运维与实战(二)-Https配置
查看>>
Nginx配置ssl实现https
查看>>
Nginx配置TCP代理指南
查看>>
Nginx配置——不记录指定文件类型日志
查看>>
Nginx配置代理解决本地html进行ajax请求接口跨域问题
查看>>
Nginx配置参数中文说明
查看>>
Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
查看>>
Nginx配置如何一键生成
查看>>
Nginx配置实例-负载均衡实例:平均访问多台服务器
查看>>