插件窝 干货文章 Node.js日志中内存泄漏如何排查

Node.js日志中内存泄漏如何排查

内存 泄漏 快照 使用 630    来源:    2025-05-05

Node.js 内存泄漏排查指南

内存泄漏是 Node.js 应用中常见的问题,会导致应用内存使用量持续增长,最终可能引发进程崩溃。以下是系统性的排查方法:

1. 确认内存泄漏现象

首先确认是否存在内存泄漏: - 监控进程内存使用量(process.memoryUsage()) - 使用操作系统工具(如 top, htop, pm2 monit) - 观察 GC 行为(--trace-gc 标志)

2. 使用内置工具

2.1 堆快照分析

# 生成堆快照
node --inspect your-app.js
# 然后通过 Chrome DevTools 获取堆快照

# 或者直接生成堆转储
kill -USR2 <pid>  # 生成堆转储到 /tmp/ 目录

2.2 内存分析标志

node --inspect --trace-gc --trace-gc-verbose your-app.js

3. 使用专业工具

3.1 Chrome DevTools

  1. 启动应用时添加 --inspect 标志
  2. 打开 chrome://inspect
  3. 使用 Memory 标签页获取和分析堆快照

3.2 Clinic.js

npm install -g clinic
clinic doctor -- node your-app.js

3.3 heapdump 模块

const heapdump = require('heapdump');

// 手动触发堆转储
heapdump.writeSnapshot('/path/to/snapshot.heapsnapshot');

4. 常见内存泄漏模式及排查点

4.1 全局变量

  • 意外的全局变量(未使用 var/let/const
  • 缓存未设置上限

4.2 闭包

  • 大型对象被闭包引用
  • 事件监听器未正确移除

4.3 定时器

  • setInterval 未清除
  • 定时器回调中引用大型对象

4.4 事件监听器

  • EventEmitter 监听器未移除
  • 高频事件添加过多监听器

4.5 数据库/缓存连接

  • 连接池未正确关闭
  • 查询结果未释放

5. 分析方法

  1. 比较多个时间点的堆快照
  2. 查找保留大小(retained size)大的对象
  3. 查看对象的支配树(dominator tree)
  4. 关注字符串、闭包、数组等常见泄漏点

6. 预防措施

  • 使用 --max-old-space-size 限制内存使用
  • 实现内存监控和报警
  • 定期进行压力测试
  • 使用 TypeScript 减少意外全局变量
  • 对缓存设置大小限制

7. 示例代码片段

// 内存监控中间件
app.use((req, res, next) => {
  const mem = process.memoryUsage();
  console.log(`Memory: ${Math.round(mem.heapUsed / 1024 / 1024)}MB`);
  next();
});

// 强制GC(仅用于测试)
if (global.gc) {
  setInterval(() => {
    global.gc();
    console.log('Manual GC');
  }, 30000);
}

通过以上方法,您可以系统地排查和解决 Node.js 应用中的内存泄漏问题。