본문 바로가기
1. 개발/1.8. ActiveMQ

'Message Redistribution' 기능이 컨슈머가 없는 노드의 메시지를 옮기는 시점?

by 엉짱 2026. 4. 11.
반응형

'Message Redistribution' 기능이 컨슈머가 없는 노드의 메시지를 옮기는 시점?

엔터프라이즈 환경에서 메시지 브로커(ActiveMQ Artemis 등)의 고가용성(HA)과 처리량 확장을 위해 여러 대의 브로커를 엮어 클러스터(Cluster)를 구성하는 것은 필수적인 아키텍처입니다. 클러스터 환경에서는 기본적으로 프로듀서가 메시지를 보내면, 브로커는 영리하게 컨슈머가 연결된 노드를 찾아 메시지를 라우팅(Load Balancing)해 줍니다.

하지만 인프라 운영 중에는 항상 예기치 못한 변수가 발생합니다. 특정 노드에 메시지가 정상적으로 적재되었으나, 해당 노드에서 메시지를 처리하던 컨슈머 애플리케이션이 갑자기 다운되거나 네트워크 단절로 연결이 끊어지는 상황입니다.

이때 큐(Queue)에 남겨진 메시지들은 자신을 꺼내갈 컨슈머가 없어 영원히 고립되는 'Stuck Message(고립된 메시지)' 상태에 빠집니다. 다른 노드에 쌩쌩한 컨슈머들이 수십 대 대기하고 있음에도 불구하고 말입니다. 이러한 클러스터 내의 불균형과 데이터 처리 지연을 해결하기 위해 존재하는 강력한 기능이 바로 'Message Redistribution (메시지 재분배)'입니다.

본 가이드에서는 고립된 메시지를 다른 노드로 구출해 내는 Message Redistribution의 정확한 발동 시점과, 이를 제어하는 핵심 파라미터의 아키텍처적 의미를 상세히 해부합니다.


1. 'Stuck Message'의 비극과 Redistribution의 등장

일반적인 클러스터 로드 밸런싱은 메시지가 브로커에 도착하는 순간(Arrival)에만 목적지를 결정합니다. 일단 A 브로커의 큐에 메시지가 물리적으로 저장(디스크 기록)되고 나면, A 브로커의 컨슈머가 죽더라도 이 메시지들은 스스로 B 브로커로 넘어가지 않습니다.

  • 결과: A 브로커의 큐에는 처리되지 못한 메시지가 수만 건 쌓여 지연(Lag)이 발생하고, B 브로커의 컨슈머들은 할 일이 없어 CPU를 놀리는 극심한 리소스 낭비가 발생합니다.
  • 해결책: ActiveMQ Artemis는 이를 감지하고, A 브로커의 큐에 저장된 메시지들을 능동적으로 다시 꺼내어(Forward) 컨슈머가 살아있는 B 브로커로 넘겨주는 Message Redistribution 기능을 제공합니다.

2. 메시지를 옮기는 결정적 시점: 'redistribution-delay'

그렇다면 A 브로커는 컨슈머가 사라진 것을 인지한 직후, 정확히 언제(When) 메시지를 B 브로커로 넘길까요?

이 시점을 결정하는 단 하나의 핵심 파라미터가 바로 목적지 설정(address-setting) 내에 있는 redistribution-delay입니다. 이 값(밀리초 단위)을 어떻게 설정하느냐에 따라 클러스터의 운명이 완전히 뒤바뀝니다.

A. redistribution-delay="0" (즉각 이동: 핑퐁의 함정)

  • 동작 시점: 큐에 연결된 마지막 컨슈머의 연결이 끊어지는 즉시(0ms 대기), 큐에 남아있는 모든 메시지를 컨슈머가 있는 다른 노드로 쏟아냅니다.
  • 위험성 (Network Ping-Pong): 네트워크 장비의 일시적인 순단이나 애플리케이션의 가비지 컬렉션(GC) 멈춤 현상으로 인해 컨슈머가 단 0.1초 연결이 끊어졌다가 다시 붙는 경우가 빈번합니다. 지연 시간이 0이면, 컨슈머가 잠시 끊어진 찰나의 순간에 브로커는 수만 건의 메시지를 B 브로커로 넘깁니다. 그런데 메시지가 넘어가고 있는 도중 A 브로커의 컨슈머가 다시 접속하면, 메시지들은 다시 A 브로커로 돌아오려 합니다. 이렇게 메시지가 브로커 사이를 미친 듯이 오가는 '핑퐁(Ping-Pong)' 현상이 발생하여 클러스터 네트워크 대역폭이 100% 고갈되는 대형 장애가 발생할 수 있습니다.

