С помощью микросервисов nest js вы можете отправлять сообщения и получать результат, используя подход на основе запросов / ответов. Это реализуется комбинацией @MessagePattern
и client.send('my_pattern', myData)
. Для примера см. Вложенные документы: https://docs.nestjs.com/microservices/basics#request -response и https://docs.nestjs.com/microservices/basics#sending -messages .
Как мне получить результат в подходе, основанном на событиях ?
Предположим, у вас есть микросервис пользователя и микросервис аутентификации. Каждый раз, когда создается пользователь, вы хотите, чтобы также создавалась тема auth (сохраняя имя пользователя и ha sh пароля, чтобы пользователь мог войти в систему с запросом api к микросервису auth вместо пользовательского сервиса).
auth / auth.controller.ts
@EventPattern('EVT_USER_CREATED')
public async handleUserCreated(data: any): Promise<AuthSubject> {
if (!data.username || !data.password) {
throw new RpcException('Auth subject must supply username and password');
}
const newSubject: CreateAuthSubject = {
username: data.username,
password: data.password,
email: data.email ?? '',
};
const sub = await this.subjectService.create(subject);
return sub;
}
user / user.controller.ts
@Post('')
@ApiBody({ type: CreateUser })
@ApiCreatedResponse({ type: User })
public async create(@Body() user: CreateUser): Promise<User> {
const newUser = await this.userService.create(user);
this.userQueue
.emit<any, CreateUser>('EVT_USER_CREATED', user)
.subscribe((res) => {
console.log(res); // undefined
});
return newUser;
}
Чтобы убедиться, что в моей настройке нет ошибок, я изменил @EventPattern
на @MessagePattern
и this.userQueue.emit<...
на this.userQueue.send<...
. Это сработало, т.е. res был допустимым субъектом аутентификации с именем пользователя и паролем, как и ожидалось. Однако с подходом, основанным на событиях, описанном в этом вопросе, res
всегда undefined
(независимо от того, возвращает или нет контроллеры аутентификации handleUserCreated
).
В конечном итоге я бы хотелось бы добиться следующего: если другой микросервис должен обрабатывать события 'EVT_USER_CREATED', я просто добавляю метод @EventPattern('EVT_USER_CREATED') public async handleUserCreated
к его контроллеру. Наблюдаемый this.userQueue.emit<any, CreateUser>('EVT_USER_CREATED', user)
затем получит оба результата: Один раз для каждой микрослужбы, потребляющей событие, созданное пользователем.
Итак, предположим, я добавляю третью микросервис: микросервис клиента, который отвечает за сохранение платежной информации, историю заказов, эт c. Как и служба аутентификации, он подписывается на 'EVT_USER_CREATED'.
customer / customer.controller.ts
@EventPattern('EVT_USER_CREATED')
public async handleUserCreated(data: any): Promise<AuthSubject> {
const customer = await this.customerService.create(data);
return customer ;
}
Теперь, после вышеуказанной настройки, авторизация микросервисов и клиент будут альтернативный прием событий: если пользовательские микросервисы генерируют создание пользователя, только служба аутентификации отреагирует на это и создаст тему аутентификации от пользователя шляпы. Для этого пользователя не будет создано ни одного клиента. Для следующего пользователя, созданного в пользовательском микросервисе, будет создан только клиент, но не субъект авторизации. Третий созданный пользователь снова будет использоваться микросервисом auth, но не микросервисом клиента. И так далее.
-- auth microservice
/
user microservice --- message broker ---
\
-- customer microservice
Подводя итог: как мне получить архитектуру обмена сообщениями, показанную на диаграмме, так что мне нужен только один вызов emit(...)
в user.controller.ts
и, чтобы я обнаружил оба ответы в подписке на emit(...)
звонок?