이는 처리 시간이 긴 요청을 분리하거나, 하나의 요청을 여러 클라이언트에게 비동기적으로 전달해야할 때 유용하게 사용됩니다.
저 또한 진행하고 있는 프로젝트에서 공간예약 시 알림을 발생하는데 예약행위와 알림발생을 분리하고 싶어 메세지큐를 도입하였습니다.
클라이언트와 메시지 지향 미들웨어(MOM)사이에서 데이터를 주고받기 위한 메시징 프로토콜입니다.
Exchange는 Producer에게 1차적으로 메시지를 받고 이를 규칙에 맞게 Queue에 분배하는 집배원같은 역할을 합니다.
아래 화면에서 Exchange에 대한 설정이 가능하며 크게 4가지 Type을 갖습니다. 해당 부분은 아래에서 더 설명하겠습니다.
direct
, fanout
, headers
, topic
)alternate-exchange
: 대체 Exchange 설정. 만약 바인딩된 큐 또는 바인딩 조건이 일치하는 큐가 없다면 대체 Exchange로 메시지를 전달합니다.Queue는 Exchange로 부터 메시지를 전달받으며 Consumer가 처리하기 전까지 메시지를 저장합니다.
아래 화면에서 Queue에 대한 설정을 할 수 있으며, Arguments를 통해 다양한 기능을 줄 수 있습니다.
Classic
, Quorum
, Stream
)x-expires
: 설정된 시간동안 큐가 사용되지 않으면 자동으로 삭제됩니다.(ms단위)x-message-ttl
: 설정된 시간동안 publish된 메시지가 큐에 살아있으면 자동으로 삭제됩니다.(ms단위)x-overflow
: 큐의 max-length에 도달했을 때 동작을 결정합니다. (유효값: drop-head
, reject-publish
, reject-publish-dlx
)x-single-active-consumer
: 설정된 경우, 한번에 한명의 소비자만 큐를 소비합니다. 만약 해당 소비자가 취소되거나 종료되면 등록된 다른 소비자가 장애조치(fail over)를 할 수 있습니다.x-dead-letter-exchange
: 메시지가 거부되거나 만료된 경우, 해당 메시지가 republish될 Exchange를 설정합니다.x-dead-letter-routing-key
: 메시지가 거부되거나 만료된 경우, DLX로 보내질 때 사용할 라우팅 키입니다. 만약 설정되지 않은 경우 원래 라우팅키가 사용됩니다.x-max-length
: 큐에 저장할 수 있는 메시지 최대 개수입니다.x-max-length-bytes
: 큐에 저장할 수 있는 메시지 최대 크기입니다. (byte단위)Direct는 특정 큐에 메시지를 보낼 수 있습니다. 메시지에 라우팅 키를 작성하여 보내면, 바인딩된 라우팅키와 일치하는 큐로 메시지를 보내줍니다. 주의할 점은 어떤 라우팅키와도 일치하지 않으면 메시지는 폐기됩니다.
블로깅 시스템에 사진을 업로드할 경우 png, jpg 파일은 바로 썸네일을 생성하고 svg 파일은 변환작업이 필요하다는 상황을 가정해봅시다. 위 상황엔 확장자를 라우팅키로 Direct Exchange를 두는것이 적절합니다.
설정할 Exchange의 Bindings 탭에 들어가 Queue이름과 매칭할 라우팅키를 입력해주면됩니다.
Direct와 유사하게 특정 큐에 메시지를 보낼 수 있습니다. 메시지에 라우팅 키를 작성하여 보내면, 바인딩된 라우팅키 패턴과 일치하는 모든 큐에 메시지를 보내줍니다.
라우팅키 패턴에는 2가지 규칙이 있습니다.
Direct 예시에 몇 가지 요구사항을 더해봅시다. 모바일 앱에서 온 사진은 이미지 필터 적용이 필요하며, 큰 크기의 svg는 로깅이 필요합니다. 위와 같은 경우 Topic Exchange를 두고 아래와 같이 라우팅키 패턴을 작성해 주면 요구사항을 만족할 수 있습니다.
만약 mobile.large.svg
라우팅키를 가진 메시지가 들어온다면? vector, mobile, log 큐 모두에게 전달될 것입니다.
Fanout은 Exchange에 바인딩된 모든 큐에 메시지를 보냅니다.
모든 큐에 동일하게 메시지를 전달하기 때문에 라우팅 키는 무시됩니다. 만약 N개의 큐가 연결되어있다면 메시지는 N개 복사되어 각 큐로 전달됩니다.
HR시스템에 신규입사자 또는 퇴직자가 발생할 경우 회계/마케팅시스템 모두 해당 데이터를 처리해야한다는 상황을 가정해봅시다. 위 상황엔 두 시스템 모두 메시지를 받아야하므로 Fanout Exchange를 두는 것이 적절합니다.
Header 방식을 사용하면 메시지의 라우팅 키는 무시되고, 대신 헤더에 정의된 기준을 사용하여 헤더 값과 Exchange에 바인딩된 규칙을 비교합니다.
Header Exchange는 기본적으로 x-match
Argument를 사용하며, 기본 값은 all
입니다. 이는 지정된 모든 조건을 만족해야 메시지가 라우팅 될 수 있다는 것을 의미하며 AND조건으로 볼 수 있습니다.
다른값으로는 any
가 있으며, 지정된 조건을 하나라도 만족하면 메시지가 라우팅 될 수 있습니다. 즉 OR조건으로 볼 수 있습니다.
만약 위와 같이 바인딩 규칙을 만들게되면 아래와 같이 전달됩니다.
메세징 시스템엔 RabbitMQ말고도 대표적으로 Kafka가 존재합니다. 이 둘의 차이에 대해서도 살펴보고 적용하고자 하는 시스템에 적합한 기술이 무엇인지 생각해봅시다.
- Topic: 메시지가 분류되어 발행되는 카테고리로, 소비자(Consumer)가 구독할 수 있는 논리적인 채널입니다.
- Partition: 토픽 내에서 메시지를 세분화하여 저장하는 물리적 단위로, 메시지의 순서와 분산 처리를 가능하게 합니다.
RabbitMQ는 3.11부터는 Stream과 단일 소비자 활성 기능이 추가되어 Kafka동작과 비슷하도록 개선하였습니다.
시스템의 성격에 따라 적합한 메시징 시스템이 다릅니다.
빠른 거래(fast transaction)가 필요한 회사들은 Kafka를 핵심 메시징 시스템으로 선호하는 반면, 거래량이 적은(lower transaction) 회사들은 RabbitMQ를 선택하는 경향이 있습니다.
이는 RabbitMQ가 매니징이 다소 쉽기때문입니다. 설치하면 대부분 메시지 브로커로서 문제없이 잘 작동합니다. 반면 Kafka는 클러스터 복제, Producer 및 Consumer 구성 등 다양한 관리작업을 필요로 합니다.
하지만 Kafka는 확장성이 뛰어나고 대규모 데이터 스트리밍 처리에 주로 사용됩니다. 예를들어 은행은 atm, 신용카드 등 다양한 채널에서 발생하는 거래를 Kafka로 스트리밍하여 사기 가능성을 분석할 수 있습니다.
둘다 널리 사용되는 기술이지만, 상대적으로 RabbitMQ가 러닝커브가 조금 더 낮고 적용하고자하는 기능이 대규모 데이터 스트리밍 처리를 필요로하지 않기 때문에 RabbitMQ가 프로젝트에 적합하다고 판단하여 선택하였습니다. 하지만 추후 RabbitMQ만으로는 트래픽 감당이 힘들 경우 Kafka로 변경이 필요할 수 있을 거같다는 생각이듭니다.
참고: