728x90
Spring Kafka Consumer 부분을 맡으면서 예외 상황을 처리하기 위해 Kafka Retry 전략에 대해 알아보았다.
메시지를 소비하는 동안 예상치 못한 오류가 발생할 수 있으며, 이를 적절히 처리하는 로직이 필요하다. 메시지를 반복적으로 재처리하거나, 재처리 후에도 실패하는 메시지를 별도의 토픽으로 관리해야한다.
Consumer의 예외 상황을 처리하기 위한 방식으로는 ErrorHandler 방식과 어노테이션 방식 이 있다.
ErrorHandler 방식
Spring Kafka는 이러한 예외 상황을 처리하기 위해 DefaultErrorHandler
와 BackOff
기능을 제공한다.
재시도 간격에 따라 다양한 Backoff 전략이 있다.
- Fixed Backoff : 일정된 시간 간격으로 재시도하는 전략
- Exponential Backoff (지수 Backoff) : 재시도 간격을 점차 길어지게 하여 시스템 부하를 줄이는 전략
- Randomized Backoff : 재시도 간격을 랜덤하게 설정하여, 여러 재시도 요청이 동시에 발생하는 것을 방지하는 전략
나는 일시적인 문제 해결에 유리한 지수 Backoff 전략을 이용했다.
@Bean
public DefaultErrorHandler errorHandler() {
// 메시지 처리가 일정 횟수 이상 실패할 경우, 해당 메시지를 "dead-letter-topic"으로 이동
DeadLetterPublishingRecoverer recoverer = new DeadLetterPublishingRecoverer(kafkaTemplate,
(consumerRecord, e) -> new TopicPartition("dead-letter-topic", consumerRecord.partition()));
ExponentialBackOff backoff = new ExponentialBackOff();
backoff.setInitialInterval(1000L); // 초기 간격은 1초
backoff.setMultiplier(2); // 2초 간격으로 재시도
backoff.setMaxInterval(8000L); // 최대 간격은 8초 ( 1 → 2 → 4 → 8 → 8 )
DefaultErrorHandler errorHandler = new DefaultErrorHandler(recoverer, backoff);
// 최대 재시도 횟수는 5회
errorHandler.setRetryListeners((ConsumerRecord<?, ?> record, Exception ex, int deliveryAttempt) -> {
if (deliveryAttempt >= 5) {
recoverer.accept(record, ex);
}
});
return errorHandler;
}
어노테이션 방식
Spring에서 @RetryableTopic 을 이용하여 재시도 처리를 할 수 있다.
간편한 설정이 장점이며 Dead Letter Topic을 자동으로 생성해 관리해준다. 특정 예외마다 다른 재시도 설정을 하는 등 고급 재시도 로직을 구현할 것 아니면 어노테이션이 간편하고 가독성도 좋은 듯하다.
@KafkaListener(topics = "${spring.kafka.topic.log-topic}", groupId = "${spring.kafka.consumer.group-id}")
@RetryableTopic(
attempts = "5", // 최대 재시도 횟수는 5회
backoff = @Backoff(delay = 1000, multiplier = 2.0), // 초기 간격은 1초로 재시도 간격이 2배씩 증가
dltTopicSuffix = ".dlt" // 기존 토픽 이름에서 .dlt 접미사가 추가된 이름으로 Dead Letter Topic 생성
)
public void listenLogRequest(ConsumerRecord<String, String> record) throws Exception {
log.info("받은 메시지: " + record.value());
}
다음과 같이 여러 번의 재시도 후 최종적으로 DLT에 도달하도록 구현하였다. 이후에 메시지가 DLT에 도달하면 개발자에게 알림을 전송하고, 원인을 분석하고 해결할 수 있도록 시스템을 구성하면 된다.
프로듀서 Retry전략은 기회가 된다면 공부해보는 것으로 ..
728x90
'WebServer > Spring' 카테고리의 다른 글
[Spring] @RequestBody 와 @ResponseBody (1) | 2023.09.25 |
---|---|
[Spring] Spring 기반의 파일업로드(File Upload) (0) | 2023.09.19 |
[Spring] MVC 네임스페이스 태그 관련 (0) | 2023.09.18 |
[Spring] 스프링의 포워드(forward)와 리다이렉트(redirect) + RedirectAttributes (0) | 2023.09.17 |
[Spring] 스프링 MVC의 Controller (0) | 2023.09.17 |