생산자 측면 재시도 구현
메시지 전송 실패 시 복구를 위해 생산자 구성에서 재시도 매개변수를 설정합니다. 비동기 전송과 콜백 핸들러를 활용하며, 멱등성 보장이 필수적입니다.
재전송 설정 예시
Properties config = new Properties();
config.setProperty("bootstrap.servers", "kafka-server:9092");
config.setProperty("key.serializer", StringSerializer.class.getName());
config.setProperty("value.serializer", StringSerializer.class.getName());
config.setProperty("retries", "5"); // 최대 재시도 횟수
config.setProperty("retry.backoff.ms", "1500"); // 재시도 간 지연 시간
config.setProperty("enable.idempotence", "true"); // 멱등성 활성화
KafkaProducer<String, String> sender = new KafkaProducer<>(config);
sender.send(new ProducerRecord<>("data-topic", "event-key", "payload"), (metadata, ex) -> {
if (ex != null) {
if (ex instanceof RetriableException) {
// 복구 가능 오류 처리
} else {
// 치명적 오류 기록
}
}
});
sender.close();
소비자 측면 재시도 전략
오프셋 수동 커밋과 오류 핸들러를 결합하여 구현합니다. 최대 재시도 후 실패 메시지는 데드 레터 큐(DLQ)로 전달됩니다.
Spring Kafka 오류 처리
@Bean
public ConsumerFactory<String, String> consumerFactory() {
Map<String, Object> settings = new HashMap<>();
settings.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka-server:9092");
settings.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); // 자동 커밋 비활성화
return new DefaultKafkaConsumerFactory<>(settings);
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> containerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
DefaultErrorHandler errorHandler = new DefaultErrorHandler(
new DeadLetterPublishingRecoverer(kafkaOperations),
new FixedBackOff(2000, 4) // 2초 간격으로 4회 재시도
);
factory.setCommonErrorHandler(errorHandler);
return factory;
}
@KafkaListener(topics = "data-topic", containerFactory = "containerFactory")
public void process(ConsumerRecord<String, String> record) {
try {
// 비즈니스 로직 실행
} catch (DataProcessingException e) {
throw new RetryableException("처리 재시도 필요", e);
}
}
핵심 고려사항
- 멱등성 보장: 생산자와 소비자 모두 중복 처리 방지 필요
- 데드 레터 큐: 지속적 실패 메시지 격리를 위한 DLQ 활용
- 오류 분류: 일시적 오류(Retriable)와 영구적 오류 구분 처리