Dapr(분산형 애플리케이션 런타임) 소개
Dapr은 분산형, 이벤트 주도형 런타임으로 다양한 언어와 프레임워크에서 탄 강성 및 무상태, 유상태 애플리케이션을 쉽게 개발할 수 있도록 지원합니다. 클라우드나 윌드-edge 환경에서도 실행할 수 있습니다.
Dapr 공식 웹사이트: https://dapr.io/
실전: Dapr의 Redis 퍼블리시-서브스크라이브 애플리케이션 구현
1. 프로젝트 생성
프로젝트 루트 폴더를 만듭니다.
mkdir dapr-nestjs-redis-pub-sub
2. Dapr Placement 서비스 구현
Docker Compose를 사용하여 서비스를 실행합니다. 프로젝트 루트 폴더에 docker-compose.yml 파일을 생성합니다.
cd dapr-nestjs-redis-pub-sub
touch docker-compose.yml
docker-compose.yml에 다음 코드를 추가합니다.
version: "3.5"
services:
dapr-placement:
image: "daprio/dapr"
command: ["./placement", "-port", "50006"]
Dapr Placement는 Dapr 액터 간의 모든 통신을 관리합니다.
3. Redis 퍼블리시 서비스 구현
docker-compose.yml 파일에 Redis 퍼블리시 서비스를 추가합니다.
redis-publisher:
image: redis
restart: always
depends_on:
- dapr-placement
4. Dapr 퍼블리시-서브스크라이브 컴포넌트 설정
dapr/components 폴더를 생성하고 redis-pubsub.yaml 파일을 만듭니다.
mkdir -p dapr/components
cd dapr/components
touch redis-pubsub.yaml
redis-pubsub.yaml에 다음 내용을 입력합니다.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: redis-pubsub
namespace: default
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: redis-publisher:6379
- name: redisPassword
value: ""
5. Redis Dapr 사이드카 구현
docker-compose.yml 파일에 Redis Dapr 사이드카 서비스를 추가합니다.
redis-dapr-sidecar:
image: "daprio/daprd:edge"
command: [
"./daprd",
"-app-id",
"redis-publisher",
"-app-port",
"6379",
"-dapr-http-port",
"5000",
"-components-path",
"/components",
"-placement-host-address",
"dapr-placement:50006"
]
volumes:
- "./dapr/components/:/components"
depends_on:
- redis-publisher
network_mode: "service:redis-publisher"
6. NestJS 서버 구현
NestJS를 사용하여 Redis 서브스크라이브 서비스를 만듭니다.
cd dapr-nestjs-redis-pub-sub
npm i -g @nestjs/cli
nest new nest-subscriber
nest-subscriber/src/app.controller.ts 파일을 수정합니다.
import { Controller, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Post('/redis-publisher')
async postRedisPub(@Body() reqBody) {
console.log(`Redis가 발행한 ${JSON.stringify(reqBody)} `);
return `NestJS 서브스크라이브자가 받은 ${reqBody} 발행`;
}
}
7. NestJS 서버용 Dockerfile 작성
nest-subscriber 폴더에 Dockerfile을 생성합니다.
cd nest-subscriber
touch Dockerfile
Dockerfile에 다음 코드를 입력합니다.
FROM node:16.13.0-alpine
WORKDIR "/app"
COPY ./nest-subscriber/package.json ./
RUN yarn install
COPY ./nest-subscriber .
RUN yarn run build
EXPOSE 3000
CMD ["yarn","start:prod"]
Docker 이미지를 빌드합니다.
docker build -f ./nest-subscriber/Dockerfile -t nest-subscriber:latest . --no-cache
8. NestJS 서브스크라이브 서비스 추가
docker-compose.yml 파일에 NestJS 서비스를 추가합니다.
nest-subscriber:
image: "nest-subscriber:latest"
depends_on:
- redis-publisher
- dapr-placement
restart: always
9. Dapr 서브스크라이브 설정
dapr/subscriptions 폴더를 생성하고 redis-subscription.yaml 파일을 만듭니다.
mkdir -p dapr/subscriptions
cd dapr/subscriptions
touch redis-subscription.yaml
redis-subscription.yaml에 다음 내용을 입력합니다.
apiVersion: dapr.io/v1alpha1
kind: Subscription
metadata:
name: nest-redis-sub
spec:
topic: nest-redis-pub-topic
route: /redis-publisher
pubsubname: redis-pubsub
scopes:
- nest-subscriber
10. NestJS 서버용 Dapr 사이드카 구현
docker-compose.yml 파일에 NestJS 서버용 Dapr 사이드카 서비스를 추가합니다.
nest-subscriber-dapr-sidecar:
image: "daprio/daprd:edge"
command: [
"./daprd",
"-app-id",
"nest-subscriber",
"-app-port",
"3000",
"-components-path",
"/components",
"-placement-host-address",
"dapr-placement:50006",
]
volumes:
- "./dapr/components/:/components"
depends_on:
- nest-subscriber
network_mode: "service:nest-subscriber"
11. 테스트
로컬 머신에서 퍼블리시 테스트를 수행합니다.
curl --location --request POST 'http://localhost:5001/v1.0/publish/redis-pubsub/nest-redis-pub-topic' \
--header 'Content-Type: application/json' \
--data-raw '{
"hello": "world"
}'
12. CloudEvents 처리를 위한 NestJS 설정
body-parser 패키지를 설치하고 main.ts 파일을 수정합니다.
cd nest-subscriber
yarn add body-parser
main.ts 파일을 수정합니다.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as bodyParser from 'body-parser';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(bodyParser.json({ type: 'application/cloudevents+json' }));
app.use(bodyParser.json());
await app.listen(3000);
}
bootstrap();
13. 완전한 docker-compose.yml
version: "3.5"
services:
dapr-placement:
image: "daprio/dapr"
command: ["./placement", "-port", "50006"]
redis-publisher:
image: redis
depends_on:
- dapr-placement
restart: always
ports:
- 5001:5000
redis-dapr-sidecar:
image: "daprio/daprd:edge"
command: [
"./daprd",
"-app-id",
"redis-publisher",
"-app-port",
"6379",
"-dapr-http-port",
"5000",
"-components-path",
"/components",
"-placement-host-address",
"dapr-placement:50006"
]
volumes:
- "./dapr/components/:/components"
depends_on:
- redis-publisher
network_mode: "service:redis-publisher"
nest-subscriber:
image: "nest-subscriber:latest"
depends_on:
- redis-publisher
- dapr-placement
restart: always
nest-subscriber-dapr-sidecar:
image: "daprio/daprd:edge"
command: [
"./daprd",
"-app-id",
"nest-subscriber",
"-app-port",
"3000",
"-components-path",
"/components",
"-placement-host-address",
"dapr-placement:50006",
]
volumes:
- "./dapr/components/:/components"
depends_on:
- nest-subscriber
network_mode: "service:nest-subscriber"
14. 소스 코드
https://github.com/Hacker-Linner/dapr-nestjs-redis-pub-sub.git
더 많은 정보: Dapr을 위한 NestJS SDK 통합 방법