Node.js内存泄漏

Node.js应用程序中的内存泄漏问题

症状

  • 应用程序内存使用量持续增长
  • 出现"JavaScript heap out of memory"错误
  • 应用性能随时间推移而下降
  • 服务器最终崩溃或重启

可能的原因

  • 未正确关闭的事件监听器
  • 全局变量持续增长
  • 闭包引用导致的对象无法被垃圾回收
  • 定时器未清除

解决方案

1. 使用内存分析工具

步骤:

  1. 使用Node.js --inspect参数启动应用
  2. 使用Chrome DevTools的Memory面板
  3. 或使用专业工具如heapdump、clinic.js等
  4. 分析内存快照找出泄漏源

代码示例:

node --inspect app.js
# 然后在Chrome中访问chrome://inspect

说明:

内存分析工具可以帮助识别哪些对象占用了大量内存,以及它们为什么没有被垃圾回收。

2. 正确管理事件监听器

步骤:

  1. 在不需要时移除事件监听器
  2. 避免在循环或频繁执行的函数中添加监听器
  3. 使用once选项或removeListener方法

代码示例:

// 添加监听器
element.addEventListener('click', handler);

// 移除监听器
element.removeEventListener('click', handler);

// 或使用once选项
element.addEventListener('click', handler, { once: true });

说明:

未移除的事件监听器是内存泄漏的常见原因,特别是在组件销毁或页面切换时。

3. 避免全局变量积累

步骤:

  1. 限制全局变量的使用
  2. 使用局部作用域
  3. 实现缓存过期和清理机制

代码示例:

// 不好的做法 - 全局缓存无限增长
const globalCache = {};

// 更好的做法 - 实现缓存限制
const LRUCache = require('lru-cache');
const cache = new LRUCache({
  max: 500,
  maxAge: 1000 * 60 * 60 // 1小时过期
});

说明:

全局变量中存储的数据不会被垃圾回收,如果持续增长会导致内存泄漏。

4. 清除定时器

步骤:

  1. 保存setTimeout和setInterval的返回值
  2. 在适当的时机调用clearTimeout或clearInterval
  3. 特别是在组件卸载或请求完成时

代码示例:

// 设置定时器
const timerId = setTimeout(() => {
  // 执行操作
}, 1000);

// 清除定时器
clearTimeout(timerId);

说明:

未清除的定时器会阻止相关的回调函数及其闭包被垃圾回收,导致内存泄漏。

标签

node.js内存性能运行时