要解决内存泄漏,首先需要定位泄漏源,以下是CentOS环境下常用的工具组合:
npm install heapdump --save
。heapdump.writeSnapshot('/path/to/snapshot.heapsnapshot')
手动生成堆快照(或在代码中设置定时器定期生成)。生成的.heapsnapshot
文件可通过Chrome浏览器打开,利用Chrome DevTools的Memory面板分析内存中的对象分布,找出异常增长的对象(如未被释放的全局变量、缓存等)。node --inspect app.js
启动应用,然后在Chrome中访问chrome://inspect
,连接至Node.js进程,使用Memory面板的“Heap Snapshot”功能捕获实时内存状态,对比不同时间点的快照,识别内存泄漏的对象。clinic heapprofiler -- node server.js
启动分析,Ctrl+C停止后会生成可视化火焰图。火焰图的X轴表示时间/样本数量,Y轴表示调用栈深度,宽度表示内存占用比例,通过观察宽且持续的函数调用(如某个模块的频繁内存分配),快速定位泄漏根源。定位到泄漏源后,需针对性修复,常见原因及解决方法如下:
global.xxx = data
),使用let
/const
替代var
声明变量,确保变量在作用域内被回收。EventEmitter
实例(如http.Server
、fs.FSWatcher
),在不需要时调用removeListener
或removeAllListeners
移除监听器,防止内存持续占用。fs.close
)、数据库连接(如mongoose.connection.close
)、套接字(socket.destroy
)等资源,避免资源句柄泄漏。lru-cache
模块),定期清理过期缓存,避免缓存无限增长占用内存。通过监控工具定期检查内存使用情况,及时发现泄漏趋势:
top
、htop
(需安装:yum install htop
)、vmstat 1
(每秒刷新一次内存统计)命令,查看Node.js进程的RES
(常驻内存)或%MEM
(内存占比)是否持续增长。process.memoryUsage()
定期输出内存使用信息(如heapUsed
、heapTotal
、rss
),例如:setInterval(() => {
const memory = process.memoryUsage();
console.log(`Heap Used: ${(memory.heapUsed / 1024 / 1024).toFixed(2)}MB`);
}, 5000);
memwatch-next
监控内存泄漏,安装后添加以下代码:const memwatch = require('memwatch-next');
memwatch.on('leak', (info) => {
console.error('Memory leak detected:', info);
});
--max-old-space-size
参数调整(单位:MB),例如:node --max-old-space-size=4096 app.js # 设置为4GB
或通过环境变量设置:export NODE_OPTIONS="--max-old-space-size=4096"
注意:此方法仅为临时缓解,需结合泄漏修复使用。node -p "process.arch"
验证,输出x64
即为64位)。pm2 start app.js --max-memory-restart 4G # 内存超过4GB时自动重启
PM2还支持内存监控(pm2 monit
)和日志分析。cluster
模块,将应用分布在多个CPU核心上,分散单个进程的内存压力。例如:const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
for (let i = 0; i < numCPUs; i++) cluster.fork();
} else {
require('./app.js'); // 子进程运行应用
}
sudo fallocate -l 4G /swapfile # 创建4G交换文件
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab # 永久生效
autocannon
或artillery
模拟高并发请求,结合内存分析工具(如Clinic.js),在接近生产环境的场景下检测内存泄漏。