005 Rabbit Mq

기술 블로그 정리 #

RabbitMQ란? #

RabbitMQ란? #

  • AMQP를 따르는 오픈소스 메시지 브로커
  • 메시지를 많은 사용자에게 전달하거나, 요청에 대한 처리 시간이 길 때, 해당 요청을 다른 API에게 위임하고 빠른 응답을 할때 많이 사용한다.

AMQP #

Advanced Message Queueing Protocol MQ의 오픈소스에 기반한 표준 프로토콜을 의미한다.

RabbitMQ 개념 #

img.png

1. Producer #

  • 메시지를 생성하고 발송하는 주체
  • 이 메시지가 Queue에 저장된다.
  • Producer는 Queue에 직접 접근하지 않고, 항상 Exchange를 통해 접근하게 된다.

2. Exchange #

  • Producer들에게서 전달받은 메시지들을 어떤 Queue들에게 발송할지를 결정하는 객체
  • 4가지 타입이 있으며, 일종의 라우터 개념

3. Binding #

  • Exchange에게 메시지를 라우팅 할 규칙을 지정하는 행위
  • 특정 조건에 맞는 메시지를 특정 큐에 전송하도록 설정할 수 있는데, 이는 해당 Exchange 타입에 맞게 설정되어야한다.
  • Exchange와 Queue는 m:n binding이 가능하다.

4. Queue #

  • Producer들이 발송한 메시지들이 Consumer가 소비하기 전까지 보관되는 장소
  • 같은 이름과 같은 설정으로 Queue를 생성하면 에러 없이 기존 Queue에 연결되지만, 같은 이름과 다른 설정으로 Queue를 생성하려고 시도하면 에러 발생한다.

5. Consumer #

  • 메시지를 수신하는 주체
  • Queue에 직접 접근하여 메시지를 가져온다.

Exchange 타입 #

    1. Direct : Routing key가 정확히 일치하는 Queue에 메시지 전송
    1. Topic : Routing key 패턴이 일치하는 Queue에 메시지 전송
    1. Headers : [key:value] 로 이루어진 header 값을 기준으로 일치하는 Queue에 메시지 전송
    1. Fanout : 해당 Exchange에 등록된 모든 Queue에 메시지 전송

Direct #

  • 라우팅 키를 이용하여 메시지를 라우팅하는데, 하나의 큐에 여러개의 라우팅 키를 지정할 수 있다.

img_1.png

  • 각 메시지에 따라 C1, C2에 저장

img_2.png

  • 여러 큐에 같은 라우팅 키를 지정하여 Fanout처럼 동작하게 할 수도 있다.

Topic #

  • 라우팅 키 패턴을 이용하여 메시지를 라우팅한다.

img_3.png

  • example.orange.rabbit -> 메시지가 Q1, Q2에 모두 전달
  • example.orange.turtle -> 메시지가 Q1에 전달
  • lazy.grape.rabbit -> 메시지가 Q2에 한번만 전달
    • 라우팅 패턴이 여러개 일치하더라도 하나의 큐에는 메시지가 한번만 전달된다.

Headers #

  • Topic Exchange와 유사하지만 라우팅을 위해 header를 쓴다는 차이점이 있다. img_4.png

Fanout #

  • exchange에 등록된 모든 queue에 메시지를 전송한다. img_5.png

Message Queue 및 Message 보존 #

RabbitMq server가 종료 후 재기동하면, 기본적으로 Queue는 모두 제거된다. 이를 막기 위해서는 Queue를 생성할때, Durable 옵션에 true를 주고 생성해야한다. Producer가 메시지를 발송할 때, PERSISTENT_TEXT_PLAIN 옵션을 주어야 메시지가 보존된다.

dispatching #

만약 여러 소비자가 1개의 Queue를 바라보고 있다면 RabbitMQ에서는 Round-Robin 사용해 메시지를 균등하게 분배한다. 즉, 중복 처리를 방지하기 위해 첫번째 메시지는 소비자 1에게 전달하고, 두번째 메시지는 소비자1이 아닌 소비자2에게 전달한다. 소비자 뿐만 아니라 여러 생산자도 같은 Queue에 메시지를 전달할 수 있다. 이러한 특성으로 메시지를 받아 처리하는 프로그램의 수평 확장이 가능하다.

Fair dispatching #

만약 소비자는 2개만 존재하고 홀수번째의 메시지의 크기는 항상 크고 짝수번째 메시지는 항상 작다면, Round-Robin 알고리즘을 사용해서 메시지 분배를 해도 공평하게 소비자에게 전달되지 않는다. 이러한 이유로 지연이 발생한 소비자에는 메시지를 전달하지 않도록 prefetch count라는 개념을 사용한다.

prefetch count #

  • 1로 설정 : 소비자로부터 act을 받지 못한 메시지가 1개라도 있으면 해당 소비자에게 메시지를 전달하지 않는다.
  • 즉, prefetch count는 소비자에게 동시에 전달되는 메시지의 양이다.

소비자 서버가 죽었을 경우 #

Queue는 소비자에게 메시지를 전달한 후 ACK를 받았을때 해당 메시지를 dequeue한다. 소비자가 ACK를 Queue에 전달하지 못하는 경우는 메시지가 너무 커서 아직 처리 중이거나 소비자 서버가 죽었을 때이다. RabbitMQ에서는 ACK을 받지 못한 메시지의 경우, 대기를 하고 있다가 전달한 소비자 서버의 상태를 확인한 후, Disconnected와 같은 신호를 받았을 경우 해당 소비자를 제외하고 다른 소비자에게 동일한 메시지를 전달한다.

Message Durability #

만약 메시지를 Queue에 넣은 다음 소비자에게 전달하기 전에 RabbitMq가 죽는다면, Queue는 메모리에 데이터를 쓰는 형식이므로 모든 데이터가 소멸하게 된다.

영속성 #

message durability는 메시지가 Queue에 저장될때, disk의 파일에도 동시에 저장하는 방법이다.

해당 방법을 사용하면 서버가 죽었을때, Queue의 데이터가 어느 정도 복구가 되지만 메시지가 disk의 파일에 쓰는 도중에 서버가 죽는 경우도 있어서 일부 데이터의 소실이 발생할 수 있다.

RabbitMQ 노드 #

  • RAM : 모든 메타 정보를 메모리에 저장한다.
    • disc보다 성능이 좋지만 해당 노드에 문제가 생겼을때 데이터가 유실될 수 있다.
  • disc : 데이터를 디스크에 저장한다.

RabbitMQ는 클러스터 내 모든 노드를 RAM 타입을 구성하는 것을 제한한다. 반드시 1개 이상의 disc 타입의 노드를 포함해야한다.