Java & Spring

RabbitMQ Listener에서 예외가 발생할 때 무한 반복 요청되는 문제

ju_young 2024. 5. 17. 16:06
728x90
/**  
 * 거래 완료 메시지 전송 Listener  
 */
@RabbitListener(  
        queues = {"#{wasteCompleteQueue.name}", "#{wasteCancelQueue.name}", "#{wasteChangeStatusQueue.name}"})  
public void receiveWasteTransaction(@Payload MessageRequest messageRequest) {  
    log.debug("receive complete transaction message");  
    Alarm alarm = saveAlarm(messageRequest);  
    receive(messageRequest.memberId(), AlarmResponse.fromEntity(alarm));  
}  

/**  
 * SSE 알람 전송  
 * @param memberId 알람을 받는 사용자 id  
 */
private void receive(Long memberId, AlarmResponse alarmResponse) {  
    if (true) throw new RuntimeException(); //ListenerExecutionFailedException
}

 

위처럼 중간에 임의로 예외(ListenerExecutionFailedException)를 발생시킬 경우 무한 재실행이 된다. DB를 확인해보면 데이터가 계속 추가되는 것을 확인할 수 있었다.

 

 

공식 문서를 확인해보면 다음과 같은 문장을 볼 수 있었다.

Consequently, by default, a message that is rejected or rolled back because of a business exception can be redelivered endlessly.

끊임없이 redeliver를 한다고 한다. 만약 re-deliver 횟수를 제한하고 싶다면 StatefulRetryOperationsInterceptor을 사용하라고 한다.

 

하지만 더 간단한 방법으로 properties 값을 설정해줄 수 있다.

spring:  
  config.activate.on-profile: amqp  
  rabbitmq:  
    listener:  
      simple:  
        retry:  
          enabled: true  
          max-attempts: 3

 

이렇게 설정해주면 3번 redeliver를 해주게된다. 위처럼 max-attempts만 지정해주면 1초 간격으로 retry를 한다.

 

또한 다음과 같이 RetryTemplate을 사용해줄 수 있다.

 

@Bean
public RabbitTemplate rabbitTemplate() {
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    RetryTemplate retryTemplate = new RetryTemplate();
    ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
    backOffPolicy.setInitialInterval(500);
    backOffPolicy.setMultiplier(10.0);
    backOffPolicy.setMaxInterval(10000);
    retryTemplate.setBackOffPolicy(backOffPolicy);
    template.setRetryTemplate(retryTemplate);
    return template;
}

 

여기서 retryCallback을 추가해줄 수 있다고 한다.

RetryTemplate.execute(RetryCallback<T, E> retryCallback, RecoveryCallback<T> recoveryCallback)
728x90