由于 nodejs 天生只支持单进程,虽然 nodejs 使用非阻塞 异步事件驱动,在单进程下性能足够优秀,但是在用户量多的时候也是不行的

使用 socket.io 默认把用户连接数据保存在内存中的,假如我们的服务器是多核服务器,开了多个进程,或者是多个服务器之间多个进程,那么每个进程间是不存在数据共享的,即在不同的进程下连接的用户是不能够给其它用户发送消息的,同样如果部署在 Serverless 上更是如此 (一个连接一个实例)

所以需要有个适配器解决这一问题,适配器作为一个组件,负责将事件广播到所有或部分客户端.

socket.io 提供了以下 4 个适配器供使用

  • Redis 适配器
  • MongoDB 适配器
  • Postgres 适配器
  • Cluster 适配器

由于 Redis 数据库的特性,显然它是作为 socket.io 适配器的最佳选项!

# 安装必要模块

h
$ npm install -S @socket.io/redis-adapter @socket.io/redis-emitter

# 集成 @socket.io/redis-adapter

使用了 nestjs-redis-plus , 作者帮我们集成好了 @socket.io/redis-adapter , 只需要在 main.ts 中加入声明即可

t
//main.ts
import { NestFactory } from '@nestjs/core';
import { VersioningType } from "@nestjs/common";
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
// 引入模块
import { IoRedisAdapter, getAdapterConstructorToken } from 'nestjs-redis-plus';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('api');// 统一前缀
  app.enableVersioning({
    type: VersioningType.HEADER,
    header: 'ApiVersion',
  });
  const config = new DocumentBuilder()
      .setTitle('管理系统API文档')
      .setDescription('管理系统API文档')
      .setVersion('0.0.1')
      .addTag('api')
      .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);
  // 指定使用 IORedis 适配器
  const adapterConstructor = app.get(getAdapterConstructorToken());
  const adapter = new IoRedisAdapter(app, adapterConstructor);
  app.useWebSocketAdapter(adapter);
  await app.listen(9000);
  console.log("server listen on 9000!");
}
bootstrap();
t
//app.module.ts
RedisModule.forRootAsync({
    useFactory: async (config: ConfigService) => config.get('redis'),
    inject: [ConfigService]
}),
// 引入适配器控制器
RedisModule.forAdapterConstructor(),

至此,非常简单的就集成好了 Redis 适配器,这样使用多个服务端可以把消息广播到所有客户端,用户增多只需要增加服务端即可.

使用 Redis-cli 工具查看

h
$ redis-cli
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6479> pubsub channels
1) "socket.io-request#/#"
2) "socket.io-response#/#"
3) "socket.io-response#/#IzmXZC#"
127.0.0.1:6479>

默认在 Redis 中创建了 3 个通道作为传输消息的媒介.

请我喝杯[咖啡]~( ̄▽ ̄)~*

一个放羊娃 微信支付

微信支付

一个放羊娃 支付宝

支付宝