记录一次Node内存泄露排查

52 阅读2分钟

最近遇到一个node项目有内存泄露的问题,内存会有个周期性的升高下降。

image.png

收集数据

  1. 工具选择

常用node内存分析工具有heapdump, Easy-monitor, v8-profiler-rs等,这次使用的是heapdump。

  1. 代码    

function collectMemory() {   
   heapdump.writeSnapshot('./' + Date.now() + '.heapsnapshot') 
}  
setInterval(collectMemory, 60000)

将上面代码放入入口文件,1分钟后就可以看到内存快照被打印了。如果内存变化不大,可以自行调整打印的间隔。

分析数据

  1. 导入devtool

    打开chrome://inspect,点击node专用

image.png

再点击 memory,点击load或者左侧空白区域右击load按时间顺序加载内存快照

image.png

  1. 寻找线索

    主要关注comparion,选择一个快照及对比的快照

image.png

      然后可以看到 size delta列的数据变化,从前几个入手,system和array都没有找到什么有效的信息,看到string的时候感觉是一些log输出,并且下面的详细信息里有个logger函数。

image.png

解决方法

       回到项目里,有三处log相关的函数,一个是用自定义log函数替换了默认的console.log,第二个是‘nestjs’的logger,最后一个是第三方包‘yog-log’。

       先是注释了自定义的log函数,但问题仍然存在;

       nestjs的logger也先排除了,毕竟是一个比较主流的框架,在很多项目使用,有问题应该早爆出来了;

       那就只剩‘yog-log’了,到它的github看了下,有一个issue说到domain可能导致的内存泄露,顺着这个就去node上看了下domain这个包,显示要被废弃了。接着又搜了下,有一些关于domain导致内存泄露的问题,‘yog-log’的源码中确实有用到了domian以及定义了logger的函数,到这基本就定位到问题了。注释后跑了下,内存没有那么大的变化了。

image.png

放到服务器内存也不是一直上升了。

image.png

彩蛋

写文章的时候发现了另外一个分析工具v8-profiler-rs,增加了可视化和辅助分析报告,基本一眼就能看到哪个函数导致了泄漏。

image.png

(v8-profiler-rs的可视化页面,满屏的logger已经很明显了)