Node.js 如何利用多核 CPU

Node.js 单线程默认只用一个核,利用多核的方案:cluster 模块 fork 多个 worker 共享端口、worker_threads 处理 CPU 密集计算、pm2 的 cluster 模式一键多进程,或容器编排层做水平扩容。

最佳实践
Node.js 事件循环与异步任务示意

单个 JavaScript 主线程一次只在一个 CPU 核上执行,但 Node.js 进程也会使用其他内部线程。 需要并行执行 JavaScript 任务时, 吃满多核有三条路:① cluster 模块按核数 fork 多个进程共享同一端口;② worker_threads 在进程内开真正并行的线程做 CPU 密集计算;③ 用 pm2 等进程管理器的集群模式(本质是封装 cluster)。

cluster:多进程共享端口

const cluster = require('node:cluster');
const os = require('node:os');

if (cluster.isPrimary) {
  const numCPUs = os.cpus().length;
  for (let i = 0; i < numCPUs; i++) cluster.fork();

  cluster.on('exit', (worker) => {
    console.log(`worker ${worker.process.pid} 退出,自动重启`);
    cluster.fork();          // 崩溃自动拉起
  });
} else {
  const http = require('node:http');
  http.createServer((req, res) => {
    res.end(`来自进程 ${process.pid} 的响应`);
  }).listen(3000);
}

主进程只负责 fork 和监管,请求由内核在 worker 间分发(Linux 下 Node 12+ 也可选 round-robin)。

worker_threads:进程内真并行

适合图像处理、加密、大数据计算这类 CPU 密集任务:

const { Worker } = require('node:worker_threads');
const worker = new Worker('./heavy-task.js', { workerData: input });
worker.on('message', resolve);
worker.on('error', reject);

与 cluster 的区别:worker_threads 共享内存(可传 SharedArrayBuffer),适合计算;cluster 是独立进程,适合分摊请求。

pm2 一行搞定

pm2 start app.js -i max   # 按核数起实例,自动负载均衡
pm2 reload app            # 零停机滚动重启

常见问题(FAQ)

Q:fork 多少个 worker 合适?

一般等于物理核数。超线程带来的额外逻辑核收益有限;容器里注意 os.cpus() 看到的是宿主机核数,应根据 cgroup 限额手工指定数量。

Q:cluster 里共享状态怎么办?

各 worker 内存独立,session、计数器等共享状态要放 Redis 等外部存储,不能放进程内存。

Q:什么任务该用 worker_threads 而不是 cluster?

纯计算型(压缩、哈希、图片处理)用 worker_threads;分摊网络请求用 cluster。两类问题,两个工具。

参考资料

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台