NestJs - Mircoservices
nest는 마이크로 서비스 아키텍처를 지원합니다. 문서에서 다루었던 대부분의 개념들( injection, decorators, exception filters, pipes, guards ...)은 마이크로 서비스에 공통적으로 적용됩니다. Nest는 implementation 상세 정보를 추상화합니다. 덕분에 HTTP/websocket/Microservice에서 같은 component들이 실행될 수 있습니다. 이번 section에서는 Nest에서의 microservice에 대해서 다뤄볼 것입니다.
Nest에서 microsercie는 근본적으로 http와 다른 전송 수단을 사용합니다. Nest는 microservice instance 간 전송에 책임지는 built-in transport layer 도구인 "Transporters" 를 제공합니다. 대부분의 transporters는 request-response 그리고 event-based 메시지 스타일을 모두 지원합니다. Nest는 reqeust-response와 event-based messaging 각각의 표준 interface를 추상화하였다. 이것은 하나의 전송 layer에서 다른 layer로 application code에 영향을 주지 않고 쉽게 이동할 수 있게 만든다.
Installation
$ npm i --save @nestjs/microservices
getting started
To instantiate a microservice, use the createMicroservice() method of the NestFactory class:
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
},
);
await app.listen();
}
bootstrap();
참고
마이크로서비스는 TCP 전송레이어를 기본적으로 사용한다.
Patterns
microservice는 message와 event를 패턴으로 인식한다. pattern이란 전형적인 object나 string과 같은 평문의 값이다. Pattern은 자동적으로 serialize되고 네트워크로 message를 담은 data로 보내어진다. 이 방식으로는 message 전송자와 수신자는 어떤 요청이 어떤 handler에 의해 수신되었는지 알수 있다.
Request-response
request-response message 방식은 방대한 외부 서비스들 사이에서 메시지 교환을 해야할 때 필요하다. 이러한 패러다임에서 너는 서비스가 정말로 message를 전달 받았는지 확신(수동으로 직접 message에 ACK 프로토콜을 추가하지 않고)할 수 있어야한다. 하지만 request-response 패러다임은 항상 최고 선택은 아니다. 예를 들어, log-based streaming 전송 방식 (Kafka 또는 NATS streaming)는 다른 범위의 문제인 event messaging 패러다임을 해결하도록 최적화되어 있다.
reqeust-response 형식을 가능하게 하려면 nest는 두가지의 논리적 채널을 생성해야한다 - 하나는 들어오는 response가 기다리는 동안 다른 하나는 data를 전달 할 책임이 있다. NATS와 같은 transports에서는 dual-channel이 바로 처리된다. 그. 외에는 Nest 수동적으로 별도의 채널을 생성하여 보상한다. 이거에 대하여 overhaedrk qkftodgkf tn dlTdjtj request-response 메시지 스타일이 필요하지 않으면 event-based method 방식을 사용하는 것을 고려해야한다.
reqeust-response패러다임 기반의 message handler를 생성하기 위해선 @nestjs/microservices package의 @MessagePattern() 데코레이터를 사용하면 된다. 이 decorator는 application의 진입점인 controller에서만 사용되어야한다. 이것을 provider에서 사용하는것은 runtime에 무시됨으로 아무런 효과가 없다.
math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
@Controller()
export class MathController {
@MessagePattern({ cmd: 'sum' })
accumulate(data: number[]): number {
return (data || []).reduce((a, b) => a + b);
}
}
위의 코드에서 `accumulate()` message handler는 메시지가 `{cmd :"sum"}을 만족하는지 듣고 있는다. Message handler가 client가 보낸 data 중 하나의 변수를 전달받는다. 이 케이스에서는 data는 number[] 이고 이는 계산되어야한다.
Asynchronous responses
message handlers는 동기/비동기적으로 응답할 수있다. 그러므로 async method가 지원된다.
message handelr는 또한 결과 값이 stream이 완료되어야 발휘되는 경우 Observable을 반환할 수 있다.
Event-based
reqest-response 방식은 서비스간 메시지 교환방식에서 이상적이라면, 그런 경우에 덜 적합한 message style 방식이 event-based 방식이다. - response를 기다리지 않고 event를 publish 하고 싶을 경우, 이 경우에 너는 request-responsedml 두 채널을 유지하는overhead를 원치 않을 것이다.
시스템의 한 파트에서 어떤 일이 일어났을 때 다른 시스템에 알림을 보고 싶을 경우를 가정해보자. 이런 경우가 event-based message 방식을 사용하기 적절하다.
event-handler를 생성하기 위해서 우리는 @EventPattern() 데코레이터를 사용하면 된다.
@EventPattern('user_created')
async handleUserCreated(data: Record<string, unknown>) {
// business logic
}
참고
하나의 이벤트 패턴에 대하여 한번에 병렬적으로 실행되는 여러 event handler를 등록할 수 있다.
Decorators
더 복잡한 시나리오에서는, 들어오는 요청에 대한 더 많은 정보를 접근할 수 있다. 예를 들아, wildcard subscription의 NATS의 경우, 제공자가 메시지에 보낸 original subject를 받고 싶을 수있다. 마찬가지로, Kafka에서 message header에 접근을 하고 싶을 . 수있다. 이를 달성하기 위해서 너는 built-in dacorator를 다음과 같이 사용하면 된다.
Client
Nest appication client는 message나 event를 `ClientProxy class를 토대로 교환할 수있다. 이러한 class는 몇몇의 method를 제공 한다. (send() - request-response message 그리고 emit() -event-driven messaging) , tjsxorwjrdls transport property(default 는 TCP) 그리고