- 큐를 구독하는 컴포넌트를 메시지 핸들러(message handler)라고 한다.
- 대개 메시지의 종류(레디스의 채널, NATS의 서브젝트에 해당)마다 이를 처리하는 메시지 핸들러가 하나씩 필요하다.
- to-do 애플리케이션에는 새 할 일 이벤트 메시지를 처리해 데이터를 데이터베이스에 추가하는 역할을 해 줄 메시지 핸들러가 필요하다.
완성된 애플리케이션의 아키텍처
- 이 아키텍처는 메시지 큐가 급증하는 부하의 버퍼와도 같은 역할을 하기 때문에 스케일링이 용이하다.
- 웹 컨테이너가 수백 개 있더라도 메시지 핸들러 컨테이너는 열 개면 층분하다.
- 메시지 핸들러는 그룹으로 묶어 두고 돌아가면서 큐에 들어온 메시지를 처리한다.
- 메시지는 한 번에 하나씩 처리하므로 사용자가 아무리 많더라도 동시에 데이터 추가를 위해 들어오는 SQL 연결은 열 개로 제한된다.
- 메시지 핸들러 열 개 이상의 부하가 걸린다면, 메시지는 큐에 저장된 상태로 자신의 차례를 기다릴 것이다.
- 애플리케이션은 그대로 잘 동작하며 데이터도 잠시 후면 저장이 완료된다.
실습 to-do 애플리케이션의 메시지 핸들러는 미리 이미지로 빌드해 도거 허브에서 배포 중이다. 이 이미지로 컨테이너를 실행해 애플리케이션의 비동기 메시징이 완전히 동작하는지 확인하라.
# 메시지 핸들러 컨테이너 시작
➜ docker-compose up -d save-handler
# 컨테이너 로그 확인
➜ docker logs todo-list-save-handler-1
Connecting to message queue url: nats://message-queue:4222
Listening on subject: events.todo.newitem, queue: save-handler
# 웹 브라우저에서 http://localhost:8080 에 접근해 새로운 할 일 추가
# 이벤트가 잘 처리되는지 확인
➜ docker logs todo-list-save-handler-1
Received message, subject: events.todo.newitem
Saving item, added: 08/20/2023 04:48:30; event ID: ef26c7f1-fe07-483f-be9f-1c525994ab4c
Item saved; ID: 1; event ID: ef26c7f1-fe07-483f-be9f-1c525994ab4c
- 메시지 핸들러는 특정 목적에 특화된 작은 컴포넌트로, 주 애플리케이션이나 다른 컴포넌트와 별도로 업데이트하거나 스케일링할 수 있다.
- 이번 실습에서 큐를 사용해 수평 확장문제를 해결했으므로 이제 메시지 핸들러의 수를 늘려 SQL 커넥션 풀의 수를 늘리지 않고도 증가하는 부하에 대응할 수 있다.
실습 메시지 핸들러는 내부 컴포넌트다. 다른 포트를 주시하지 않으므로 단일 컴퓨터에서 여러 컨테이너를 실행해도 문제가 없다. NATS는 같은 서브젝트를 처리하는 여러 핸들러 간의 로드 밸런싱을 지원한다.
001) # 핸들러의 인스턴스 수를 늘림
002) ➜ docker-compose up -d --scale save-handler=3
003)
004) # 새로 늘린 핸들러가 메시지를 구독하는지 확인
005) ➜ docker logs todo-list-save-handler-2
006) Connecting to message queue url: nats://message-queue:4222
007) Listening on subject: events.todo.newitem, queue: save-handler
008)
009) # 웹 브라우저에서 http://localhost:8080 에 접근해 새로운 할 일 추가
010)
011) # 어느 메시지 핸들러가 메시지를 처리했는지 확인
012) ➜ docker-compose logs --tail=1 save-handler
013) todo-list-save-handler-1 | at ToDoList.SaveHandler.Program.Main(String[] args) in /src/save-handler/Program.cs:line 11
014) todo-list-save-handler-2 | Item saved; ID: 2; event ID: 65a640d5-3ad5-4b12-8617-0a336b389a28
015) todo-list-save-handler-3 | Listening on subject: events.todo.newitem, queue: save-handler
-
002: NATS 메시지 큐는 큐에 접속한 모든 메시지 핸들러에 고르게 메시지를 배분한다.
-
NATS는 라운드 로빈 방식의 로드 밸런싱을 통해 서브스크라이버에 메시지를 분배할 수 있다.
- 우리가 한 일은 메시지 핸들러의 수를 늘린 것뿐이다.
- 같은 이벤트를 통해 동작하는 다른 기능이 있다면, 해당 서브젝트를 구독하는 또 다른 메시지 핸들러를 실행하면 된다.
- 이런 방법으로 코드 변경 없이 새로운 기능을 추가할 수도 있다.