Node.js用cluster模块启动多个进程后,React前端怎么连?

沐言 阅读 39

我用 Node.js 的 cluster 模块起了多个工作进程,但前端 React 应用发请求时老是连不上,或者偶尔 502。是不是端口没配对?我主进程监听的是 3001,前端代码里写死了这个端口:

useEffect(() => {
  fetch('http://localhost:3001/api/data')
    .then(res => res.json())
    .then(data => setData(data));
}, []);

但 cluster 启动后,每个 worker 都在同一个端口监听,理论上应该没问题啊?是我理解错了还是哪里漏了配置?

我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
司空圣恩
你的理解有个关键错误:cluster 模块里,不是每个 worker 都能独立监听同一个端口。

根本原因

Node.js 的 cluster 工作模式是「主进程监听端口,多个 worker 共享处理请求」。你不能让每个 worker 都去 listen(3001),这会报 EADDRINUSE 或者只有第一个 worker 抢到端口,其他启动失败。

你遇到的 502 和连不上,大概率是请求被分发了,但 worker 进程没有正确接收处理。

正确的 cluster 写法

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
// 主进程:只创建 worker,不监听端口
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}

// 监听 worker 退出时自动重启
cluster.on('exit', (worker, code, signal) => {
console.log(worker ${worker.process.pid} died, restarting...);
cluster.fork();
});
} else {
// worker 进程:每个 worker 都会执行这段
// 但注意:这里不要自己调用 listen!
// cluster 模块会自动把主进程监听的端口分发给 worker

const server = http.createServer((req, res) => {
// 你的业务逻辑
if (req.url === '/api/data') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'from worker ' + process.pid }));
} else {
res.writeHead(404);
res.end();
}
});

// 关键:cluster 模块会自动处理端口共享
// worker 进程不需要手动 listen,主进程会分发请求过来
server.listen(0, () => {
console.log(Worker ${process.pid} started);
});
}


原理解释

cluster.isMaster 时,只有主进程执行 fork(),不调用 listen。

cluster.isWorker 时,worker 进程调用 server.listen(0),注意这里端口填 0,不是 3001!cluster 模块内部会拦截这个调用,让它绑定到主进程已经监听的端口上,请求会自动在 workers 之间轮询分发。

你之前写错的地方

// 错误写法 - 每个 worker 都试图监听 3001
if (cluster.isMaster) {
// 主进程
const server = http.createServer(...);
server.listen(3001); // 主进程监听了
}

if (cluster.isWorker) {
// worker 也来监听 3001?冲突!
server.listen(3001);
}


这样写会导致主进程和 worker 抢端口,或者只有主进程能处理请求,worker 根本收不到。

前端代码没问题

你前端 fetch 的地址不用改,localhost:3001 对着主进程就行,cluster 会自动把请求分到各个 worker。

如果还有 502,检查一下 worker 进程里有没有未捕获的异常导致进程崩溃退出——这也是 cluster 模式下 502 的常见原因。
点赞 1
2026-03-13 14:06
予曦
予曦 Lv1
cluster 的理解没错,多个 worker 确实共享同一个端口,master 进程负责分发请求。502 和连不上的问题大概率是这几个原因:

第一,worker 进程挂了没重启。cluster 不会自动帮你重启挂掉的 worker,得自己监听 exit 事件。

第二,CORS 没配,浏览器直接拦了。

第三,代码报错导致 worker 频繁崩溃。

给你一个完整的示例,直接改一下就行:

const cluster = require('cluster');
const os = require('os');
const express = require('express');
const cors = require('cors');

if (cluster.isPrimary) {
const cpuCount = os.cpus().length;
console.log(主进程 ${process.pid} 启动,CPU核数: ${cpuCount});

for (let i = 0; i < cpuCount; i++) {
cluster.fork();
}

// worker 挂了自动重启,不然请求就 502 了
cluster.on('exit', (worker, code, signal) => {
console.log(worker ${worker.process.pid} 挂了,重启中...);
cluster.fork();
});
} else {
const app = express();

// CORS 必须配,不然前端跨域请求直接被浏览器干掉
app.use(cors({
origin: 'http://localhost:3000',
credentials: true
}));

app.use(express.json());

app.get('/api/data', (req, res) => {
res.json({
message: 'hello from worker',
pid: process.pid
});
});

app.listen(3001, () => {
console.log(worker ${process.pid} 监听 3001);
});
}


前端代码不用改,http://localhost:3001 是对的。cluster 模式下所有 worker 共享端口是内核级别的负载均衡,对前端透明。

再检查几个点:

确保装了 cors 包,npm install cors

看下控制台有没有 worker 频繁重启的日志,有的话就是代码里有 bug 导致崩溃。

如果用了 nginx 反向代理,记得检查 upstream 配置,不过你本地开发应该没这个。

调试的时候可以先把 worker 数量改成 1,确定没问题再开多进程。
点赞 6
2026-03-01 05:03