일반적인 RabbitMQ 메시지 패턴과 사용 시기는?

필수 메시징 패턴을 익혀 RabbitMQ의 잠재력을 최대한 활용하세요. 이 가이드에서는 작업 큐(작업 분배 및 로드 밸런싱용), 게시/구독(시스템 이벤트 브로드캐스팅용), 요청/응답(동기식 호출 시뮬레이션용)의 구조, 사용 사례 및 구현 팁을 자세히 설명합니다. RabbitMQ를 사용하여 확장성이 높고, 디커플링된, 안정적인 애플리케이션을 설계하기 위한 메시지 승인, 공정 디스패치(QOS) 및 특수 교환(Fanout, Direct, Topic)과 같은 중요한 개념을 알아보세요.

일반적인 RabbitMQ 메시지 패턴과 사용 시기는?

RabbitMQ 메시지 패턴은 하나의 작업자가 작업을 처리할지, 모든 구독자가 이벤트를 받을지, 아니면 하나의 서비스가 응답을 기다릴지를 결정합니다. 잘못된 패턴을 선택하면 시스템이 작업을 중복하거나, 유용한 이벤트를 잃거나, 비동기로 유지되어야 할 호출에서 차단될 수 있습니다.

RabbitMQ는 익스체인지, 큐, 바인딩, 확인, 메시지 속성을 제공합니다. 유용한 설계 작업은 이러한 요소들이 애플리케이션에 어떻게 맞춰질지 선택하는 것입니다. 일반적인 패턴은 작업 큐, 게시/구독, 직접 또는 토픽 라우팅, 요청/응답입니다.


작업 큐: 작업자를 작업 분산

작업 큐 패턴은 종종 태스크 큐라고도 하며, 시간이 많이 걸리는 작업을 여러 작업자 프로세스(소비자)에 분산하는 데 사용되는 가장 간단하고 일반적인 메시지 패턴입니다.

작동 방식

  1. 생산자는 단일 큐에 작업(메시지)을 보냅니다.
  2. 여러 소비자(작업자)가 동일한 큐를 수신합니다.
  3. RabbitMQ는 각 메시지를 하나의 소비자에게 전달하므로 작업자가 백로그를 공유합니다.

RabbitMQ는 기본적으로 활성 소비자에게 라운드 로빈 방식으로 메시지를 분배합니다. 한 작업자가 느린 작업을 처리하고 다른 작업자가 빠른 작업을 처리하는 경우 이 분배가 항상 공정하지는 않으므로 일반적으로 이 패턴을 확인 및 프리페치 제한과 함께 사용합니다.

확인 사용

수동 확인을 사용하면 작업자가 작업이 완료되었을 때 RabbitMQ에 알립니다. 작업자가 basic_ack을 보내기 전에 종료되면 RabbitMQ는 해당 메시지를 대기열에 다시 넣고 다른 소비자에게 재전달할 수 있습니다. 이것이 작업 큐를 보고서 생성, 이미지 처리, 청구 작업 또는 자동으로 삭제되지 않아야 하는 모든 작업에 유용하게 만드는 이유입니다.

프리페치 수 설정

basic.qos는 소비자가 한 번에 보유할 수 있는 확인되지 않은 메시지 수를 제어합니다. 느리고 불균일한 작업의 경우 prefetch_count1로 설정하는 것이 안전한 시작점입니다. RabbitMQ는 첫 번째 작업을 확인할 때까지 해당 소비자에게 두 번째 작업을 보내지 않기 때문입니다. 더 빠른 작업의 경우 처리량과 메모리 사용량을 측정한 후 값을 높일 수 있습니다.

구현 예시 (개념적)

# 공정 분배를 위한 소비자 설정
channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue='task_queue', on_message_callback=worker_function)

# 작업자 로직은 성공적인 처리 후 확인을 보내야 함
worker_function(ch, method, properties, body):
    # 작업 처리...
    ch.basic_ack(delivery_tag=method.delivery_tag)

게시/구독: 이벤트 브로드캐스트

Pub/Sub 패턴은 여러 관심 있는 소비자에게 동시에 메시지를 브로드캐스트하도록 설계되었습니다. 각 메시지가 하나의 작업자만 소비하는 작업 큐와 달리 Pub/Sub은 연결된 모든 구독자가 메시지 사본을 받도록 보장합니다.

팬아웃 익스체인지 사용

생산자는 팬아웃 익스체인지에 게시합니다. 익스체인지는 라우팅 키를 무시하고 메시지 사본을 바인딩된 모든 큐에 복사합니다. 각 구독자는 일반적으로 자체 큐를 가지므로 하나의 로깅 서비스, 하나의 메트릭스 서비스, 하나의 감사 서비스가 동일한 이벤트를 경쟁 없이 받을 수 있습니다.

사용 사례

  • 실시간 알림: 모든 앱 인스턴스에 유지 관리 모드 이벤트를 브로드캐스트합니다.
  • 로깅 분산: 동일한 로그 이벤트를 아카이브 서비스와 알림 서비스로 보냅니다.
  • 캐시 무효화: 데이터베이스 변경 후 모든 서비스 인스턴스에 로컬 캐시를 지우도록 알립니다.

구현 팁

