이번에는 동아리 프로젝트에서 메시지 브로커인 RabbitMQ를 도입하기로 했다. 이에 대해 알아보자.
RabbitMQ란?
- RabbitMQ는 가장 널리 배포된 오픈 소스 메시지 브로커다.
- RabbitMQ는 가볍고 구내 및 클라우드에 배포하기 쉽다.
- 여러 메시징 프로토콜을 지원한다.
- RabbitMQ는 분산형 및 연합형 구성으로 구현되어 대규모 고가용성 요구사항을 쉽게 충족할 수 있다.
- 이렇게 공식 사이트에서 소개하고 있다. 다른 설명보다 제일 눈에 띄는 것은 메시지 브로커다.
메시지 브로커란 무엇인가?.
- 메시지 브로커는 애플리케이션, 시스템 및 서비스가 서로 간에 통신하고 정보를 교환할 수 있도록 해주는 소프트웨어다.
- 메시지 브로커는 정규 메시징 프로토콜 간에 메시지를 변환함으로써 이를 수행한다.
- 이를 통해 상호 의존적인 서비스는 상이한 언어로 작성되거나 상이한 플랫폼에서 구현된 경우에도 서로 간에 통신을 할 수 있다.
- 또한 메시지 브로커는 메시징 미들웨어 또는 메시지 지향 미들웨어(MOM)의 소프트웨어 모듈, 즉 구현체다.
- 메시지 브로커는 메시지를 검증, 저장, 라우팅하고 이를 적절한 대상에 전달할 수 있다.
- 다른 애플리케이션 간의 중개자 역할을 함으로써 수신자의 위치, 수신자가 활성인지 여부 또는 수신자의 수를 잘 몰라도 송신자가 메시지를 발행할 수 있도록 허용한다.
메시지 큐란?
- 신뢰할 수 있는 메시지 저장과 보장된 메시지 전송을 위해, 메시지 브로커는 이용하는 애플리케이션이 처리할 수 있을 때까지 메시지를 저장하고 순서화하는 메시지 큐를 사용한다.
- 메시지 큐에서 메시지는 전송된 정확한 순서대로 저장되며(FIFO), 인수되었는지 확인될 때까지 큐에 남아있다.
메시지 브로커의 2가지 패턴
point to point
- 메시지의 송신자와 수신자 간에 일대일 관계를 지닌 메시지 대기열에서 사용되는 패턴이다.
publisher / consumers
- 각 메시지의 생성자는 이를 토픽에 발행하고, 다수의 메시지 이용자는 해당 메시지를 수신하고자 하는 토픽을 구독한다.
- 토픽에 대해 발행된 모든 메시지는 이를 구독한 모든 애플리케이션에 분배된다.
- 이는 메시지의 발행자와 이용자 사이에 일대다 관계가 있는 브로드캐스트 스타일의 분배 방법이다.
이제 본격적으로 RabbitMQ의 동작 방식에 대해 알아보겠다.
우선 RabbitMQ는 AMQP를 지원하기 위해 만들어졌다고 한다. 따라서 AMQP와 관련하여 알아보겠다.
AMQP
AMQP는 Advanced Message Queing Protocol의 약어다.
Publisher
Consumer에게 보낼 메시지를 생성한 주체이다.
Exchange
Consumer에게서 발행된 메시지는 Exchange를 통해 큐로 라우팅 된다.
추가적으로 Exchange Type과 Binding이라는 규칙이 더해져 라우팅 알고리즘이 결정된다.
AMQP 0-9-1은 4가지 Exchange Type를 제공한다.
1. Direct exchange
Direct exchange는 메시지 라우팅 키를 기반으로 큐에 메시지를 전달합니다.
Direct exchange는 메시지의 유니캐스트 라우팅에 이상적이다.
Direct exchange는 라운드 로빈 방식(RR)으로 여러 작업자(동일한 응용 프로그램의 인스턴스) 간에 작업을 배포하는 데 자주 사용된다.
작동 방식은 다음과 같다.
- 큐는 라우팅 키 K를 사용하여 exchange에 binding 된다.
- 라우팅 키 R이 있는 새 메시지가 direct exchange에 도착하면 해당 exchange는 K = R인 경우 큐로 라우팅한다.
2. Fanout exchange
Fanout exchange는 바인딩된 모든 큐에 라우팅 키를 무시하고 메시지를 전달한다.
해당 방식은 브로드캐스팅 라우팅 방식에 유용하다.
N개 큐가 Fanout exchange에 binding된 경우 새 메시지가 Fanout exchange에 도달하면 메시지 복사본이 모든 N개 큐에 전달된다.
3. Topic exchange
Topic exchange는 메시지 라우팅 키와 큐를 exchange에 binding하는 데 사용된 패턴 간의 일치를 기반으로
하나 이상의 큐로 메시지를 라우팅한다. Topic exchange는 다양한 발행/구독 패턴 변형을 구현하는 데 자주 사용된다.
Topic exchange는 일반적으로 메시지의 멀티캐스트 라우팅에 사용됩니다.
Topic exchange는는 매우 광범위한 사용 사례가 있다.
문제가 수신하려는 메시지 유형을 선택적으로 선택하는 consumers/applications 관련될 때마다 주제 교환의 사용을 고려해야 한다.
4. Headers exchange
Headers exchange는 라우팅 키보다 메시지 헤더로 더 쉽게 표현되는 여러 속성에 대한 라우팅을 위해 설계되었다.
Headers exchange은 라우팅 키 속성을 무시한다. 대신 라우팅에 사용되는 속성은 headers 속성에서 가져온다.
헤더 값이 바인딩 시 지정된 값과 같으면 메시지가 일치하는 것으로 간주된다. 일치를 위해 둘 이상의 헤더를 사용하여 헤더 교환에 큐를 바인딩하는 것이 가능하다.
Binding
Binding은 Exchange에서 메시지를 큐로 라우팅하는데 사용하는 규칙이다.
Exchange E가 메시지를 큐 Q로 라우팅하도록 지시하려면 Q가 E에 바인딩 되어야 한다.
바인딩에는 일부 Exchange 유형에서 사용되는 선택적 라우팅 키 속성이 있을 수 있다.
라우팅 키의 목적은 바인딩된 대기열로 라우팅할 교환에 게시된 특정 메시지를 선택하는 것이다.
즉, 라우팅 키는 필터와 같은 역할을 합니다.
Consumer
메시지를 수신받을 주체이다.
메시지 큐는 위에서 확인했으므로 넘어가겠다. 이렇게 AQMP에 핵심 구조를 살펴보았다.
추가적인 내용을 몇 가지 더 살펴보겠다.
메시지 확인
Consumers는 때때로 개별 메시지를 처리하지 못하거나 충돌할 수 있다. 또한 네트워크 문제로 인해 문제가 발생할 가능성도 있다.
그럼 이런 생각이 떠오를 수 있다. 어떻게 메시지 전송이 성공, 실패한지 인지하고,
또 언제 메시지 브로커는 큐에서 메시지를 제거해야 할까..?
AMQP 0-9-1 사양은 consumers가 이를 제어할 수 있도록 도와준다. 해당 문제를 해결할 두 가지 방법이 있다.
- 브로커가 애플리케이션에 메시지를 보낸 후 제거.( basic.deliver 또는 basic.get-ok 방법 사용).
- 응용 프로그램이 ack을 다시 보낸 후 제거.( basic.ack 메서드 사용).
전자를 자동 승인 모델이라고 하고 후자를 명시적 승인 모델이라고 한다.
명시적 모델을 사용하면 애플리케이션이 승인을 보낼 시기를 선택한다.
메시지를 수신한 직후 또는 처리하기 전에 데이터 저장소에 메시지를 유지한 후 또는 메시지를 완전히 처리한 후일 수 있다.
(예: 웹 페이지를 성공적으로 가져오고 처리하여 일부 영구 데이터 저장소에 저장)
Consumer가 확인을 보내지 않고 죽어버리면 브로커는 이를 다른 Consumer에게 다시 전달하거나,
당시 사용할 수 없는 경우 브로커는 적어도 한 Consumer가 동일한 대기열에 등록될 때까지 기다렸다가 다시 전달을 시도한다.
메시지를 거부할 경우
Consumer가 메시지를 수신하면 해당 메시지의 처리가 성공할 수도 있고 실패할 수도 있다.
Consumer는 메시지를 거부하여 메시지 처리가 실패했음(또는 당시에 완료할 수 없음)을 브로커에 표시할 수 있다.
메시지를 거부할 때 애플리케이션은 브로커에게 메시지를 삭제하거나 다시 대기열에 추가하도록 요청할 수 있다.
큐에 Consumer가 하나만 있는 경우 동일한 Consumer의 메시지를 계속해서 거부하고
다시 대기열에 추가하여 무한 메시지 배달 루프를 생성하지 않도록 하자.
이상으로 포스팅을 마칩니다. 감사합니다.
참고자료
https://www.rabbitmq.com/#features
https://www.rabbitmq.com/tutorials/amqp-concepts.html#highlevel-overview
댓글