Node.js 内存泄漏排查工具与方法(heapdump/clinic)
请说明 Node.js 应用常见的几种内存泄漏场景(全局变量/闭包/定时器/事件监听器),以及如何使用 heapdump、clinic.js、Chrome DevTools 等工具进行排查。
回答
小字辈
常见内存泄漏场景:
- 全局变量:意外将大对象挂在
global上 - 未清除的定时器:
setInterval回调持有引用 - 未移除的事件监听器:
EventEmitter.on()未调用off() - 闭包引用:函数持有大对象的外层作用域引用
- 缓存无限增长:未设上限的 Map/WeakMap
- Stream 未消费:可读流未监听 data 或 pipe 导致内存堆积
排查工具:
1. heapdump:生成堆快照
const heapdump = require('heapdump');
// 通过信号触发
process.kill(process.pid, 'SIGUSR2');
// 或定时
setInterval(() => {
heapdump.writeSnapshot('/tmp/heap-' + Date.now() + '.heapsnapshot');
}, 60000);
- 在 Chrome DevTools → Memory 中加载
.heapsnapshot - 比较两个快照(前/后)分析对象增长
2. clinic.js:诊断工具套件
npx clinic doctor -- node app.js
# 生成可视化报告,定位泄漏源
npx clinic flame -- node app.js # 火焰图分析 CPU
npx clinic heap -- node app.js # 内存分配分析
3. Chrome DevTools(--inspect):
node --inspect app.js
# Chrome 打开 chrome://inspect → Open dedicated DevTools
# Memory 面板:Allocation instrumentation on timeline
4. process.memoryUsage():
setInterval(() => {
const mem = process.memoryUsage();
console.log(`RSS: ${mem.rss / 1024 / 1024} MB`);
console.log(`Heap: ${mem.heapUsed / 1024 / 1024} MB / ${mem.heapTotal / 1024 / 1024} MB`);
// heapUsed 持续增长暗示泄漏
}, 5000);
预防:使用 WeakRef/FinalizationRegistry、设置缓存上限、确保 addEventListener/on 配对 off。