Inflearn brand logo image

인프런 커뮤니티 질문&답변

이진우님의 프로필 이미지
이진우

작성한 질문수

RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기

16.DeadLetterQueue를 이용한 재처리

DLQ 재시도 로직 처리후 DLQ에 unacked 1건이 남는거에 대해서

작성

·

74

·

수정됨

0

안녕하세요.

예시 학습 중에 DeadLetterQueue 수동 재시도 관련해서 질문있습니다.

 

http 호출 이후에 추가적으로 DLQConsumer가 호출되지는 않는데, 처리 후 RabbitMQ 콘솔 확인해보니 DLQ에 unacked 한 건이 남아 있었습니다. 제 생각에는 DLQConsumer에서 정상적으로 메시지 소비했으면 마찬가지로 ack 처리 해줘야 하는게 아닌가 싶은데, DLQ에 unacked 상태로 남기는게 의도된 경우가 있을수 있는건지 궁금합니다.

스크린샷 2025-04-27 12-47-16.png

 

order_completed_queue에서는 모두 처리되서 메시지가 보이지 않습니다.

스크린샷 2025-04-27 12-49-34.png

 

예시 코드

@Component
@RequiredArgsConstructor
public class OrderDLQConsumer {
    private final RabbitTemplate rabbitTemplate;

    @RabbitListener(queues = RabbitMQConfig.DLQ)
    public void process(String message) {
        System.out.println("DLQ Message Received: " + message);

        try {
            String fixMessage = "success";

            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.ORDER_EXCHANGE,
                    "order.completed.shipping",
                    fixMessage
            );
            System.out.println("DLQ Message Sent: " + fixMessage);
           
        } catch (Exception e) {
            System.err.println("### [DLQ Consumer Error] " + e.getMessage());
        }
    }
}

 

 

답변 2

1

코드빌런님의 프로필 이미지
코드빌런
지식공유자

안녕하세요. 수강자님

Spring에서 @RabbitListener는 기본적으로 AcknowledgeMode가 AUTO라서 정상적으로 종료된 경우에는 Spring 내부에서 ack가 처리 됩니다.
다만 여기서 Exception이 있고 내부적으로 커넥션이 잠시 잃어버렸다거나 리스너가 비정상이어서 여기에 진입한 경우 정상적으로 처리 하지 못하고 unacked 로 남기는 것으로 보입니다.

 

이 부분을 정밀하게 처리하려면 catch 구문에서 세부적인 exception 을 잡아 throw 하거나 ack mode를 MANUAL로 바꿔서 호출해주는 형태로 변경해주면 unacked 로 남는 경우는 없을것으로 보입니다.

exception throw 관련 예외 클래스는 AmqpRejectAndDontRequeueException 를 살펴보시고 관련 예제를 한번 보시면 도움이 될것 같습니다.

 

도움이 되었기를 바랍니다.

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다. 이진우님.

Dead Letter Queue(DLQ)와 관련한 수동 재시도 처리 로직에서의 unacked 메시지 관련 질문에 대해 설명드리겠습니다.

DLQ에서의 unacked 메시지 현상

  1. 확인 응답(Acknowledge) 처리:

    • 일반적으로 RabbitListener에서 메시지를 소비하면 메시지가 정상적으로 처리되었음을 브로커에 알려주기 위해 확인 응답(acknowledge)을 보내야 합니다. 이는 메시지가 다시 재전송되지 않도록 하기 위한 방법으로, 기본적으로 Spring의 AMQP 설정이 auto acknowledge로 되어 있지 않으면 개발자가 수동으로 acknowledge를 처리해야 합니다.
  2. unacked가 되는 이유:

    • unacked로 메시지가 남아있는 경우, 메시지를 소비한 후에 메시지 처리가 완료되지 않았을 가능성이 있습니다. 예를 들어, 더 이상 처리되지 않거나 예외가 발생하면서 명시적으로 ack가 호출되지 않았을 수 있습니다.
    • Java 코드에서 예외가 발생할 때, Spring AMQP는 기본적으로 메시지를 제외하고 예외를 던지게끔 설정되어 있습니다. 이런 경우, 메시지가 unacked 상태로 남을 수 있습니다.
  3. 해결 방법:

    • 메시지를 성공적으로 재전송하였다면, ack를 수동으로 보내는 방법을 고려해보세요. Spring에서 수동으로 ack 및 nack 처리할 수 있는 방법을 문서에서 찾아보고, 이를 적용하여 처리해 보시는 것을 추천드립니다.
  4. 추가 참고:

    • 특정 비즈니스 로직에서 DLQ 메시지를 그대로 놓아둬야 하는 경우도 있지만, 님의 경우에는 실제로 ack가 이루어지지 않은 것으로 보입니다. 이를 확인하는 것이 중요합니다.

기획 의도에 따라 메시지를 소비 후 재전송 후의 처리를 명확히 하는 것이 중요하며, 신뢰성 있는 소비 및 전송을 구현하기 위해 수동 ack로의 전환을 검토할 수도 있습니다.

아래 추가로 도움이 될만한 관련 질문 링크를 참조하세요:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

이진우님의 프로필 이미지
이진우

작성한 질문수

질문하기