Node.js默认的V8堆内存限制(约1.4GB/32位、2GB/64位)可能不足以应对大型数据处理或高并发场景。通过--max-old-space-size参数可调整堆内存上限(单位:MB),例如设置为4GB:
node --max-old-space-size=4096 your_script.js
或在package.json的scripts中配置(推荐,避免每次手动输入):
"scripts": {
"start": "node --max-old-space-size=8000 app.js"
}
此方法适用于短期缓解,但需结合代码优化避免掩盖根本问题。
内存泄漏是导致OOM的常见原因,需重点检查以下场景:
user = {...}),全局变量会一直占用内存直至进程结束。function createClosure() {
const largeData = new Array(1e6);
return function() { console.log(largeData[0]); }; // largeData未被释放
}
优化:将largeData定义在函数内部或及时置空。EventEmitter监听器会导致对象无法被回收。例如:const EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('event', () => {}); // 未移除的监听器
优化:使用emitter.off()或emitter.removeAllListeners()移除监听器。setInterval或setTimeout会导致回调函数及关联对象持续存在。例如:setInterval(() => { console.log('Running...'); }, 1000); // 未清除的定时器
优化:在组件销毁或不需要时调用clearInterval/clearTimeout。处理大文件(如Excel、JSON、日志)时,使用fs.createReadStream(读取)和fs.createWriteStream(写入)代替fs.readFileSync/fs.writeFileSync,避免将整个文件加载到内存。例如,用xlsx库分段读取Excel:
const XLSX = require('xlsx');
const fs = require('fs');
const workbook = XLSX.readFile('large.xlsx');
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
// 分块处理(每1000行一次)
const chunkSize = 1000;
for (let i = 1; i <= worksheet['!ref'].split(':')[1].match(/\d+/)[0]; i += chunkSize) {
const chunk = XLSX.utils.sheet_to_json(worksheet, { header: 1, range: i + ':' + Math.min(i + chunkSize - 1, worksheet['!ref'].split(':')[1].match(/\d+/)[0]) });
console.log('Processed chunk:', chunk.length);
}
此方法显著降低内存峰值,适用于百万级数据的处理。
使用工具生成堆内存快照,对比分析内存增长的对象:
heapdump,在可疑位置生成快照文件(.heapsnapshot),用Chrome DevTools打开分析:npm install heapdump
const heapdump = require('heapdump');
// 在需要分析的位置生成快照
heapdump.writeSnapshot('/tmp/heap-${Date.now()}.heapsnapshot');
node --inspect启动应用,在Chrome中访问chrome://inspect,选择目标进程,切换至Memory面板,点击“Take heap snapshot”生成快照,对比前后快照找出增长的对象。console.log(process.memoryUsage()),监控内存使用趋势(如rss(常驻内存)、heapUsed(堆内存使用)持续增长则可能存在泄漏)。当物理内存不足时,交换空间(Swap)可将部分内存数据转移至磁盘,释放物理内存。步骤如下:
# 创建1GB交换文件(路径可自定义)
sudo fallocate -l 1G /swapfile
# 设置权限(仅root可读写)
sudo chmod 600 /swapfile
# 格式化为交换空间
sudo mkswap /swapfile
# 启用交换空间
sudo swapon /swapfile
# 永久生效(编辑/etc/fstab)
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
注意:Swap性能远低于物理内存,仅作为临时解决方案,长期仍需优化代码或增加物理内存。
通过PM2等进程管理工具监控内存使用,当内存超过阈值时自动重启应用,避免进程崩溃:
# 全局安装PM2
npm install -g pm2
# 启动应用并设置内存限制(如超过800MB重启)
pm2 start app.js --max-memory-restart 800M
# 监控内存使用
pm2 monit
PM2还支持集群模式(Cluster Mode),将应用分布在多个CPU核心上,提升内存利用率和并发处理能力。
以上方法需结合场景使用:短期可通过增加内存限制或交换空间缓解,长期需通过代码优化、内存分析和工具监控彻底解决问题。