Skip to content

Redis

Redis 传输器实现了发布/订阅消息范式,利用了 Redis 的 Pub/Sub 功能。已发布的消息按频道分类,而不知道哪些订阅者(如果有的话)最终会接收到消息。每个微服务都可以订阅任意数量的频道。此外,可以同时订阅多个频道。通过频道交换的消息是即发即忘的,这意味着如果发布了一条消息但没有感兴趣的订阅者,该消息会被移除且无法恢复。因此,你无法保证消息或事件至少会被一个服务处理。单条消息可以被多个订阅者订阅(并接收)。

安装

要开始构建基于 Redis 的微服务,首先安装所需的包:

bash
$ npm i --save ioredis

概述

要使用 Redis 传输器,请将以下选项对象传递给 createMicroservice() 方法:

typescript
// main
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
  transport: Transport.REDIS,
  options: {
    host: 'localhost',
    port: 6379,
  },
});

提示

Transport 枚举从 @nestjs/microservices 包中导入。

选项

options 属性特定于所选的传输器。Redis 传输器暴露了以下属性。

host连接地址
port连接端口
retryAttempts消息重试次数(默认值:0
retryDelay消息重试间隔(毫秒)(默认值:0
wildcards启用 Redis 通配符订阅,指示传输器在底层使用 psubscribe/pmessage。(默认值:false

官方 ioredis 客户端支持的所有属性也被此传输器支持。

客户端

与其他微服务传输器一样,你有多种选项来创建 Redis ClientProxy 实例。

创建实例的一种方法是使用 ClientsModule。要通过 ClientsModule 创建客户端实例,导入它并使用 register() 方法传递一个选项对象,该对象具有与上面 createMicroservice() 方法中所示相同的属性,以及一个用作注入令牌的 name 属性。在此处阅读更多关于 ClientsModule 的信息。

typescript
@Module({
  imports: [
    ClientsModule.register([
      {
        name: 'MATH_SERVICE',
        transport: Transport.REDIS,
        options: {
          host: 'localhost',
          port: 6379,
        }
      },
    ]),
  ]
  ...
})

也可以使用其他选项来创建客户端(ClientProxyFactory@Client())。你可以在此处阅读相关信息。

上下文

在更复杂的场景中,你可能需要访问有关传入请求的附加信息。使用 Redis 传输器时,你可以访问 RedisContext 对象。

typescript
@MessagePattern('notifications')
getNotifications(@Payload() data: number[], @Ctx() context: RedisContext) {
  console.log(`Channel: ${context.getChannel()}`);
}

提示

@Payload()@Ctx()RedisContext@nestjs/microservices 包中导入。

通配符

要启用通配符支持,请将 wildcards 选项设置为 true。这会指示传输器在底层使用 psubscribepmessage

typescript
const app = await NestFactory.createMicroservice(AppModule, {
  transport: Transport.REDIS,
  options: {
    // Other options
    wildcards: true,
  },
});

确保在创建客户端实例时也传递 wildcards 选项。

启用此选项后,你可以在消息和事件模式中使用通配符。例如,要订阅所有以 notifications 开头的频道,可以使用以下模式:

typescript
@EventPattern('notifications.*')

实例状态更新

要获取连接和底层驱动实例状态的实时更新,你可以订阅 status 流。该流提供特定于所选驱动的状态更新。对于 Redis 驱动,status 流会发出 connecteddisconnectedreconnecting 事件。

typescript
this.client.status.subscribe((status: RedisStatus) => {
  console.log(status);
});

提示

RedisStatus 类型从 @nestjs/microservices 包中导入。

同样,你可以订阅服务器的 status 流以接收有关服务器状态的通知。

typescript
const server = app.connectMicroservice<MicroserviceOptions>(...);
server.status.subscribe((status: RedisStatus) => {
  console.log(status);
});

监听 Redis 事件

在某些情况下,你可能希望监听微服务发出的内部事件。例如,你可以监听 error 事件以在发生错误时触发附加操作。为此,使用 on() 方法,如下所示:

typescript
this.client.on('error', (err) => {
  console.error(err);
});

同样,你可以监听服务器的内部事件:

typescript
server.on<RedisEvents>('error', (err) => {
  console.error(err);
});

提示

RedisEvents 类型从 @nestjs/microservices 包中导入。

底层驱动访问

对于更高级的用例,你可能需要访问底层驱动实例。这对于手动关闭连接或使用驱动特定方法等场景非常有用。但请记住,在大多数情况下,你不需要直接访问驱动。

为此,你可以使用 unwrap() 方法,该方法返回底层驱动实例。泛型类型参数应指定你期望的驱动实例类型。

typescript
const [pub, sub] =
  this.client.unwrap<[import('ioredis').Redis, import('ioredis').Redis]>();

同样,你可以访问服务器的底层驱动实例:

typescript
const [pub, sub] =
  server.unwrap<[import('ioredis').Redis, import('ioredis').Redis]>();

请注意,与其他传输器不同,Redis 传输器返回一个包含两个 ioredis 实例的元组:第一个用于发布消息,第二个用于订阅消息。

基于 NestJS 官方文档翻译