Message Queue
Ref.
What is a Message Queue?
Message Queue(메시지 큐)란 무엇이며 어떤 특징들이 있을까?
정의
메시지 큐는 서버리스 및 마이크로서비스 아키텍처에 사용되는 비동기 서비스 간 통신의 한 형태입니다.
메시지는 처리되어 삭제될 때까지 큐에 저장됩니다. 각 메시지는 단일 소비자에 의해 한 번만 처리됩니다.
종류
RabbitMQ, ActiveMQ, ZeroMQ, Kafka, [Amazon Simple Queue Service(SQS)](https://aws.amazon.com/sqs) … etc
MQ 종류
용어
Message : 한 시스템에서 또 다른 시스템으로 전달 되는게 예상되어지는 정보의 한 조각
- ex) meta data, file, Data payload 등
Queue : FIFO(First in First Out)형식의 자료구조
MessageBroker : Queue가 정의되어 있는 써드파티 소프트웨어. 응용프로그램들 사이에서 Message를 전달하는 미들웨어 역할을 하게 된다. 다양한 유형의 Message를 다른 Queue로 라우팅 하기 위한 규칙들도 제공한다. Message Broker는 Message를 제공하는 Producer와 소비하는 Consumer 사이에서 사용되는 API set가 있다. 즉 MessageQueue는 data struct로 Message를 보관하는 방법이고, MessageBroker는 Queue를 관리하는 별도의 구성 요소라고 볼 수 있다.
Producer : Message를 전달하는 개체
Consumer : Message를 전달받는 개체
Producer와 Consumer는 역할이 고정된게 아니기때문에 언제든 변경될 수 있다.
즉, 한번은 Producer 일 수 있고 또 한번은 Consumer일 수 도 있다.
생명주기(Life Cycle)
Producer는 Message를 Queue에 보낸다 Consumer는 현재 Message를 사용하거나 사용하지 못할 수도 있기 때문에 Queue는 Consumer가 사용할 수 있을 때까지 Message를 유지, 보관
Consumer는 Message를 처리할 준비가 되면 Queue에서 Message를 검색/사용함, Queue는 Message를 즉시 삭제하지 않으며 Consumer가 처리를 완료할 때까지 유지한다. Queue는 일시적으로 Message를 다른 사용자가 참조하지 못하도록 lock을(고립성) 건다.
Consumer가 Message를 처리하고나서 Queue에서 Message가 삭제된다.
Messaging Pattern
One-way Messaging

- point-to-point messaging 이라고도 알려져 있음.
Producer는 Consumer가 특정 시점에 Message를 검색하고 처리할 것을 기대하고 Queue에 Message를 보냄.
Consumer는 Queue에서 Message를 검색하고 처리하며여기서 Producer는 Consumer의 존재나 Message가 어떻게 전달되는지 알지 못하며 Consumer의 응답을 기다리지 않는다. 즉 Consumer의 응답에 의존적이지 않는다.
Request/Response Messaging

Producer는 Request Queue에 Message를 보낸 뒤 Reply Queue로부터 Consumer에 response가 나오기를 기대하며 Consumer는 Message를 처리한 다음에 Reply Queue에 response Message를 전달한다.
- 만약 response가 설정해 놓은 or 정상적인 time interval 안에 도착하지 않는다면
Producer는 두 가지를 선택할 수 있다.
Message를 다시 보낸다 (재전달)
- timeout 처리를 해버린다
Pub/Sub(Publish, Subscribe)

