메시지 큐(MQ)

메시지 큐에 대해서 학습하고 정리한 글입니다.

메세지 큐란 ?

메세지 지향 미들웨어(MOM)은 비동기 메시지를 사용하는 다른 응용프로그램의 데이터 송수신을 말한다.

메세지 큐(MQ)는 프로그래밍에서 프로세스 또는 프로그램 인스턴스가 데이터를 서로 교환할 때 사용하는 방법이다.

데이터를 교환 시 시스템이 관리하는 메시지 큐를 이용하는 것이 특징이다.

MOM은 MQ를 포괄하고 있고 MQ에는 Kafka, RabbitMQ, ActiveMQ 등이 있다.

왜 사용을 하는 것일까?

  • 메세지 큐는 IPC(Inter-Process Communication) 도구 중 하나로, 시스템 프로그래밍에서 사용된다.

    이는 프로세스들 간에 데이터 송수신을 위해 사용하는데, 각 데이터를 메세지 형태로 생성, 전달하고 수신이 가능하게끔 Queue 데이터구조를 이용한다.

  • 또 다른 이유로는 분산 메시징 시스템에 활용된다. 모니터링, 로그, 이벤트 메시지 등 아주 거대한 양의 데이터를 다룰 일이 생김에 따라 필요하게된다.

    Queue는 여러 컴포넌트들이 데이터를 생성하고 또 저장하고 사용하는 과정에서 일종의 버퍼 역할을 수행한다.

    이로인해 Producer와 Consumer간의 속도가 다를 때, 둘 중 어느 한 컴포넌트가 장애가 발생했을 때 상황 등에 대응이 가능하다. 따라서 장애 전파를 막을 수 있다.

    기본적으로 분산 메시징 시스템은 어떤 특정 메시지가 최소한 한번은 전달될 수 있도록 보장하며 다수의 reader와 writer를 하나의 큐를 통해서 공유하고 상호작용할 수 있게끔 만든다.

구체적인 장점들

좀 더 구체적으로 장점을 정리하자면 아래와 같다.

  • 비동기(Asynchronous): Queue에 넣어두기 때문에 나중에 처리할 수 있다.
  • 분리 또는 비동조(Decoupling): 애플리케이션과 분리할 수 있다.
  • 탄력성(Resilience): 일부가 실패 시 전체에 영향을 받지 않는다.
  • 과잉(Redundancy): 실패 할 경우 재실행이 가능하다.
  • 보증(Guarantees): 작업이 처리된 걸 확인할 수 있다.
  • 확장성(Scalable): 다수의 프로세스들이 큐에 메시지를 보낼 수 있다.

여러가지 MQ들

MQ의 종류로는 여러가지가 있는데 Kafka, RabbitMQ, ActiveMQ(JMS)가 대표적이다. Amazon SQS, Amazon MQ 등도 있다.

ActiveMQ(JMS)

MOM을 자바에서 지원하는 표준 API이다. JMS는 다른 자바 애플리케이션들끼리 통신이 가능하지만 다른 MOM의 통신은 불가능하다. (AMQP, SMTP 같은)

ActiveMQ의 JMS 라이브러리를 사용한 자바 애플리케이션들끼리 통신이 가능하다. 하지만 다른 자바 애플리케이션(Non ActiveMQ)의 JMS와는 통신할 수 없다.

RabbitMQ

RabbitMQ는 AMQP(Advanced Message Queuing Protocol)를 구현한 오픈소스 메시지 브로커이다.

AMQP는 MQ를 오픈 소스에 기반한 표준 프로토콜이다. 프로토콜만 맞다면 다른 AMQP를 사용한 애플리케이션끼리 통신이 가능하다. 플러그인을 통해서 SMTP, STOMP 프로토콜과의 확장이 가능하다.

AMQP는 메세지 전달을 아래 3가지 방식 중 하나를 보장한다.

  • At-Most-Once: 각 메시지는 한번만 전달되거나 전달되지 않음
  • At-Least-Once: 각 메시지는 최소 한번 이상 전달됨을 보장
  • Exactly-Once: 각 메시지는 딱 한번만 전달됨

AMQP는 메시징 제공자와 클라이언트의 동작에 대해 각기 다른 벤더들의 구현체가 상호 운용될 수 있는 정도로까지 권한을 준다. 이는 SMTP, HTTP, FTP 등이 상호 운용이 가능한 시스템을 만든다는 점에서 동일하다.

AMQP

  • Producer(Publisher): 메시지를 보내는 곳이다.
  • Consumer(Subscriber): 메시지를 받는 곳이다.
  • Exchange: Producer로부터 메시지를 수신하는 곳. 수신한 메시지를 큐에 분배한다.
  • Queue: 메시지를 저장하는 곳. 저장했다가 Consumer에게 전달한다.
  • Binding: Exchange와 Queue의 Mapping. 1:1 또는 1:N

간단히 말하면 아래와 같다.

Exchange가 Producer로부터 메시지를 받고 Queue에 전달한다. Queue는 Consumer에게 메시지를 전달한다.

Usage

RabbitMQ는 범용 메시징 솔루션으로, 사용자가 결과를 기다리는 동안 리소스 사용량이 많은 절차를 수행하지 않고 웹 서버가 요청에 신속하게 응답할 수 있도록 하는 데 종종 사용된다. 메시지를 여러 수신자에게 배포하여 소비하거나 부하가 많은 작업자 간에 부하를 분산시키는 데도 유용하다.

Rabbit MQ는 아래와 같은 시나리오에서 사용하기 적합할 수 있다.

  • AMQP 0-9-1, STOMP, MQTT, AMQP 1.0 같은 기존 프로토콜의 조합으로 작업해야 하는 경우
  • 메시지별 정합성 관리/보증이 필요한 경우
  • 시점별 다양성, 요청/응답, 게시/구독 메시지가 필요한 경우
  • 소비자에 대한 복잡한 라우팅, 여러 서비스/앱과 타의 추종을 불허하는 라우팅 논리 통합

