【发布时间】:2018-08-13 10:51:32
【问题描述】:
我正在开发一个完全依赖于 Socket.io 的应用程序。众所周知,NodeJS 默认只在一个内核上运行。现在我想将它扩展到多个核心。我发现很难让 socketio 在 PM2 集群模式下工作。任何示例代码都会有所帮助。
我正在使用炮兵进行测试。当应用程序在单核上运行时,我得到响应,而它在集群中运行,响应将是 NaN
【问题讨论】:
-
嗨,我也有同样的问题。你找到解决办法了吗?
我正在开发一个完全依赖于 Socket.io 的应用程序。众所周知,NodeJS 默认只在一个内核上运行。现在我想将它扩展到多个核心。我发现很难让 socketio 在 PM2 集群模式下工作。任何示例代码都会有所帮助。
我正在使用炮兵进行测试。当应用程序在单核上运行时,我得到响应,而它在集群中运行,响应将是 NaN
【问题讨论】:
NESTjs 服务器
我使用 Socket server 2.4.1,所以我得到了兼容的 redis 适配器,即 5.4.0
我需要扩展 Nest 的 adepter 类“ioAdapter”,该类仅适用于正常的 ws 连接,而不适用于我们的 pm2 集群
import { IoAdapter } from '@nestjs/platform-socket.io';
import * as redisIOAdapter from 'socket.io-redis';
import { config } from './config';
export class RedisIoAdapter extends IoAdapter {
createIOServer(port: number, options?: any): any {
const server = super.createIOServer(port, options);
const redisAdapter = redisIOAdapter({
host: config.server.redisUrl,
port: config.server.redisPort,
});
server.adapter(redisAdapter);
return server;
}
}
其实就是nestjs的实现
现在我需要告诉 Nest im 使用该实现,所以我转到 main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { config } from './config';
import { RedisIoAdapter } from './socket-io.adapter';
import { EventEmitter } from 'events';
async function bootstrap() {
EventEmitter.defaultMaxListeners = 15;
const app = await NestFactory.create(AppModule);
app.enableCors();
app.useWebSocketAdapter(new RedisIoAdapter(app));
await app.listen(config.server.port);
}
bootstrap();
我有很多关于这个的事件,所以我不得不增加我的最大事件数
现在对于您获得的每个网关,您需要使用不同的连接策略,因此您需要直接转到 websocket 而不是使用轮询
...
@WebSocketGateway({ transports: ['websocket'] })
export class AppGateway implements OnGatewayConnection, OnGatewayDisconnect {
...
或者如果你正在使用命名空间
...
@WebSocketGateway({ transports: ['websocket'], namespace: 'user' })
export class UsersGateway {
...
最后一步是install the redis database on your AWS instance and that is another thing; 并安装 pm2
nest build
pm2 i -g pm2
pm2 start dist/main.js -i 4
客户
const config: SocketIoConfig = {
url: environment.server.admin_url, //http:localhost:3000
options: {
transports: ['websocket'],
},
};
您现在可以使用 FireCamp 测试您的 websocket 服务器
【讨论】:
您需要使用 Node 服务器设置 Redis。这是我设法让集群模式与 Socket.io 一起工作的方法
首先安装 Redis。如果您使用的是 Ubuntu,请点击此链接:https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04
然后:
npm i socket.io-redis
现在将 Redis 放置在您的节点服务器中
const redisAdapter = require('socket.io-redis')
global.io = require('socket.io')(server, { transports: [ 'websocket' ]})
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }))
这就是让 PM2 集群模式在我的服务器中与 socket.io 一起工作所要做的全部工作。
【讨论】:
【讨论】:
PM2 文档说
确保您的应用程序是无状态的,这意味着没有本地数据 存储在进程中,例如会话/websocket 连接, 会话内存和相关。使用 Redis、Mongo 或其他数据库 在进程之间共享状态。
Socket.io 不是无状态的。
Kubernetes 实现通过基于源 IP 路由到特定实例来解决状态问题。这仍然不是 100%,因为某些来源可能提供多个 IP 地址。我知道这不是 PM2,但可以让您了解复杂性。
【讨论】: