记一次 Node.js 内存泄漏排查
发布于 7 年前 作者 DuanPengfei 4406 次浏览 来自 分享

首先感谢 alinode 团队 https://alinode.aliyun.com 的支持。

大概一个月前,在 alinode 管理页面看到内存占用成锯齿状上升,虽然上涨速度很慢,但是最低点与最高点都在稳定上涨,意识到应该是内存泄漏了。

虽然有关内存泄漏方面的文章读了一些,也知道需要看内存快照,内存时间线等日志来分析内存泄漏,但是真正自己上手时还是有些懵逼了。使用 alinode 将程序运行不同时间点的内存快照导出然后对比分析(这时使用的是 devtools),因为对于 devtools 了解不深,其中显示的各种参数完全看不懂。但是使用 compare 得到的是 closure 有 50K 的新增却没有减少,这时候大概就定位到了这里,开始一层层打开树状图追踪。

从开始追踪就已经一步步走到了坑里,在内存快照中看到了一个函数 onUncaughtException 被频繁调用,这个函数是我写给 process.on('uncaughtException') 的回调函数。这时候我深信不疑是这里出了问题,也不能说不对,但是真实的错误栈却不在这里,存在另一个地方频繁发生 uncaughtException 才导致这里看起有问题,而真正的问题却被我忽略了。

发现问题所在后我就反复的看代码,怎么也没发现有错误出现。在正常工作与查内存泄漏中徘徊了将近一个月。当初是因为对 ONS 有些疑问被一个朋友拉近了一个群,进来就知道这是朴灵大大 Node.js 团队的群了,ONS 的问题直接就没有问,这个群也就淹没在大堆消息里了。昨天突然想起我的内存泄漏问题正是这个群覆盖的范畴,赶紧在群里反应了我的问题,得到了@奕钧的及时响应,先是根据我的截图猜测到是事件重复监听,后又加入我的项目帮忙查看内存快照,最终追查到了真正的问题所在,确实是我的一段代码对 error 事件进行反复的监听。

定位到问题再去看代码时瞬间清醒,这样的错误我犯过两次了。可能是 HTTP 处理写习惯了,碰到 TCP 处理时总是忘记创建一个连接池,还是在每次请求时创建新的连接并监听事件。现在记录下这个过程并深刻反思,事不过三。

5 回复

棒棒哒💯

帖段泄露的代码上来学习一下呗

楼主, 群号呢?

@XiaozhongLiu “Node.js 性能平台客户群”群的钉钉群号: 11794270

来自酷炫的 CNodeMD

回到顶部