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

你可能感兴趣的文章
Python3编写网络爬虫10-数据存储方式三-CSV文件存储
查看>>
python3读取redis返回数据带有'b'的问题
查看>>
Python3连接MySQL
查看>>
Python关于isinstance函数的解析 | 附Demo(全)
查看>>
Python3:setup.py:完成所有任务的PIP安装(Build_ext+Install)
查看>>
python4.0 gil_Python 并发编程系列--1、浅谈GIL历史及对多线程的影响
查看>>
python60行绘图程序_天底下最简单的QT画图板,就一个类,60行代码
查看>>
Python: AES加密与解密
查看>>
Python: Range() 最大尺寸;动态的还是静态的?
查看>>
Python: Windows下用 multiprocessing 的深坑
查看>>
python:Could not find platform independent libraries <prefix>解决方法
查看>>
Python:datetime tzinfo 时区名称文档
查看>>
Python:deepcopy(list) vs new_list = old_list[:]
查看>>
Python:Google API - 从消息中获取 mimeTypes
查看>>
Python:Google API - 从消息中获取 mimeTypes
查看>>
Python:subprocess.call,stdout to file,stderr to file,在屏幕上实时显示stderr
查看>>
Python:TypeError:无法连接“str“和“int“对象
查看>>
Python:XPath 在 ElementTree 中不可用
查看>>
Python:从 FTP 服务器下载文件
查看>>
python:从列表中创建元组列表
查看>>