在Ubuntu系统中,检测Node.js应用的内存泄漏需结合内存监控、快照分析、工具辅助及代码审查等多步骤,以下是具体流程:
通过Node.js内置的process.memoryUsage()方法定期记录内存使用情况,观察**堆内存(heapUsed)或常驻内存(rss)**是否持续增长(无下降趋势)。例如:
setInterval(() => {
const memoryUsage = process.memoryUsage();
console.log(`RSS: ${(memoryUsage.rss / 1024 / 1024).toFixed(2)}MB, Heap Used: ${(memoryUsage.heapUsed / 1024 / 1024).toFixed(2)}MB`);
}, 5000); // 每5秒打印一次
若内存值随时间持续上升,可能存在泄漏。
使用heapdump模块生成堆内存快照(.heapsnapshot文件),通过Chrome DevTools对比不同时间点的快照,分析内存增长的对象及引用链:
npm install heapdumpconst heapdump = require('heapdump');
heapdump.writeSnapshot(`/tmp/snapshot-${Date.now()}.heapsnapshot`);
chrome://inspect,选择Node.js进程;const memwatch = require('memwatch');
memwatch.on('leak', (info) => {
console.error('Memory leak detected:', info); // 输出泄漏详情(如growth、reason)
});
pm2 monit命令实时查看内存使用曲线,或通过pm2 logs过滤内存异常日志。通过Node.js启动参数--expose-gc暴露垃圾回收接口,手动触发GC并观察内存是否下降:
node --expose-gc app.jsif (global.gc) global.gc(); // 手动触发垃圾回收
console.log('Memory after GC:', process.memoryUsage().heapUsed / 1024 / 1024);
若GC后内存无明显下降,说明存在无法回收的对象(如全局变量、循环引用)。
内存泄漏的常见原因包括:
global(如global.leak = data);return function() { console.log(leak); });removeListener(如emitter.on('event', handler));cache[key] = data未设置过期时间)。使用工具(如artillery、ab)模拟高并发场景,观察内存使用是否随请求量增加而异常增长(如每秒请求数增加10倍,内存增长超过2倍)。例如:
artillery quick --count 1000 --rate 100 http://localhost:3000/api/leak
压力测试能快速暴露高负载下的内存泄漏,帮助验证修复效果。
通过以上步骤,可系统性地检测Ubuntu下Node.js应用的日志内存泄漏问题,并结合工具与代码审查定位根源,最终解决问题。