Apache Kafka

Apache Kafka는 LinkedIn이 개발하고 Apache Software Foundation에 기부한 오픈 소스 스트림 프로세싱 소프트웨어 플랫폼이다.

높은 처리량을 요구하는 실시간 데이터 피드 처리나 대기 시간이 짧은 플랫폼을 제공하는 것을 목표로 하며 TCP 기반 프로토콜을 사용한다. 클러스터를 중심으로 Producer와 Consumer가 데이터를 Push하고 Pull하는 구조를 가진다.

특징

  • Publisher / Subscriber 모델
  • 고가용성
  • 확장성
  • 디스크 순차 저장 및 처리
  • 분산 처리 (Partitioning)

카프카는 내구성이 뛰어난 메시지 저장소로, 고객들은 메시지가 한 번 배달되면 대기열에서 제거되는 전통적인 메시지 중개업자들과는 달리, 필요에 따라 이벤트 스트림을 재생할 수 있다.

대용량의 실시간 로그 처리에 특화되어 설계된 메시징 시스템으로써 기존 범용 메시징 시스템대비 TPS(Transaction per second)가 매우 우수하다. 단, 특화된 시스템이기 때문에 범용 메시징 시스템에서 제공하는 다양한 기능들은 제공되지 않는다.

분산 시스템을 기본으로 설계되었기 때문에 기존 메시징 시스템에 비해 분산 및 복제 구성을 손쉽게 할 수 있다.

AMQP 프로토콜이나 JMS API를 사용하지 않고 단순한 메시지 헤더를 지닌 TCP기반의 프로토콜을 사용하여 프로토콜에 의한 오버헤드를 감소시켰다.

Producer가 Broker에게 다수의 메시지를 전송할 때 각 메시지를 개별적으로 전송해야하는 기존 메시징 시스템과는 달리, 다수의 메시지를 batch형태로 Broker에게 한 번에 전달할 수 있어 TCP/IP 라운드 트립 횟수를 줄일 수 있다.

메시지를 기본적으로 메모리에 저장하는 기본 메시징 시스템과는 달리 메시지를 파일 시스템에 저장한다. (RabbitMQ는 ram or disk 선택가능)

파일 시스템에 메시지를 저장하기 때문에 별도의 설정을 하지 않아도 데이터의 영속성이 보장된다.

기존 메시징 시스템에서는 처리되지 않고 남아있는 메시지의 수가 많을수록 시스템의 성능이 크게 감소하였으나, Kafka에서는 메시지를 파일 시스템에 저장하기 때문에 메시지를 많이 쌓아두어도 성능이 크게 감소하지 않는다. 또한 많은 메시지를 쌓아둘 수 있기 때문에, 실시간 처리뿐만 아니라 주기적인 batch 작업에 사용할 데이터를 쌓아두는 용도로도 사용할 수 있다.

Consumer에 의해 처리된 메시지(ack)를 곧바로 삭제하는 기존 메시징 시스템과는 달리 처리된 메시지를 삭제하지 않고 파일 시스템에 그대로 두었다가 설정된 수명이 지나면 삭제한다. 처리된 메시지를 일정 기간동안 삭제하지 않기 때문에 메시지 처리 도중에 문제가 발생하였거나 처리 로직이 변경되었을 경우 Consumer가 메시지를 처음부터 다시 처리(rewind)하도록 할 수 있다.

기존의 메시징 시스템에서는 Broker가 Consumer에게 메시지를 Push해주는 방식인데 반해, Kafka는 Consumer가 Broker로부터 직접 메시지를 가지고 가는 pull(poliing)방식으로 동작한다. 따라서 Consumer는 자신의 처리능력만큼의 메시지만 Broker로부터 가져오기 때문에 최적의 성능을 낼 수 있다.

메시지를 Pull 방식으로 가져오므로, 메시지를 쌓아두었따가 주기적으로 처리하는 Batch Consumer의 구현이 가능하다.

큐의 기능은 JMS, AMQP 기반의 RabbitMQ등에 비해서는 많이 부족하지만 대용량 메시지를 지원할 수 있는 것이 가장 큰 특징이다. 특히 분산 환경에서 복사본을 다른 노드에 저장함으로써 노드 장애에 대한 장애 대응성을 가지고 있는 강점이 있다.

Usage

Apache Kafka는 아래와 같은 시나리오에서 사용하기에 적합할 수 있다.

  • 최대 처리량(100k/sec+)으로 복잡한 라우팅 없이 A에서 B로 스트리밍, 분할된 순서대로 1회 이상 제공
  • 응용 프로그램에서 스트림 히스토리에 대한 액세스 권한이 필요한 경우, 분할된 순서대로 한 번 이상 제공
  • 내구성이 뛰어난 메시지 저장소로, 고객들은 메시지가 한 번 배달되면 대기열에서 제거되는 전통적인 메시지 브로커와는 달리, 필요에 따라 이벤트 스트림을 다시 재생하여야 하는 경우
  • 스트림 처리
  • 이벤트 소싱(상태에 대한 변경 사항을 모두 저장하는 개발 패턴, 순차적으로 발생하는 이벤트를 모두 저장)

Reference

https://twowinsh87.github.io/etc/2018/08/07/etc-kafka-8/

https://kji6252.github.io/2015/12/18/message-quere/

https://veluxer62.github.io/reference/message-queue/

https://preamtree.tistory.com/172

⤧  Next post Docker Compose를 이용한 개발 환경구성과 예제 ⤧  Previous post JVM 구조와 자바의 실행방식