수명이 짧은 구독자의 경우 독점적이고 자동 삭제되는 큐를 만들고 팬아웃 익스체인지에 바인딩합니다. 지속적인 구독자의 경우 지속적인 큐를 사용하여 구독자가 오프라인 상태일 때 도착한 메시지를 다시 읽을 수 있도록 합니다.

직접 및 토픽 라우팅: 이벤트 선택적 전송

팬아웃 익스체인지가 블라인드 브로드캐스팅을 제공하는 반면, AMQP는 선택적 게시를 위한 익스체인지를 제공하여 Pub/Sub 모델을 확장합니다.

직접 익스체인지

메시지는 메시지의 라우팅 키와 큐의 바인딩 키 간의 정확한 일치를 기반으로 큐로 라우팅됩니다. 이는 다양한 유형의 소비자를 특별히 대상으로 지정해야 할 때 유용합니다.

예를 들어 로그 게시자는 error, warning, info와 같은 라우팅 키로 메시지를 보낼 수 있습니다. 알림 큐는 error에만 바인딩되고 아카이브 큐는 세 가지 심각도 모두에 바인딩될 수 있습니다.

토픽 익스체인지

이것은 가장 유연한 익스체인지 유형으로, 바인딩 키와 라우팅 키가 와일드카드를 사용할 수 있도록 합니다. 라우팅 키는 구분된 목록(예: 마침표 . 사용)으로 처리됩니다.

  • *는 정확히 한 단어와 일치합니다.
  • #는 0개 이상의 단어와 일치합니다.

orders.us.created와 같은 라우팅 키는 orders.*.created에 바인딩된 사기 큐와 #.us.#에 바인딩된 미국 운영 큐로 이동할 수 있습니다. 라우팅 규칙이 하나의 고정된 필드가 아닌 실제 비즈니스 범주인 경우 토픽 익스체인지를 사용하세요.

요청/응답: 특정 응답 요청

요청/응답 패턴을 사용하면 클라이언트 애플리케이션이 요청 메시지를 보내고 작업자(서버)의 응답을 동기적으로 기다릴 수 있습니다. 메시징은 본질적으로 비동기적이지만 이 패턴은 메시지 버스를 통해 기존의 원격 프로시저 호출(RPC)을 시뮬레이션합니다.

reply_tocorrelation_id 사용

  1. 클라이언트는 rpc_queue와 같은 큐에 요청을 보냅니다.
  2. 클라이언트는 reply_to를 자신이 소비하고 있는 콜백 큐로 설정합니다.
  3. 클라이언트는 고유한 correlation_id를 설정합니다.
  4. 작업자는 요청을 처리하고 reply_to 큐에 응답을 게시합니다.
  5. 클라이언트는 correlation_id를 확인하여 응답을 원래 요청과 일치시킵니다.

사용 사례

  • 서비스 조회: 다른 서비스에서 사용자 프로필 또는 기능 플래그를 가져옵니다.
  • 짧은 결정: 주문을 수락하기 전에 재고를 확인합니다.

신중하게 사용하세요

요청/응답은 유용하지만 메시징 시스템에 동기 대기를 다시 도입합니다. 클라이언트 시간 초과를 설정하고, 중복 응답을 처리하며, 장기 실행 작업에 RPC를 사용하지 마십시오. 느린 작업의 경우 명령을 게시하고, 작업 ID를 반환한 다음, 진행 또는 완료 이벤트를 별도로 보냅니다.

개념적 RPC 흐름

graph TD
    A[클라이언트 (요청자)] -->|1. 요청 메시지 (reply_to, correlation_id 포함)| B(RPC 요청 큐);
    B --> C[서버 (작업자)];
    C -->|2. 요청 처리|
D[결과];
    D -->|3. 응답 메시지 (reply_to 통해, correlation_id 유지)| A;

일반적인 RabbitMQ 패턴 한눈에 보기

패턴 익스체인지 유형 라우팅 메커니즘 주요 기능 주요 사용 사례
작업 큐 기본 또는 직접 작업자가 공유하는 하나의 큐 하나의 메시지, 하나의 소비자 장기 실행 작업의 부하 분산
게시/구독 팬아웃 라우팅 키 무시 하나의 메시지, 모든 바인딩된 큐 시스템 브로드캐스트, 로깅
직접 라우팅 직접 정확한 라우팅 키 일치 소비자 선택적 대상 지정 심각도 또는 유형 기반 라우팅
토픽 라우팅 토픽 와일드카드 일치 (*, #) 유연하고 복잡한 라우팅 마이크로서비스 통신, 이벤트 스트림
요청/응답 (RPC) 직접 (응답용) reply_tocorrelation_id 사용 동기 API 호출 시뮬레이션 즉각적인 서비스 조회, 소규모 트랜잭션

결론

통신의 형태부터 시작하세요. 정확히 하나의 작업자가 작업을 처리해야 하는 경우 작업 큐를 사용하고, 모든 구독자가 이벤트를 봐야 하는 경우 Pub/Sub을 사용하고, 일부 구독자만 봐야 하는 경우 직접 또는 토픽 라우팅을 사용하고, 호출자가 즉각적인 응답을 정말로 필요로 하는 경우에만 요청/응답을 사용하세요.