Node.js 如何利用多核 CPU
Node.js 单线程默认只用一个核,利用多核的方案:cluster 模块 fork 多个 worker 共享端口、worker_threads 处理 CPU 密集计算、pm2 的 cluster 模式一键多进程,或容器编排层做水平扩容。
单个 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。两类问题,两个工具。