【问题标题】:How to use PM2 Cluster with Socket IO?如何使用带有 Socket IO 的 PM2 集群?
【发布时间】:2018-08-13 10:51:32
【问题描述】:

我正在开发一个完全依赖于 Socket.io 的应用程序。众所周知,NodeJS 默认只在一个内核上运行。现在我想将它扩展到多个核心。我发现很难让 socketio 在 PM2 集群模式下工作。任何示例代码都会有所帮助。

我正在使用炮兵进行测试。当应用程序在单核上运行时,我得到响应,而它在集群中运行,响应将是 NaN

When Ran Without Cluster

【问题讨论】:

  • 嗨,我也有同样的问题。你找到解决办法了吗?

标签: node.js socket.io pm2


【解决方案1】:

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 服务器

【讨论】:

    【解决方案2】:

    您需要使用 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 一起工作所要做的全部工作。

    【讨论】:

      【解决方案3】:

      尝试使用这个库:

      https://github.com/luoyjx/socket.io-redis-stateless

      通过redis让socket io无状态

      【讨论】:

        【解决方案4】:

        PM2 文档说

        确保您的应用程序是无状态的,这意味着没有本地数据 存储在进程中,例如会话/websocket 连接, 会话内存和相关。使用 Redis、Mongo 或其他数据库 在进程之间共享状态。

        Socket.io 不是无状态的。

        Kubernetes 实现通过基于源 IP 路由到特定实例来解决状态问题。这仍然不是 100%,因为某些来源可能提供多个 IP 地址。我知道这不是 PM2,但可以让您了解复杂性。

        【讨论】:

        • 无状态是有道理的。
        猜你喜欢
        • 1970-01-01
        • 2022-01-20
        • 2021-11-22
        • 2018-04-02
        • 1970-01-01
        • 1970-01-01
        • 2017-03-07
        • 2021-03-28
        • 1970-01-01
        相关资源
        最近更新 更多