RabbitMQ는 AMQP 1.0를 만족하는 오픈소스 메세지 큐 서비스이다.
메세지 큐 또는 이벤트 큐 진영에서 가장 유명한 Kafka에 비해서 비교적 쉽고 간단한 구조를 갖고 있어서 라이트한 구조의 시스템에서는, RabbitMQ를 사용하는 것도 좋은 선택일 수 있다.
홈페이지 피셜로 RabbitMQ는 멱등성, 유연함, 메세지 전송의 신뢰를 보장하는 서비스라고 한다.
Event-Driven Architecture 대부분이 그렇겠지만 프로듀서, 컨슈머와 메세지 브로커로 전체적인 구조를 설명할 수 있다. 그 중에서 메세지 브로커의 역할을 RabbitMQ가 수행하게 된다.
RabbitMQ는 N개의 Exchange를 갖고, 하나의 Exchange는 여러 개의 Queue를 가질 수 있다.
하나의 Exchange와 하나의 Queue의 연결을 "바인딩"이라고 부른다.
클라이언트(프로듀서, 컨슈머)의 입장에서는 Exchange와 Connection을 맺어서 특정 Channel(Queue)에 데이터를 보내거나 구독하게 된다.
Exchange는 프로듀서로부터 메세지를 받아서, Queue에 저장하는 역할을 한다.
Exchange는 Queue로 메세지를 라우팅하는 방식에 따라서 4개의 유형이 존재하는데, 하나 하나 알아보자.
Direct exchange는 Routing key 값과 Routing key를 갖고 있는 Binding을 찾고 해당 바인딩이 가리키는 Queue에 데이터를 할당한다. 이런 특징으로 인해서 간단한 기능에 적합한 옵션이다.
fanout
옵션은 Routing key 값과 무관하게, Exchange에 바인딩되어 있는 모든 Queue에 데이터를 전달하는 옵션이다.
Routing key값의 패턴에 일치하는 이름을 갖고 있는 Queue에 데이터를 라우팅하는 옵션이다.
예를 들어서, animal.tiger
, animal.lion
이라는 Queue와 바인딩되어 있는 Topic exchange가 있다고 가정해보자.
이 때, Routing key 값을 animal.tiger
라고 메세지를 보내면 animal.tiger
큐에만 데이터가 전해지고, animal.*
라는 Routing key 값으로 메세지를 보내면, animal.
이라는 문자열로 시작하는 모든 큐에 데이터가 전달되는 것이다.
메세지의 Routing key 값은 무시되고, Headers에 정의된 Key:Value
값을 통해서 메세지가 라우팅된다.
Queue의 Arguments에 동일한 Key:Value
가 존재하는 경우에만 라우팅한다.
Exchange와 Queue의 연결을 "바인딩"이라고 부른다고 위에서 이야기했는데, 이 바인딩에도 여러 설정을 추가할 수 있다.
그 중에 하나가 x-match
라는 값이다. 바인딩의 Arguments에 x-match
라는 키 값으로 all
또는 any
라는 값을 지정할 수 있다.
all
: 메세지 헤더의 모든 Key:Value
와 바인딩 Arguments의 모든 Key:Value
가 일치해야 메세지를 라우팅하는 옵션any
: 메세지 헤더 중 하나의 Key:Value
와 바인딩 Arguments의 하나의 Key:Value
만 일치해도 메세지를 라우팅하는 옵션Exchange에는 Type 말고도 몇가지 옵션이 더 존재한다. 하나 하나 살펴보자.
Durable
, Transient
라는 값이 존재하고, Durable
은 재시작해도 Exchange가 없어지지 않고, Transient
는 브로커가 재시작하면 Exchange가 삭제되는 옵션이다.yes
로 하면, 바인딩되어 있던 큐들이 모두 언바인딩되면, Exchange가 삭제된다.yes
로 하면, 클라이언트가 직접 Exchange에 연결할 순 없게 된다.큐는 다른 메세지 브로커 서비스들의 큐와 마찬가지로 FIFO구조를 갖고 있다. 데이터 또는 메세지를 쌓는 역할을 한다.
RabbitMQ는 Erlang으로 만들어져있는데, 하나의 큐는 하나의 Erlang 프로세스라고 생각하면 된다.
몇가지 옵션을 통해서 큐를 제어할 수 있는데, 이 옵션들을 알아보자.
Queue는 4개의 유형으로 생성할 수 있다. 하나 하나 알아보자.
말 그래도 큐의 이름인데, 이름 이상의 역할을 하므로 잘 지어야한다. xxx.yyy.zzz
와 같은 형태로 이름을 짓는 것이 권장된다.
amq.
로 시작하는 큐들은 RabbitMQ가 내부적으로 사용하는 큐이다.
Exchange와 마찬가지로, 브로커가 재시작할 때 해당 큐를 생존시킬지를 결정하는 옵션이다.
하나의 Queue는 여러 개의 컨슈머에 의해서 소비될 수 있는데, 이렇게 메세지를 소비하는 것에도 중요한 개념들이 있다. 한번 알아보자!
Ack 모드는 컨슈머가 메세지를 소비하면서 해당 메세지를 어떤 상태로 만들 것인지에 대한 옵션이다.
이 옵션으로 큐에 Ack
또는 Negative Ack
를 보낼지를 결정하고, 소비한 메세지를 큐에 다시 추가(Requeue)할 것인지를 결정할 수 있다.
Ack mode는 4가지 종류가 있다.
위 설명만으로는 어떤 경우에 각 Mode를 사용하는 것인지 알기 어려우니, 실제적인 에시로 이야기해보겠다.
먼저, Ack
는 메세지 처리가 잘 이루어졌을 때 사용하면 되고, Nack
과 Reject
는 메세지 처리 중, 뭔가 에러가 발생한 경우에 사용하면 된다. Nack
은 복수의 메세지를 한번에 처리할 수 있지만, Reject
는 단 건의 메세지만 처리할 수 있다.
Automatic ack
과 Reject requeue false
모두 큐에서 제거하는 건데 뭐가 다르냐고 생각될 수 있는데, Reject requeue false
는 메세지 자체에 이슈가 있어서, 다른 컨슈머가 처리하지 못하도록 큐에서 아예 제거하는 의미를 갖고 있다.
한번에 몇 개의 메세지를 읽어들일 것인지를 결정하는 옵션이다.
이번 글에서는 RabbitMQ의 주요 개념들에 대해서 알아보았다. 블로그에서 언급한 것의 몇 배는 더 많은 내용들이 있지만, 그 중에서도 기본적이고 핵심적인 것만 언급했다는 것을 참고해주면 좋을 것 같다.
다음 글에서는 RabbitMQ를 구동해보고 다양한 기능들을 사용해보도록 하겠다. 👍