确定node内存泄漏
生产服务器内存,整体一直在上升,而且速度很快,5天上升了3000MB,占比就将近50%
从内存使用图中,能很直观看出内存不断上升。重启后又继续一直增加。
定位泄漏点
在尝试浏览器快照,heapdump快照,都没有办法定位泄漏点后,尝试使用alinode找到了问题。
浏览器快照
浏览器控制台memory自带的take snapshot, 对比堆快照查看。但是难度很大,增加的地方很多,每一个增加的类型里面东西都很多,完全看不出来泄漏点,各种找错方向。
安装heapdump,打印内存快照
本地打印堆快照
首先heapdump提供了两种方式打印堆快照
第一种:直接在代码中调用writeSnapshot()
heapdump.writeSnapshot();
// 测试内存快照(对比)
setTimeout(async () => {
try {
const result = await heapdump.writeSnapshot();
} catch (error) {
console.log('error', error);
}
}, 1000 * 60 * 5);
第二种:install heapdump后,不写代码,直接在控制台,用命令打快照
kill -USR2 pgrep -n node
kill 发送信号, pgrep查看当前正在运行的进程并, -n 仅选择最新(最近开始)的匹配进程。
本地打印结果:
然后在浏览器memory中load打印后的heapsnapshot文件,跟浏览器打印的堆快照一样,很难直接看出泄漏点。
用alinode 性能平台打印快照,并且分析
官网文档:help.aliyun.com/document_de…
- Node.js 性能平台全部功能免费提供给用户使用。额免费的,试试不亏
- Node.js 性能平台( Node.js Performance Platform )是面向所有 Node.js 应用提供 性能监控、安全提醒、故障排查、性能优化 等服务的整体性解决方案,尤其适用于中大型 Node.js 应用。Node.js 性能平台凭借对 Node.js 内核深入的理解,提供完善的工具链和服务,协助客户主动、快速发现和定位线上问题。
需要理解关键点
-
alinode改造后的Node 运行时。 这个node基本上是原生node,只是阿里在里面给加入了dump数据的开关,从而可以远程收集性能数据。(简单理解就是在本地node的基础上,加了一些node代码,可以方便用户在性能平台web页面查看性能数据,可以开启打印堆快照等操作)
-
agenthub。这是一个安装在应用服务器上的一个agent。它负责与云端alinode服务进行通信。云端管理系统进行命令下发、机器进行数据上报 都要通过这个agent来执行。
操作步骤
按照官网文档要求操作,有一些需要注意的点。
1.本地安装tnvm
遇到小问题,github上写的地址安装不成功
注意到文档
改用文档中code.aliyun.com... 这个地址就可以了
******$ bash -c "$(curl -fsSL https://code.aliyun.com/aliyun-node/tnvm/raw/master/install.sh)"
=> Downloading tnvm from git to '/Users/***/.tnvm'
=> Cloning into '/Users/***/.tnvm'...
这里注意启用一下
******$ tnvm help
bash: tnvm: command not found
******$ source ~/.bashrc
2. 安装alinode
******$ tnvm install alinode-v6.8.0
alinode-v6.8.0
will download alinode-v6.8.0-darwin-x64.tar.gz
******$ tnvm use alinode-v6.8.0
这里版本选择根据本地node 版本,找对应的alinode版本。
这边node本地版本是14.8.0, 选择alinode6.8.0版本可以兼容。
******$ npm -v
6.14.16
******$ npm -v
14.19.1
注意到这里会直接根据alinode版本,改本地node 和 npm 对应的版本,这个没有关系,可以兼容。
3. 安装agenthub
npm install @alicloud/agenthub -g # 安装 agenthub
// 检验一下是否安装好
******$ which node
/Users/***/.tnvm/versions/alinode/v6.8.0/bin/node
******$ which agenthub
/Users/***/.tnvm/versions/alinode/v6.8.0/bin/agenthub
4. 配置yourconfig,start agenthub
创建应用获得的App ID 和 App Secret,配置在yourconfig.json文件中, 方便agenthub启用,使平台和本地关联(yourconfig.json 放项目根目录下就好)
登录官网,创建新应用
node.console.aliyun.com/#!/owned
然后agenthub start yourconfig.json
5.启动本地node应用
注意这里node 不要忘记配置一下原来启用node的配置(比如 NODE_ENV 和 PORT )
******$ NODE_LOG_DIR=/tmp ENABLE_NODE_LOG=YES NODE_ENV=test PORT=9000 node app.js
6. alinode 平台打印堆快照
在平台找到实例,node进程,查看内存等数据,打印堆快照
******$ lsof -i:9000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 25720 ****** 34u IPv6 0xef2992ea73b53ff 0t0 TCP *:9000 (LISTEN)
注意: 打印堆快照,前后对比时,记得使用一下应用,方便查看内存使用的区别。在打堆快照时,一开始只简单的等待一段时间后重新打印,结果不是很明显。可以用工具重复多次调用应用的接口,或者定位有疑问的页面刷新。
7. 查看和分析堆快照
点击转储上传,然后就可以直接看分析内容了。
可以多打印几个堆快照然后对比查看。
第一个快照是先打印的,后面这个是在本地页面刷新使用过。很明显第二张快照多了一个可疑点Array。
查看详情可以看到对象debug 重复保存了4万4千多,可以定位泄漏问题到一个依赖包,里面的debug。
可以看出依赖包安装了debug包,然后debug对象一直被创建,没有被回收。找到对应代码会发现闭包问题导致的debug对象没有被GC,然后内存泄漏。