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

브로커가 메시지를 버리는 'Discard' 정책의 설정법은?

by 엉짱 2026. 3. 17.
반응형

브로커가 메시지를 버리는 'Discard' 정책의 설정법은?

엔터프라이즈 메시징 환경에서 브로커의 메모리와 디스크 리소스는 유한합니다. 컨슈머(Consumer)의 처리 속도가 프로듀서(Producer)의 발행 속도를 따라가지 못해 큐(Queue)나 토픽(Topic)에 메시지가 무한정 쌓이는 상황(Slow Consumer)이 발생하면, 브로커는 전체 시스템의 다운(OOM)을 막기 위해 한계치에 도달한 메시지를 능동적으로 폐기(Discard 또는 Drop)해야 합니다.

이 가이드에서는 ActiveMQ Classic과 ActiveMQ Artemis에서 제공하는 메시지 폐기 정책의 종류와 구체적인 설정 방법을 상세히 분석합니다.


1. 폐기(Discard) 정책이 필요한 아키텍처적 이유

메시지 유실을 극도로 꺼리는 일반적인 환경에서는 큐가 꽉 찼을 때 프로듀서의 연결을 차단(Block)하거나 페이징(Paging)하여 디스크로 밀어내는 방식을 택합니다. 하지만 다음과 같은 비즈니스 환경에서는 오래된 데이터를 과감히 버리는 것이 시스템 안정성에 훨씬 유리합니다.

  • 실시간 성격의 데이터: 주식 호가, 센서의 실시간 온도 데이터 등은 1분 전의 데이터가 현재 시점에서는 아무런 가치가 없습니다. 항상 최신 데이터가 과거 데이터를 덮어쓰는 구조가 적합합니다.
  • 이벤트 브로드캐스팅: 단일 이벤트가 수많은 토픽 구독자에게 전파될 때, 응답이 없는 하나의 불량 구독자 때문에 전체 브로커 메모리가 고갈되는 것을 방지해야 합니다.

2. ActiveMQ Artemis의 폐기 정책 설정 (Address Full Policy)

차세대 브로커인 Artemis는 broker.xml<address-setting>을 통해 큐가 메모리 한계(max-size-bytes)에 도달했을 때의 동작 방식을 직관적으로 제어합니다.

A. DROP 정책 (조용히 버리기)
큐가 가득 차면 새로 유입되는 메시지를 브로커가 조용히 버립니다. 프로듀서에게는 오류를 반환하지 않으므로, 프로듀서 애플리케이션은 메시지가 정상적으로 전달되었다고 인지합니다.

<address-setting match="sensor.telemetry.#">
   <max-size-bytes>10485760</max-size-bytes> <address-full-policy>DROP</address-full-policy>
</address-setting>

B. FAIL 정책 (오류 반환 후 버리기)
메시지를 버리는 것은 동일하지만, 프로듀서에게 명시적으로 ActiveMQException (Queue is full) 예외를 던집니다. 프로듀서 측에서 재시도 로직이나 예외 처리가 필요할 때 사용합니다.

<address-setting match="critical.event.#">
   <max-size-bytes>50000000</max-size-bytes>
   <address-full-policy>FAIL</address-full-policy>
</address-setting>

C. RING 정책 (가장 오래된 것 버리기 - Ring Buffer)
새로운 메시지를 수용하기 위해 큐의 가장 앞단(Head)에 있는, 즉 가장 오래된 메시지를 폐기합니다. 항상 최신 상태의 데이터(Size 유지)만 큐에 남겨두고 싶을 때 가장 이상적인 설정입니다.

<address-setting match="stock.price.topic">
   <max-size-bytes>10485760</max-size-bytes>
   <address-full-policy>RING</address-full-policy>
</address-setting>

3. ActiveMQ Classic의 폐기 정책 설정 (Eviction Policy)

ActiveMQ 5.x 버전에서는 토픽(Topic)을 구독하는 느린 컨슈머(Slow Consumer)를 제어하기 위해 Pending Message LimitEviction Policy 조합을 주로 사용합니다.

A. 오래된 메시지 폐기 (Oldest Message Eviction)
activemq.xml의 목적지 정책 설정 구역에 정의합니다. 가장 오래된 메시지부터 삭제하여 메모리를 확보합니다.

<destinationPolicy>
   <policyMap>
      <policyEntries>
         <policyEntry topic="PRICE.DATA.>" topicPrefetch="1000">
            <pendingMessageLimitStrategy>
               <constantPendingMessageLimitStrategy limit="5000"/>
            </pendingMessageLimitStrategy>
            <messageEvictionStrategy>
               <oldestMessageEvictionStrategy/>
            </messageEvictionStrategy>
         </policyEntry>
      </policyEntries>
   </policyMap>
</destinationPolicy>

B. 우선순위를 고려한 폐기 (Lowest Priority Eviction)
모든 메시지를 동일하게 버리는 것이 아니라, 메시지의 JMSPriority 헤더 값을 확인하여 중요도가 가장 낮은 메시지부터 우선적으로 버립니다. 시스템 리소스가 부족할 때 VIP 고객의 데이터는 남기고 일반 등급의 데이터를 먼저 폐기하는 식의 고급 제어가 가능합니다.

<messageEvictionStrategy>
   <oldestMessageWithLowestPriorityEvictionStrategy/>
</messageEvictionStrategy>

4. DLQ(Dead Letter Queue)와의 관계 및 설정 주의사항

폐기 정책을 적용할 때 가장 빈번하게 발생하는 아키텍처적 실수는 "버려진 메시지가 DLQ에 쌓일 것"이라고 착각하는 것입니다.

  • 완전한 소멸: 브로커의 메모리 보호를 위해 폐기 정책에 의해 드롭된 메시지는 DLQ로 이동하지 않고 메모리에서 영구적으로 소멸됩니다.
  • DLQ는 컨슈머가 수신 후 처리에 실패하여 '최대 재시도 횟수'를 초과했을 때 이동하는 격리 공간이며, 큐 진입 단계에서 브로커 한계치로 인해 튕겨 나간 메시지 처리와는 완전히 다른 메커니즘입니다.

따라서 폐기 정책을 적용하는 토픽이나 큐는 '유실되어도 비즈니스에 치명적인 영향을 주지 않는 데이터'로 철저히 제한해야 합니다. 만약 유실되어서는 안 되는 결제, 주문 데이터라면 폐기 정책 대신 PAGE (디스크로 오프로드) 또는 BLOCK (프로듀서 대기) 정책을 설정하여 데이터 정합성을 보호해야 합니다.


5. 요약

메시지 브로커의 폐기 정책은 유한한 자원 환경에서 브로커 전체의 생존을 보장하기 위한 강력한 밸브 역할을 합니다.

  • Artemis: DROP (신규 버림), FAIL (버리고 예외 발생), RING (오래된 것 버림) 중 선택.
  • Classic: PendingMessageLimit과 함께 oldestMessageEviction 또는 우선순위 기반 폐기 방식 적용.

비즈니스 도메인의 데이터 휘발성 허용 범위를 정확히 파악하고, 각 큐의 목적에 맞는 한계치와 폐기 방식을 설정하여 장애 확산을 차단하는 인프라를 구축하시기 바랍니다.

반응형