RabbitMQ란?
RabbitMQ란 함수형 언어인 erlang
을 기반으로 AMQP를 구현한 메시지 큐(Message Queue)/메시지 브로커(Message Broker)로, 메시지를 송신자(producers)와 수신자(consumers) 사이에서 중개하는 역할을 한다.
💡 AMQP(Advanced Message Queing Protocol)란?
메시지 지향 미들웨어를 위한 개방형 표준 프로토콜이다. 이 프로토콜은 애플리케이션 간의 메시지 전송을 위한 규칙과 메커니즘(publisher/exchange/queue/consumer)을 정의하여, 서로 다른 시스템이나 애플리케이션이 효율적으로 통신할 수 있도록 지원한다.
그렇다면 RabbitMQ와 같은 Messaging Queue를 사용하는 이유가 뭘까?
1) 요청을 많은 사용자에게 전달하는 경우
- 하나의 메시지를 여러 수신자에게 효율적으로 전달할 수 있다.
- Publish/Subscribe 패턴을 사용하여 구독자들에게 자동으로 메시지가 전달할 수 있다.
2) 요청에 대한 처리시간이 긴 경우
- 시간이 오래 걸리는 작업을 비동기로 처리할 수 있다.
- 사용자는 즉시 응답을 받고, 작업은 백그라운드에서 처리된다.
3) 많은 작업이 요청되어 처리를 해야하는 경우
- 작업들을 큐에 저장하고 순차적으로 처리할 수 있다.
- 여러 워커(Consumer)가 분산하여 작업을 처리할 수 있다.
- 시스템 부하를 조절하고 안정적인 처리가 가능하다.
예시로 배치(batch)와 같이 요청에 대한 응답을 즉각적으로 기다리지 않아도 되는 작업들의 경우 메시징 큐를 활용할 수 있다. 매일 혹은 영업일에 한번 씩 돌아가는 배치의 경우, 실시간으로 처리될 필요가 없다. 따라서 메시징 큐를 활용하여, 저장해두었다가 순차적으로 처리할 수 있도록 한다. 이외에도 회원가입 인사 이메일, 가입 환영 쿠폰 등에도 활용할 수 있다.
Messaging Queue(Message Broker)의 필요성에 대해서는 다음 포스팅에서 더 자세히 다뤄볼 예정이다.
Rabbit MQ 동작원리
RabbitMQ는 AMQP를 구현한 메시지 브로커로서, 프로토콜만 맞으면 다른 AMQP를 사용한 Application 끼리 통신이 가능하다. 기본적으로 아래 그림과 같이 동작한다.
- Exchange가 Producer로 부터 메시지를 받고 Queue에 전달한다.
- Queue는 Consumer에게 메시지를 전달한다.
RabbitMQ(브로커)로 전달된 메시지는 Queue로 전달되지 않고 Exchange를 통해 들어오게 된다. 그리고 정의된 Exchange 방법과 Binding 규칙을 통해 알맞은 queue로 전달된다. RabbitMQ는 1개 이상의 Queue들이 존재하고, 해당 queue들을 통해 각긱 다른 consumer로 데이터가 전달되게 된다.
요소 | 설명 |
---|---|
Producer | 요청을 보내는 주체 (메시지를 exchange에 push) |
Consumer | produceer로부터 메시지를 받아 처리 |
exchange | producer로부터 전달받은 메시지를 어떤 queue로 보낼지 결정하는 장소(4가지 type) |
bindings | exchange와 queue의 관계 |
queue | consumer가 메시지를 consume하기 전까지 보관하는 장소 (RabbitMQ 서버가 설치되는 호스트의 메모리 및 디스크 용량에 한정된다) |
Exchange
AMQP 브로커는 다음과 같이 4가지 Exchange Type을 제공한다.
타입 | 설명 |
---|---|
Direct | 라우팅 키가 정확히 일치하는 Queue에 메시지 전송 |
Topic | [key:value]로 이루어진 Header 값을 기준으로 일치하는 queue에 메시지 전송 |
Headers | 해당 Exchange에 등록된 모든 Queue에 메시지 전송 |
Fanout | 라우팅 키 패턴이 일치하는 Queue에 메시지 전송 |
Direct Exchange
라우팅 키를 이용하여 메시지를 전달할 때, 라우팅 키가 정확히 일치하는 Queue에만 전송한다. 하나의 Queue에 여러 라우팅 키를 지정할 수 있고, 여러 Queue에 같은 라우팅 키를 지정할 수도 있다.
작동 원리는 다음과 같다.
- queue는 라우팅 키 K를 사용하여 exchange에 binding된다.
- 라우팅 키 R을 갖는 새 메시지가 직접 exchange에 도착하면, exchange는
K=R
인 경우 해당 메시지를 대기열로 라우팅한다. - 여러 대기열이 동일한 라우팅 키
K
를 사용하여 Direct Exchange에 binding된 경우,K=R
인 모든 대기열로 메시지를 라우팅한다.
Topic Exchange
라우팅 키의 패턴을 이용해 메시지를 라우팅한다. 여러 Consumer에서 메시지 형태에 따라 선택적으로 수신해야하는 경우 등등 다양한 패턴 구현에 활용될 수 있다. 아래 그림의 경우 라우팅 키가 정확히 일치하지 않아 binding 되지 않은 경우이다.
아래 그림의 경우에는 animal.rabbit
이 animal.*
와 #
모두에 일치하기 때문에 모든 Queue에 전송되는 경우이다. (#은 0개 이상의 단어를 대체)
Headers Exchange
Topic과 유사한 방법이지만 라우팅을 위해 header를 사용한다는 점에서 차이가 있다. 라우팅 키보다 메시지 헤더로 더 쉽게 표현디는 여러 속성에 대한 라우팅을 위해 설계되었다. producer에서 정의된 Header의 key-value 쌍과 consumer에서 정의된 argument의 key-value 쌍이 일치하면 binding 된다.
binding key 만을 사용하는 것보다 더 다양한 속성을 사용할 수 있고, 이 타입을 사용하면 binding key는 무시되고, 바인딩 시 지정된 값과 헤더 값이 같은 경우에만 일치하는 것으로 간주된다. 이때, x-match
의 값에 따라 다르게 동작한다.
key | value | 설명 |
---|---|---|
x-match | all | header의 모든 key-value 쌍 값과 argument의 모든 key-value쌍 값이 일치할 때 binding (모두 일치해야 함) |
x-match | any | argument의 key-value 쌍 값 중 하나라도 header의 key-value 쌍 값과 일치할 때 binding (1개만 일치하면 ok) |
Fanout
Exchange에 등록된 모든 Queue에 메시지를 전송한다. Binding된 모든 Queue로 라우팅하고, 라우팅 키는 무시된다. N개의 Queue가 Fanout Exchange에 Binding된 경우 새 메시지가 해당 Exchange에 게시되면, 메시지 사본이 모든 N개의 Queue에 전달된다.
Reference