Producer는 Message를 Queue에 보내고 다수의 Consumer는 copy 된 Message를 load 할 수 있음.
Consumer들이 공통으로 알아야 하는 event들이 발생했을 때 사용되기가 좋다.
💡 consumer는 message에 대해서 경쟁하지 않는다.
오직 topic에만 관심이 있으며 message를 보낸 producer에 의존적이지 않는다.
producer 역시 어떤 consumer가 message를 소비했는지에 대해 관심이 없으며 의존적이지 않는다.
특징
At-least-once processing
- 그 어떤 상황에서도 MessageQueue 인프라 내에서 Message는 일단 Queue에 보내지면 손실되었는지 Consumer에게 전달되었는지 확인을 한다.
- Consumer가 message를 process 하는 동안 message에 lock을 걸고 해당 consumer가 message를 정상 처리하지 못하는 경우 lock을 풀어서 다른 consumer 가 message에 접근할 수 있게 한다.
- Message Queue에 보관되는 모든 메시지는 결국 Consumer에게 한 번은 전달된다는 일반적인 보장을 제공한다.
Exactly-once processing
- Producer가 message를 queue에 보내는 도중 어떠한 network 상의 문제로 다운이 되고 다른 Producer가 이전 process를 이어서 한 경우 Message Queue는 동일한 message가 두 번 보내질 가능 성이 있다.
- Message Id를 기반으로 전달된 Message Id를 내부적으로 유지 관리하며 새로운 Message가 도착할 시id를 확인하고 이미 전달된 경우 삭제하도록 처리할 수 있다.
- Consumer에게 정확하게 한 번만 Message가 전달되도록 할 수 있다.
상황에 따른 Message 순서
- 대부분의 Message Queue는 두 가지 유형을 제공한다.
- standard queue
- Message 순서가 보장되지 않을 수도 있지만 아주 높은 처리량을 제공한다
- 순서가 보장되지 않아도 되나 처리량에서 이점을 얻을 수 있는 상황들에 사용ex) 사용자 아바타, 이미지 크기 조정, 사용자 가입 정보 처리
- FIFO(First In First Out) queue
- Message는 엄격하게 전송된 순서로 전달된다, 대신 처리량이 제한적이다.
- 순서가 반드시 보장되어야 하는 상황들에 사용이 가능하다. ex) 재고 조정, 계좌 거래
Priority messaging

- Message Queue에서 Message가 추가되는 위치를 결정하기 위해 Message에 우선순위를 할당하여우선순위가 더 높은 Message를 먼저 처리되도록 할 수 있다.
Message Queue의 장점
Decoupling
- Producer와 Consumer가 서로에게 의존적이지 않게 되므로 유연한 시스템 설계가 가능하다.
- Producer와 Consumer는 결국 Role 즉 역할이며 해당 역할을 할 수 있는 앱 내 컴포넌트, msa 내에서 micro service 간 의존도가 떨어지게 된다.
확장이 가능하다
![업로드중..]()
- 여러 Consumer에게 message process를 분산하여 (로드 밸런싱) 애플리케이션이 확장되고 처리량이 올라가더라도 부담을 줄일 수 있다.
- Producer가 다수의 Cosumer에게 처리되는 많은 양의 Message를 Queue에 보내게 된다고 해도 Queue의 길이에 따라서 Message를 처리하는 Consumer를 추가해서 Scale Out을 통해 처리량을 올릴 수 있다.
- MessageQueue에 대기하는 Message들이 제거되어 짐에 따라 Consumer의 수는 다시 조절할 수 있다.
플랫폼 통합
![업로드중..]()
- 서로 다른 플랫폼에서 실행되는 구성요소를 통합 가능하다.
Resilence
- Message Queue는 application 구성 요소 간 Message를 안정적으로 교환할 수 있다.
- Consumer가 실패하더라도 응답에 의존적이지 않기 때문에 Queue는 Message를 다른 Consumer에게 전달한다
🌟DLQ(Dead Letter Queue)
- Consumer가 죽더라도 Message는 Queue에 남아 있게 되며 Consumer Service가 다시 시작될 때 추가 설정이나 작업을 수행하지 않고도 Message 처리가 가능하다
- DLQ는 전달되거나 처리될 수 없는 메시지를 보관하는 MessageQueue에 내장된 특수 Queue이다.
- 모든 Consumer는 Message를 DLQ에 넣을 수 있다.
- DLQ는 대부분의 경우 Queue에 검색될 때까지 Message를 유지한다
Message expiration
- Queue가 Message를 보관하고 있을 시간제한을 둘 수 있다.
- 설정한 시간 내에 Consumer가 Message를 처리하지 않는다면 해당 Message는 DLQ에 넣게 된다
- Consumer가 처리하지 않은 Message들이 Queue에 무제한으로 쌓이는 것을 방지할 수 있다.
주의사항
Poison Message
- 형식이 잘못되었거나 예상하지 않은 정보가 포함되어 있어 처리할 수 없는 message이다
- poison message를 감지하고 빠르게 제거하는 것이 중요하다. 일반적으로는 DLQ에 들어가게 된다
- Consumer에서 처리되지 못하고 실패 → Queue로 복귀 → 또 다른 Consumer에서 처리하려고 해봄 → 처리되지 못하고 또다시 Queue로 복귀 → 무한반복 → CPU 사용량 빠르게 증가.!!