Node.js 在 CentOS 上的内存如何管理

Mia
Mia
发布时间:2026-08-24| 63人浏览过
原创

前言

Node.js 服务在 CentOS 上跑久后内存上涨并 OOM,不一定只是“堆太小”。处理时要同时看 V8 内存结构、CentOS 的 Swap 与内核参数,以及代码里的常见泄漏点和排查工具,先分清该扩容、调参,还是抓快照定位。

Node.js 服务在 CentOS 上内存持续上涨并最终 OOM,通常要同时看 V8、CentOS 内存策略和应用代码。先分清是堆、rss 还是 external 在涨,再决定扩堆、调 Swap,还是直接查泄漏。

先看清 Node.js 在 CentOS 上到底用的是什么内存

排查时先区分 3 类内存:

Node.js 与 CentOS 内存结构关系图,展示堆内存、栈内存、原生内存以及新生代和老生代的分工
Node.js 内存结构速览把 V8 堆分代、Node.js 内存类型和排查关注点放在一张图里,方便先判断问题出现在哪一层。
  • 堆内存:JavaScript 对象、闭包,最常见上涨点。
  • 栈内存:基本类型、调用信息,生命周期通常较短。
  • 原生内存:C++ 层使用,如 Buffer,不等同于 V8 堆。

V8 堆又分为:

  • 新生代:短生命周期对象,使用 Scavenge。
  • 老生代:长生命周期或晋升对象,通常由 Mark-Sweep、Mark-Compact 处理。

因此内存一直涨时,先判断增长发生在堆内,还是 rss 这类更大的常驻内存范围。

CentOS 系统层面,先把监控和内核参数调到可判断状态

先确认物理内存、Swap 和进程占用

  • free -h:看物理内存和 Swap 总量、已用量。
  • top 或 htop:按 %MEM 找高占用进程。
  • vmstat 1:持续观察虚拟内存和系统活动。
  • /proc/meminfo:查看更细项。

先判断是 Node.js 进程失控,还是系统已频繁使用 Swap。

CentOS 系统内存调优关系图,展示监控命令、Swap、swappiness 和 overcommit 的作用范围
CentOS 内存调优重点这一节更适合做成系统侧关系图:先监控,再根据机器内存和业务延迟要求调整 Swap 与内核策略。

按机器情况调整 Swap

物理内存充足且业务对延迟敏感时,可减少甚至关闭 Swap;内存经常不够时,应补充 Swap。示例:创建 2GB 交换文件。

Node.js 内存排查路径图,展示从 process.memoryUsage 到 DevTools、heapdump 和 memwatch-next 的定位步骤
内存泄漏排查路径当内存持续上涨时,先分清增长指标,再决定是抓堆快照、留现场,还是做运行期预警。
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab  # 永久生效

把 swappiness 调低,减少主动换出

vm.swappiness 默认值是 30。对 Node.js 常驻服务,可按机器情况调低到 10:

sudo sysctl vm.swappiness=10
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf  # 永久生效

必要时限制过度分配

vm.overcommit_memory:

  • 0:默认策略
  • 1:总是允许
  • 2:严格限制

担心单进程申请过多内存时,可考虑设为 2,更早暴露问题。

回到 Node.js 进程本身,重点处理堆上限、泄漏点和数据处理方式

按业务需要调整堆内存上限

V8 在 64 位系统上的默认堆上限大约是 1.4GB,可用 --max-old-space-size 调整,单位 MB:

node --max-old-space-size=2048 app.js  # 设置为2GB

PM2 可设置内存阈值自动重启:

module.exports = {
  apps: [{
    name: 'app',
    script: 'app.js',
    max_memory_restart: '2G'  // 内存超过2GB时自动重启
  }]
};

调大上限只是增加缓冲,不等于解决泄漏。

优先排查几类高发内存泄漏

  • 全局变量:如忘记写 var / let / const,或挂到 global。
  • 未清理的定时器和监听器:setInterval、setTimeout、EventEmitter。
  • 闭包长期持有大对象。
  • 外部资源未释放:如 fs.close、db.connection.end。

大文件和大结果集尽量改成流式处理

const fs = require('fs');
const readStream = fs.createReadStream('large-file.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.pipe(writeStream);  // 流式传输,减少内存占用

缓存要限额,能外置就外置

进程内缓存要限制大小;多实例或数据量较大时,更适合 Redis、Memcached 这类进程外缓存,避免多个 Node.js 进程各自堆积副本。

内存还在涨时,用这些工具把问题定位到对象和代码层

先用 process.memoryUsage() 看增长发生在哪

  • rss:常驻内存
  • heapTotal:堆总内存
  • heapUsed:堆已用内存
  • external:原生内存
setInterval(() => {
  console.log(process.memoryUsage());
}, 5000);

用 Chrome DevTools 分析堆快照

使用 --inspect 启动后,在 Chrome 打开 chrome://inspect,到 Memory 面板对比多个时间点的堆快照,找出持续存活对象和未断开的引用链。

用 heapdump 导出现场

const heapdump = require('heapdump');
heapdump.writeSnapshot('/tmp/heapdump.heapsnapshot', (err, filename) => {
  console.log('堆快照已保存到', filename);
});

用 memwatch-next 监控异常趋势

const memwatch = require('memwatch-next');
memwatch.on('leak', (info) => {
  console.log('内存泄漏检测到:', info);
});

实操时怎么判断该先调系统还是先查代码

  1. 先用 free -h、top、vmstat 1 确认是否系统整体内存紧张。
  2. 再看 process.memoryUsage(),判断增长集中在 heapUsed、rss 还是 external。
  3. 如果只是业务峰值触顶,可调整 --max-old-space-size 或 PM2 的 max_memory_restart。
  4. 如果内存长期单向上涨,优先检查全局变量、监听器、闭包、连接和缓存。
  5. 仍无法定位,再用 DevTools、heapdump、memwatch-next 做对象级分析。

有效治理通常要同时做到:系统参数有边界、进程配置有上限、代码对象能释放、问题现场能留证。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。