Nodejs: ws 模块使用 pm2 -i max cluster 模式启动,一核有难 其他核围观?

发布于 1周前 作者 ionicwang 来自 nodejs/Nestjs

Nodejs: ws 模块使用 pm2 -i max cluster 模式启动,一核有难 其他核围观?

服务端是提供的纯 WebSocket 服务做的游戏服务器,模块是 ws,没有用 express,使用 pm2 启动:pm2 start app.js -i max,虽然启动之后能正常显示,但是我拿虚拟机实际测试,分了 2 个 CPU 核心,本地客户端 20-30 个连接不停地发消息给服务端,结果是虚拟机的一个核心占用 50%,另一个核心 0%,测了很多次,结果都一样的,这是不是说明 pm2 不支持 Socket/WebSocket 形式的负载均衡?只支持纯 Web 服务的负载均衡?因为我看百度上对 pm2 的使用,也没说 pm2 这个负载均衡有什么问题,所以请教一下大家,是不是这么回事?

另外想问下,如果 pm2 实现不了 ws 的单机多核负载平衡,有什么其他办法可以实现?我的需求是单机多核心的原生 websocket 服务,谢谢大家.


11 回复

长连接的确实没试过,不知道行不行

实在不行,你把代码复制多份,然后单核启动,一个进程一个端口😂😂


这样的话 进程间通信就会变的极为复杂

别考虑进程间通信的事。 你就把多个端口看成多个地址,在这个上面在做一层逻辑用来维护每个客户端应该连接到哪一个地址

需要群发的时候 应该怎么做呢?

redis 发布订阅?每个进程既是订阅者也是发布者

请问下还有没有更好的方案 总感觉这样的思路写代码越来越复杂

把 ws 那块写成无业务无关的中间件,然后再搭个 http 后台跟中间件通信?

我也找过答案,只找到这个方案: 一实例一端口,cluster 模式下通过环境变量拿到当前的实例 id 递增端口号,通过 nginx 负载均衡 socket,配置 ip-hash 保证同 ip 的请求发到同一实例,实例间通信用 redis。后面想想非单机的场景,这样也能理解了

PM2 官方文档已做出说明了,在 cluster 模式下,你程序的这些进程之间不能有状态或数据直接共享。可选择用 Redis 或其他数据库共享进程数据。

在Node.js中使用ws模块(WebSocket库)配合pm2进行集群部署时,确实需要注意一些细节来避免“一核有难,其他核围观”的问题。这通常指的是在多核环境下,由于Node.js的单线程特性,如果某个实例(核)遇到高负载或阻塞操作,其他实例并不会自动分担其负载。

首先,确保你的WebSocket服务器是无状态的,即每个连接的处理不依赖于其他连接或全局状态。这样,每个pm2实例都可以独立处理连接。

其次,使用pm2-i max--instances max选项来启动最大数量的实例,这通常等于你的CPU核心数。这可以通过以下命令实现:

pm2 start your_app.js --name "websocket-server" -i max --cluster

在代码中,确保你正确设置了WebSocket服务器,例如:

const WebSocket = require('ws');
const http = require('http');

const server = http.createServer();
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws) => {
  console.log('New client connected');
  // 处理连接...
});

server.listen(8080, () => {
  console.log('Server is listening on port 8080');
});

由于WebSocket连接是基于TCP的,每个实例都会监听相同的端口,但pm2会利用操作系统的网络栈来分发连接。因此,只要你的应用逻辑是无状态的,就可以有效地利用多核资源。

回到顶部