You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js集群是否自带负载均衡?如何测试负载均衡有效性?

Node.js Cluster + Socket.io 负载均衡问题

问题描述

我有一台配备4核8逻辑处理器的CPU,使用以下Node.js集群代码创建了8个Worker进程和1个Master进程,但发现Socket连接都倾向于连接到最后一个Worker(对应CPU8)。想请教几个问题:

  1. 这种集群方式是否会自动实现负载均衡?
  2. 是否需要手动配置负载均衡?
  3. 有没有方法测试负载均衡是否正常工作?

我的代码

const os = require('os'), cluster = require('cluster'), cores = os.cpus();
var clusterCount = 0;
if (cluster.isMaster) {
 console.log(`Master ${process.pid} is running`);
 // Fork workers
 for (let i = 0; i < cores.length; i++) {
 cluster.fork();
 }
 cluster.on('exit', (worker, code, signal) => {
 console.log(`worker ${worker.process.pid} died`);
 });
} else {
 const http = require('http'), express = require('express'), socketio = require('socket.io'), process = require('process');;
 var cpu = cores[clusterCount];
 var app = express();
 var port = process.env.PORT || process.argv[2] || 8080;
 var server = app.listen(port);
 var io = socketio(server);
 io.adapter(socketioRedis({ host: config.redis_host, port: config.redis_port }));
 io.on('connection', (socket) => {
 console.log(`User ${socket.id} connected to worker ${process.pid}`);
 });
 console.log(`Worker ${process.pid} started on port: ${port} | ${cpu.model}`);
 clusterCount++;
}

解答

1. 这种集群方式是否会自动实现负载均衡?

Node.js的cluster模块默认提供两种负载均衡策略,但这里有几个关键细节需要注意:

  • 系统支持SO_REUSEPORT(Linux 3.9+、macOS):此时每个Worker会独立监听同一个端口,操作系统会用轮询策略把新连接分发给不同Worker,这是比较高效的方式。
  • 系统不支持SO_REUSEPORT:Master进程会负责监听端口,然后用轮询策略将连接转发给Worker。

但你的代码存在一个明显的bug:clusterCount是全局变量,但每个Worker进程是完全独立的,所以每个Worker启动时clusterCount初始值都是0,执行clusterCount++后也只会在自己的进程内生效,导致所有Worker的cpu变量都指向cores[0],这可能干扰你对Worker对应CPU的判断。

另外,Socket.io是长连接,一旦握手成功,连接会一直绑定到某个Worker,但新连接应该被均衡到不同Worker。你看到所有连接集中到最后一个Worker,大概率是默认负载均衡没生效——要么是代码问题,要么是Socket.io的握手会话关联导致的(不过你已经用了Redis适配器,理论上能解决会话共享问题)。

2. 是否需要手动配置负载均衡?

分两种情况:

  • 如果你的系统支持SO_REUSEPORT,且代码修正后,不需要手动配置,操作系统或Node.js的cluster模块会自动处理负载均衡。
  • 如果系统不支持SO_REUSEPORT,或者Socket.io连接仍出现集中问题,可以手动配置反向代理(比如Nginx),让每个Worker监听不同端口,Nginx用轮询策略将请求转发到各个Worker端口。

3. 如何测试负载均衡是否正常工作?

这里有几个实用的测试方法:

  • 日志统计法:在每个Worker的connection事件中,统计当前Worker的连接数(可以用一个本地计数器,或者把数据上报到Redis),定期打印每个Worker的连接数。如果连接数分布均匀,说明负载均衡有效。
  • 模拟多连接:用socket.io-client写一个测试脚本,循环创建100+个Socket连接,然后查看日志中各个Worker的PID出现次数,判断是否均衡。
  • 进程监控:用top或htop命令查看每个Worker进程的CPU使用率,如果负载均衡正常,各个Worker的CPU占用率应该相差不大。
  • 修正代码验证:把clusterCount替换为cluster.worker.id(Worker ID从1开始),修改Worker中CPU关联的代码为var cpu = cores[cluster.worker.id - 1];,然后启动服务,查看每个Worker对应的CPU是否正确,再观察连接分布。

你的代码需要修正的点

  1. 替换无效的clusterCount:每个Worker的ID可以通过cluster.worker.id获取,修正CPU关联代码:
// 在else分支中
var cpu = cores[cluster.worker.id - 1]; // 因为cluster.worker.id从1开始
  1. 移除冗余的process引入:process是Node.js全局变量,不需要手动require。
  2. 确认Redis适配器配置:确保config.redis_host和config.redis_port是正确的,否则Worker之间无法共享会话,可能导致连接集中问题。

内容的提问来源于stack exchange,提问作者Vardan Betikyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:50:20