通过内置工具或第三方库定期记录内存使用情况,观察是否持续增长(内存泄漏的核心特征)。
process.memoryUsage()获取Node.js进程的内存占用,打印rss(常驻内存)、heapUsed(已使用的堆内存)等指标,通过日志分析趋势。例如:setInterval(() => {
const memory = process.memoryUsage();
console.log(`RSS: ${(memory.rss / 1024 / 1024).toFixed(2)}MB, HeapUsed: ${(memory.heapUsed / 1024 / 1024).toFixed(2)}MB`);
}, 5000); // 每5秒记录一次
memwatch-next监听内存泄漏事件,当内存持续增长时触发报警:const memwatch = require('memwatch-next');
memwatch.on('leak', (info) => {
console.error('Memory leak detected:', info); // 输出泄漏详情
});
pm2(Node.js进程管理器)的monitor命令实时查看内存使用情况,支持历史数据对比。内存快照是定位泄漏的关键证据,通过工具生成堆内存的快照文件(.heapsnapshot),记录某一时刻的对象分布。
heapdump模块:在代码中引入heapdump,在可疑阶段(如接口调用后、定时任务执行后)生成快照,或通过SIGUSR2信号触发:const heapdump = require('heapdump');
// 手动生成快照(写入指定路径)
heapdump.writeSnapshot('/tmp/snapshot-' + Date.now() + '.heapsnapshot');
// 通过信号触发(终端执行:kill -USR2 <pid>)
node --inspect启动应用,在Chrome浏览器中访问chrome://inspect,连接Node.js进程后,使用Memory面板的“Take heap snapshot”功能生成快照。使用Chrome DevTools打开.heapsnapshot文件,通过Comparison视图(对比不同时间点的快照)或对象引用链分析,找出占用内存持续增长且不应存在的对象。
Delta(增长量)大的对象(如Array、Object)。global对象上的属性(如global.leak = someObject)。emitter.on('event', listener)未调用removeListener。Map、Set)无限增长,未设置大小限制。对于复杂场景,可使用Clinic.js Heap Profiler等专业工具,生成火焰图(Flame Graph)直观展示内存分配情况,快速定位泄漏点。
# 安装Clinic.js
npm install -g clinic
# 启动分析(运行应用)
clinic heapprofiler -- node app.js
# 按Ctrl+C停止,自动生成报告并在浏览器打开
--autocannon参数模拟真实用户请求,更准确地暴露生产环境中的泄漏问题:clinic heapprofiler --autocannon "POST http://localhost:3000/api" -- node app.js
根据分析结果,修复代码中的内存泄漏问题:
global对象,使用let/const声明局部变量。null。removeListener或off移除监听器。lru-cache库),定期清理过期数据。修复后,重复监控内存使用和生成快照的步骤,确认内存占用不再持续增长,泄漏问题已解决。