通過Node.js內置的process.memoryUsage()方法,定期記錄內存使用數據(如常駐內存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秒打印一次
若內存持續增長,可能存在泄漏。也可使用top、htop或pm2 monit(PM2的監控模塊)實時查看Ubuntu系統中Node.js進程的內存占用。
使用heapdump模塊在代碼中生成堆內存快照(.heapsnapshot文件),或在運行時通過信號觸發。例如:
const heapdump = require('heapdump');
// 手動生成快照(指定路徑)
heapdump.writeSnapshot('/tmp/snapshot-' + Date.now() + '.heapsnapshot');
// 或通過SIGUSR2信號觸發(需啟動時允許信號)
// kill -USR2 <pid>
堆快照會記錄當前內存中的所有對象及其引用關系,是分析泄漏的關鍵數據。
node --inspect app.js;chrome://inspect/#devices;通過日志和堆快照結果,檢查代碼中以下常見泄漏場景:
global.userCache = {}),導致對象無法被GC回收;function outer() { const bigData = [...]; return function inner() { console.log(bigData); } }),外部變量無法釋放;emitter.on('event', listener)未調用emitter.removeListener,導致監聽器持續占用內存;Map或數組緩存數據時,未設置最大容量或過期時間,導致緩存無限增長。const memwatch = require('memwatch-next');
memwatch.on('leak', (info) => {
console.error('Memory leak detected:', info); // 輸出泄漏詳情
});
clinic heapprofiler -- node app.js # 收集數據
clinic heapprofiler --visualize-only profile.heapprofile # 生成火焰圖
火焰圖中寬且持續的矩形代表內存占用高的函數,需重點關注。使用負載測試工具(如autocannon、artillery)模擬高并發請求,觀察內存使用是否隨請求增加而異常增長。例如:
autocannon -c 100 -d 30 http://localhost:3000/api # 100并發,持續30秒
結合日志和堆快照,分析高負載下的內存變化,找出壓力場景下的泄漏點。
通過以上步驟,可系統性地通過Ubuntu下的Node.js日志和工具定位內存泄漏,逐步縮小范圍至具體代碼段。