카프카 이벤트를 컨슈밍할 때, 오류가 발생하는 경우 이를 재시도하는 방안에 대해서 정리해보고자 한다.
컨슈밍에 실패한 경우, 재시도 방법을 크게 Blocking과 Non-Blocking 으로 나눠볼 수 있다.
여기서 Blocking은 현재 실행중이 프로세스에서 처리를 재시도하는 것을 말한다. Non-Blocking은 큐 시스템을 활용하여, 비동기로 다시 재시도 처리하는 것을 말한다.
(1) Blocking
대안
a. spring-retry를 사용하여, 원하는 횟수만큼 처리를 재시도하기
@Service
public interface PaymentService {
@Retryable(value = TimeoutException.class, maxAttempts = 2, backoff = @Backoff(delay = 100))
void complete(long orderId) throws SQLException;
}
장점
단순하고, 예측하기 쉬운 코드이다.
단점
- 지속적인 오류를 발생하는 특정한 케이스가 프로세스를 계속 점유할 수 있다.
- 일정한 텀을 두고 재시도를 하고 싶은 경우, 한 케이스가 프로세스를 더 오랜시간 점유할 수 있다.
(2) Non-Blocking
대안
a. kafka retry topic 사용하기
@Component
@KafkaListener(id = "order-group", topics = "payment-complete")
public class PaymentKafkaListener {
@KafkaHandler
@RetryableTopic(
backoff = @Backoff(value = 3000L),
attempts = "5",
autoCreateTopics = "false",
include = TimeoutException.class, exclude = NullPointerException.class)
public void handlePayment(PaymentCompleteEvent event) {
System.out.println("Event received: " + event);
}
}
장점
- 카프카로 Non-blocking 처리가 가능하다.
- 비동기로 재시도 처리를 구현하기 수월하다.
단점
1. RetryTopic을 사용하면, 재시도 횟수만큼 Retry Topic이 생겨난다. 이러한 Topic들을 관리해야한다.
ex. payment-complete-retry-0, payment-complete-retry-1, payment-complete-retry-2
2. Retry Topic에서 다시 에러가 발생하는 경우, 예외처리가 까다롭다.
Retry Topic에서 다시 Retry Topic을 만들어서, 무한 Retry에 빠지는 헬을 경험할 수 있다.
b. kafka dlt 토픽을 만들고, 재처리하는 consumer를 구현하기
장점
- 카프카로 Non-blocking 처리가 가능하다.
- dlt만 처리하면 되기 때문에 처리 구조가 단순하다.
단점
- dlt 처리용 consumer를 관리해야한다.
- 재시도를 1회만하기 때문에, 재시도 횟수를 제어하기 위한 다른 방안이 필요하다.
c. 컨슈밍에 실패하는 경우, 새로운 카프카 이벤트를 발행하기
장점
- 카프카로 Non-blocking 처리가 가능하다.
- 단순하다.
단점
- 최대 재시도 횟수를 DB에 저장해두어야한다.
나의 결정!
나는 이중 마지막 안을 결정했다.
처음에는 있어빌리티 주도 개발을 위해 Retry Topic과 dlt Topic을 사용하는 것을 고려해봤다.
그런데 잘 모르는 상태에서 구현을 하려다보니, 코드가 예상대로 동작하지 않았고, 쉽게 원하는 바를 이루기 어려웠다.
그래서 Non-Blocking으로 구현하면서, 최대한 단순하게 짤 수 있는 방법을 선택했다.
Simple is Best!!
'소프트웨어-이야기 > 프로그래밍 언어와 프레임워크' 카테고리의 다른 글
ChatGPT에게 IfNecessary, IfNeeded 함수명의 차이를 물어보다. (0) | 2023.03.04 |
---|---|
디자인패턴 - Strategy Design Pattern (0) | 2023.02.11 |
Enum 활용하기 (0) | 2023.01.07 |
Lombok 기본 생성자와 Getter/Builder 어노테이션 (1) | 2022.11.12 |
JPA Entity와 Lombok Annotation (1) | 2022.10.29 |