我正在使用nest js frameworknuts消息代理.

首先,我有Gateway Service个路由.

Controller

@ApiOperation({ description: 'Cheking phone and code' })
  @Get('/checkPhoneCode')
  @ApiQuery({ name: 'phone' })
  @ApiQuery({ name: 'code' })
  checkPhoneCode(@Query() phone_with_code: PhoneWithCode) {
    console.log('gateway check phone');
    return this.authenticationService.checkPhoneCode(phone_with_code);
  }

Service

async checkPhoneCode(phone_with_code: PhoneWithCode) {
    console.log('sending nuts request to check phone');
    return this.nats.send('api-gateway.authentication.checkPhoneCode', 
    phone_with_code);
  }

我也有Auth Service个等待坚果调用执行操作.

Controller

 @MessagePattern('api-gateway.authentication.checkPhoneCode')
   checkPhoneCode(phone_with_code: PhoneWithCodeDto) {
    console.log('controller check phone');
    return this.authenticationService.checkPhoneCode(phone_with_code);
  }

Service

 public async checkPhoneCode(phoneCodeDto: PhoneWithCodeDto) {
        const { phone } = phoneCodeDto;
        const { code } = phoneCodeDto;
    
        validator.isMobilePhone(phone);
    
        console.log('sending request');
        const response = await firstValueFrom(
         
          this.httpService.get(
            `https://example.com/method/v1.0/account/checkphonecode/?phone=${phone}&code=${code}`,
          ),
        );
    
        if (!response) {
          return 'error while checking phone code';
        }
    
        if(!response.data.correct){
          return response.data;
        }
    
        return response.data;
        // return this.generatePhoneVaildToken(phone);
      
      }

当我调用网关服务时,auth方法执行两次. 我添加了控制台日志(log)来调试,我看到了什么:

api5dev-api-gateway     | gateway check phone
api5dev-api-gateway     | sending nuts request to check phone
api5dev-authentication  | controller check phone
api5dev-authentication  | sending request
api5dev-authentication  | controller check phone
api5dev-authentication  | sending request

为什么AUTH CONTROLLER呼叫了两次?

-UPD,对不起.

在这个问题中,我提出了两次调用控件的例子,nats收到消息后,从服务. 但实际上似乎是整个应用的问题. 我可以在NATS中添加额外的设置来避免这种情况吗? 我目前的配置很简单,就像官方文档中介绍的那样.

目前我使用的是简单的NatS配置:

  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.NATS,
    options: {
      servers: ['nats://nats:4222'],
    },
  });

发送的示例

async getBannersByCityId(cityId: string) {
 const params = { cityId };
 return this.nats.send('api-gateway.common.getBannersById', 
 params);
}

接收示例

@MessagePattern('api-gateway.common.getBannersById')
 getBannersByCityId(getBanners: GetBannerByCityIdDto) {
 console.log('banner list');
 return this.bannerService.getBannersByCityId(getBanners);
}

客户端设置:

ClientsModule.register([
  {
    name: 'COMMON_SERVICE',
    transport: Transport.NATS,
  },
]),

在那个配置中,我发现getBannersByCityId(getBanners: GetBannerByCityIdDto)emits 了两次

也许我需要配置附加标头https://docs.nats.io/using-nats/developer/develop_jetstream/model_deep_dive

推荐答案

也许@MessagePattern decorator的使用方式可能会导致重复处理消息:您需要确保在整个应用程序中@MessagePatterndecorator 中指定的模式是unique.重复的模式可能导致单个消息被multiple处理程序消耗,因此auth方法执行了两次.

For that, prefix all your message patterns with a unique namespace related to the service.
For example, if you have an AuthenticationService and a UserService, make sure all message patterns in the AuthenticationService start with auth, and those in the UserService start with user. That prevents any accidental overlap in pattern names.

示例:

// In AuthenticationService
@MessagePattern('auth.checkPhoneCode')
checkPhoneCode(phone_with_code: PhoneWithCodeDto) {
  // Implementation
}

// In UserService
@MessagePattern('user.checkPhoneCode')
checkUserPhoneCode(phone_with_code: PhoneWithCodeDto) {
  // Implementation
}

使模式中的操作名称尽可能具有描述性.不要使用像check这样的通用术语,而是使用描述操作及其操作实体的特定术语.

@MessagePattern('auth.verifyPhoneNumberAndCode')
verifyPhoneNumberAndCode(phone_with_code: PhoneWithCodeDto) {
  // Implementation
}

该模式比checkPhoneCode个更具体,减少了无意模式匹配的可能性.


But yes the message is unique.
For example api-gateway.authentication.checkPhoneCode - service api-gateway, module authentication, method checkPhoneCode. All separated by comma.
Only authentication service receives authentication messages. In my archihecture the module name of gateway is the service name in receiver.

这意味着方法被调用两次的问题并不是由非唯一的@MessagePattern标识符引起的,而是可能与配置NATS的方式或消息在其系统中的处理方式有关.查看NatS服务器日志(log)中与消息传递相关的任何异常或错误,可以深入了解可能导致重复的原因.

如果邮件被多次处理,则实施重复数据消除策略会有所帮助.这涉及到通过维护处理过的消息ID或唯一属性的缓存来判断消息之前是否处理过(我没有看到任何NATS的内置重复数据删除功能).

你提到了JetStream和其他标题.JetStream为NATS提供了增强的功能:判断Jetstream是否包含消息重复:在JetStream中,消费者可以配置特定的选项来控制消息的传递和确认方式.这包括可能有助于防止重复处理的设置,如邮件确认策略和传递try .

确保正确实现了消息确认行为.在人工确认消息的系统中,重要的是只有在成功处理之后才确认消息,以防止它被重新传递和再次处理.

此外,如果服务无意中多次订阅同一主题,这可能导致重复处理.判断代码是否存在多个订阅实例或意外重新订阅.

Node.js相关问答推荐

使用NodeJS在S3上传文件时的格式问题

即使DDB键不存在, node Lambda也不会失败,并返回NULL作为结果

从目录中获取所有文件,而不是NodeJS中的单个文件

如何在JavaScript中使用Mongoose将项推送到MongoDB中的重嵌套数组

使用ReadableStream.管道时NodeJS Crypto Hash不正确

请求正文未定义

MongoDB的方面查询的Postgres类似功能

在全局对象上声明的函数

发布请求不使用 Nodejs 更新 MongoDB 中的标头信息

找不到模块bcryptjs

Nodejs 从链接数组中获取数据并保存到 mongodb

Next.js 在我的电脑上没有构建错误,但它们在使用 Vercel 部署时发生

Zod 模式中的self 数组

更新文档数组中的文档 Mongoose

Socket IOFlutter 未连接

如何在 Node.js 中逐字节读取二进制文件

Node.js + Express:应用程序不会开始监听端口 80

向 Stripe 提交付款请求时出现没有此类令牌错误

代理后面的凉亭

Firestore:多个条件 where 子句