首先需要通过系统工具或Node.js自带功能确认是否存在内存泄漏。常用方法包括:
top、htop实时查看Node.js进程的内存占用(关注RES(常驻内存)列),若内存持续增长且不回落,则可能存在泄漏;pm2(需提前安装:npm install pm2 -g)启动应用(pm2 start app.js),通过pm2 monit监控内存使用趋势,或通过pm2 list查看进程的内存占用情况;process.memoryUsage()定时打印内存信息(如每10秒一次),观察heapUsed(堆内存使用量)是否持续增加。定位泄漏点需通过工具生成堆内存快照,对比不同时间点的内存状态:
--inspect参数(如node --inspect app.js);chrome://inspect/#devices,找到目标Node.js进程,点击“inspect”;npm install heapdump --save;heapdump.writeSnapshot('/tmp/snapshot.heapsnapshot')),可在怀疑泄漏的代码段前后调用;.heapsnapshot文件可通过Chrome DevTools打开分析。npm install memwatch-next --save;memwatch.on('leak', (info) => console.error('Memory leak detected:', info)),当内存持续增长时会触发回调,输出泄漏信息。通过上述工具生成的快照,重点关注以下常见泄漏原因:
var name = 'value')会一直存在于全局对象(global)中,无法被垃圾回收;function outer() { var largeData = [...]; return function inner() { console.log(largeData); } });clearInterval或clearTimeout的定时器(如setInterval(() => {}, 1000))会持续执行,引用外部变量;removeListener或off的事件监听器(如emitter.on('event', callback))会持续占用内存;fs.readFile未调用close)。针对定位到的泄漏点,采取相应的修复措施:
let或const声明变量,避免意外创建全局变量;clearInterval(timerId)或clearTimeout(timeoutId);componentWillUnmount(React)或类似生命周期钩子中,调用emitter.removeListener('event', callback)移除监听器;try-finally或async/await确保资源正确关闭(如fs.readFile后调用fs.close,数据库连接后调用connection.end)。fs.readFileSync),改用fs.createReadStream逐行读取;lru-cache模块),定期清理过期缓存;autocannon或artillery模拟高并发请求,观察内存使用是否持续增长,暴露潜在泄漏;pm2的--max-memory-restart参数(如pm2 start app.js --max-memory-restart 512M),当内存超过阈值时自动重启应用,防止进程崩溃。若上述方法难以定位问题,可使用Clinic.js工具生成可视化火焰图,直观查看内存泄漏点:
npm install -g clinic;clinic heapprofiler -- node app.js,执行疑似泄漏的操作后按Ctrl+C停止;