我正在使用 nest js 框架 和 nuts 消息代理。
首先我有用于路由的网关服务。
控制器
@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);
}
服务
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,等待坚果调用来执行操作。
控制器
@MessagePattern('api-gateway.authentication.checkPhoneCode')
checkPhoneCode(phone_with_code: PhoneWithCodeDto) {
console.log('controller check phone');
return this.authenticationService.checkPhoneCode(phone_with_code);
}
服务
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 方法执行两次。 我添加了控制台日志来调试以及我所看到的:
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 控制器会调用两次?
@MessagePattern
装饰器的使用方式可能会导致消息的重复处理:您需要确保 @MessagePattern
装饰器中指定的模式在整个应用程序中是唯一。重复的模式可能会导致单个消息被多个处理程序使用,因此auth
方法执行两次。
为此,请为所有消息模式添加与服务相关的唯一命名空间作为前缀。
例如,如果您有一个
AuthenticationService
和一个 UserService
,请确保 AuthenticationService
中的所有消息模式都以 auth
开头,并且 UserService
中的所有消息模式都以 user
开头。这可以防止模式名称意外重叠。
示例:
// 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
更具体,减少了无意模式匹配的可能性。