RabbitMQ 개념

들어가며

 

최근에 RabbitMQ 공식 문서를 보면서 이해했던 기본 개념들을 정리하면 좋을것 같아 포스팅 하고자 한다.

 

 

RabbitMQ란?

 

보통 클라이언트로부터 요청된 다수의 작업을 처리하려할 때 웹 애플리케이션 서버에서 모든 요청을 처리하기 보다는 MQ를 사용하여 처리를 다른 처리자에게 위임한다. RabbitMQ는 이러한 작업을 처리할 수 있는 AMQP(Advenced Message Queing Protocol, MQ 표준 프로토콜)를 따르는 여러 오픈소스 메시지 브로커 제품중 하나다.

 

www.rabbitmq.com/

 

Messaging that just works — RabbitMQ

 

www.rabbitmq.com

 

 

대략적인 구조

 

구조에 대한 대략적인 그림은 다음과 같다.

 

 

위 그림의 설명은 다음과 같다.

 

 

Message

 

처리해야할 내용이 담겨져있다.

 

 

Producer

 

Producer는 message를 consumer에게 위임하기 위해 message를 exchange에 publish 하는 자이다.

message를 보내는 일 이외에는 아무일도 하지 않는다.

 

 

Consumer

 

Consumer는 message를 producer로 부터 위임 받아 처리하는 자이다. 

 

 

Exchange

 

Exchange는 producer에서 전달받은 message를 queue에게 전달해준다.

exchange는 메시지를 어떤 queue에 추가할지? 또, 얼마나 추가할지? 아니면 그냥 버려야할지 이는 exchange 규칙에 의해 결정된다.

 

exchange의 규칙을 결정하는 여러 타입들이 존재한다.

 

 

1. Fanout

 

Fanout 타입은 exchange와 binding된 모든 queue에게 동일한 message를 보낸다.

 

Binding이란?

 

Exchange와 Queue의 관계를 말하며, 뜻 그대로 binding이 되어야 exchange가 queue에게 message를 전달한다.

보통은 사용자가 어느 exchange가 어느 queue를 binding을 할지 정의하지만 앞서 나온 fanout은 기본적으로 모든 queue에 binding에 된다.

 

 

2. Direct

 

Direct 타입은 exchange와 message를 보낼 queue를 routing key를 통해 직접 선택하여 binding 할 수 있다.

즉 라우팅해서 보낼 수 있다.

 

 

routing key는 producer에서 exchange로 message를 publish할 때 다음 예시코드와 같이 지정하며

 

Producer.java

channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
channel.basicPublish(EXCHANGE_NAME, "rabbit", null, message.getBytes());

 

message를 위임 받는 consumer 측에서는 message를 꺼내올 queue와 바인딩되는 exchange를 설정할 때 인자로 routing key를 아래와 같이 넘겨 설정한다.

 

 

Consumer.java

channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "rabbit");

 

여기서 알 수 있는것은 publish는 producer측에서 진행하고, exchange와 queue의 binding은 consumer측에서 진행한다는 것이다.

 

그리고 만약 routing key를 dog으로 설정하고 message를 publish 했을 경우 binding 가능한 routing key는 존재하지 않기 때문에 해당 message는 버려진다.

 

 

3. Topic

 

Topic 타입은 direct 타입보다 더 유연하게 binding 규칙을 정의 할 수 있다.

direct 타입과 같은 routing key를 사용하되 topic 타입은 마침표로 구분되는 단어들을 사용한다. (최대 255Byte로 제한됨.)

 

direct 타입과 같이 publish 할 때 설정되는 routing key는 binding 할 때 설정되는 routing key와 완벽히 일치해야 binding 된다.

direct 타입과 별반 다를게 없어 보이지만 topic 타입은 routing key 문자열 내 *(start), #(hash)를 삽입시켜 유연한 binding을 제공한다.

 

*(star) - 단어 한개를 대체한다.

#(hash) - 0개 이상의 단어를 대체한다.

 

예시는 다음과 같다.

 

 

위의 그림에서 queue2는 "animal.turtle"로 exchange와 binding을 시도하려했지만 routing key가 정확히 일치하지 않아 binding 되지 않았다. 

 

 

 

위의 그림에서 queue2는 일치하는 단어가 "animal" 뿐이지만 단어 하나를 대체하기 때문에 routing key와 일치하다고 간주해 binding 된다. 그리고 queue3는 일치하는 단어가 한개도 없지만 #은 0개이상의 단어를 대체하기 때문에 binding 된다.

 

 

4. Headers

 

Headers 타입은 producer 측에서 정의된 header의 key-value 쌍과 consumer 측에서 정의된 argument의 key-value 쌍과 일치하면 binding 된다.

 

producer 측에서 정의하는 header는 message와 함께 publish 하며 consumer 측에서는 exchange와 queue를 binding 하는 시점에 argument를 정의 한다. (header 타입으로 routing key를 설정해도 무시된다.)

 

 

 

위의 그림 header와 binding에서 서로 다른값이 존재하는데 설명은 다음과 같다.

 

key value 설명
x-match all header의 모든 key-value 쌍 값과 argument의 모든 key-value 쌍 값이 일치해야 binding 된다.
x-match any argument의 key-value 쌍 값 중 하나라도 header의 key-value 쌍 값과 일치하는 쌍이 존재하면 binding 된다.

 

그리고 "x-match" 는 binding하는 시점, 즉 consumer 측에서만 정의해야 작동된다.

 

 

Queue

 

Exchange는 producer로 부터 전달 받은 message를 bingding되는 queue들에게 동일하게 전달하고

queue는 전달 받은 message들을 연결된 consumer들에게 공평하게 Round-Robin 스케쥴링 방식으로 나누어 준다. (병렬 처리)

 

 

 

마치며

 

올바르지 않은 내용에 대해 피드백 주시면 감사하겠습니다. 

 

 

참고

 

www.rabbitmq.com/