B. redistribution-delay="5000" (지연 이동: 우아한 유예 시간) ★모범 사례

  • 동작 시점: 마지막 컨슈머가 사라지면, 브로커는 즉시 메시지를 옮기지 않고 설정된 시간(예: 5000ms = 5초) 동안 타이머를 돌리며 기다려 줍니다.
  • 아키텍처적 이점: 이 5초는 일시적인 네트워크 순단으로 끊어진 컨슈머가 다시 재연결(Reconnect)을 시도하여 복구될 수 있도록 기회를 주는 '우아한 유예 시간(Grace Period)'입니다. 만약 5초 안에 원래의 컨슈머가 다시 돌아온다면, 브로커는 메시지를 옮기지 않고 로컬 컨슈머에게 그대로 전달합니다. 무거운 디스크 I/O와 네트워크 트래픽 낭비를 완벽하게 방어하면서도, 진짜로 서버가 죽어버린 상황(5초 초과 시)에서는 안전하게 다른 노드로 메시지를 재분배하여 시스템의 처리 흐름을 끊기지 않게 유지합니다.

C. redistribution-delay="-1" (이동 불가: 재분배 원천 차단)

  • 동작 시점: 브로커는 컨슈머가 사라져도 메시지를 절대 다른 노드로 옮기지 않습니다.
  • 사용 시나리오: 메시지가 다른 브로커로 넘어가는 과정에서 필연적으로 '메시지의 순서(Ordering)'가 뒤섞이게 됩니다. 금융 결제나 데이터베이스 트랜잭션 로그처럼 순서 보장이 생명인 시스템(Strict Ordering)에서는, 컨슈머가 죽어서 처리가 늦어지더라도 순서가 꼬이는 것보다는 원래 자리에 그대로 두는 것이 낫습니다. 이때 재분배 기능을 완전히 끄기 위해 사용합니다. (Artemis의 기본값은 보통 -1로 되어 있으므로, HA 구성을 위해서는 반드시 양수로 튜닝해야 합니다.)

3. 재분배(Redistribution)의 내부 동작 메커니즘

redistribution-delay 타이머가 만료되어 메시지가 실제로 이동하기 시작할 때, 브로커 내부에서는 매우 영리한 최적화 과정이 일어납니다.

  1. 글로벌 수요(Demand) 탐색: A 브로커는 무작정 메시지를 흩뿌리지 않습니다. 클러스터 토폴로지 정보를 확인하여 현재 B 브로커나 C 브로커 중 해당 큐를 리스닝(Listening)하고 있는 '살아있는 컨슈머'가 존재하는지 먼저 확인합니다.
  2. 동적 브릿지(Bridge) 생성: B 브로커에 컨슈머가 존재함을 확인하면, A 브로커는 내부적으로 B 브로커를 향해 데이터를 퍼 나르기 위한 일시적인 라우팅 파이프라인을 엽니다.
  3. 페이로드 포워딩: 큐에 잠들어 있던 메시지들이 디스크에서 읽혀 B 브로커의 큐로 이동합니다. 이때 B 브로커에 도착한 메시지들은 B 브로커의 로컬 메시지와 섞이게 되며, B 브로커의 컨슈머들이 이를 성공적으로 처리하여 글로벌 트래픽의 병목이 해소됩니다.

4. 아키텍처 설계 시 주의사항 및 최적화 가이드

프로덕션 환경에서 Message Redistribution을 완벽하게 통제하려면 broker.xml 설정 파일 내에서 다음 사항들을 반드시 체크해야 합니다.

[broker.xml 설정 예시]

<address-settings>
    <address-setting match="queue.worker.#">
        <redistribution-delay>3000</redistribution-delay>
    </address-setting>

    <address-setting match="queue.payment.strict">
        <redistribution-delay>-1</redistribution-delay>
    </address-setting>
</address-settings>

운영 튜닝 포인트:

  • 네트워크 지연율과의 상관관계: 클라이언트 애플리케이션의 Failover 설정(재연결 간격)을 확인해야 합니다. 만약 클라이언트가 재연결을 시도하는 간격이 2초라면, redistribution-delay는 이보다 여유로운 3초 이상으로 설정해야 불필요한 이동을 막을 수 있습니다.
  • 메시지 그룹핑(Message Grouping)과의 충돌: 특정 메시지들이 반드시 동일한 컨슈머에게 순서대로 가야 하는 'Message Grouping' 기능을 사용 중이라면, Redistribution이 작동하는 순간 그룹핑 규칙이 깨질 수 있습니다. 그룹핑 환경에서는 재분배 기능을 매우 신중하게 접근하거나 끄는 것이 원칙입니다.

결론적으로 'Message Redistribution'은 클러스터라는 거대한 유기체가 특정 부위의 마비(컨슈머 다운)를 스스로 치료하고 자원을 재배치하는 훌륭한 자가 치유(Self-Healing) 메커니즘입니다. 인프라의 네트워크 체력과 클라이언트의 재연결 주기를 명확히 측정하여, 가장 합리적인 redistribution-delay 타임을 부여함으로써 핑퐁의 재앙 없이 무중단 메시징 파이프라인을 완성하시기 바랍니다.

반응형