Kafka 장애 재시도 전략 - KimGyuBek/Threadly GitHub Wiki
Threadly는 메인 서비스와 알림 서비스가 분리된 MSA 구조를 가지고 있으며, 서비스 간 비동기 통신에 Kafka를 사용한다.
이 과정에서 이벤트 발신(Producer)과 수신(Consumer) 단계에서 발생할 수 있는 장애에 대응하기 위해 Resilience4j와 Spring Cloud Stream 기반 재시도 전략을 적용했다.
재시도 과정에서 발생하는 성공/실패 정보는 전부 메트릭으로 수집해 Prometheus · Grafana로 모니터링한다.
- 네트워크 지연, 일시적인 브로커 장애 등은 재시도를 통해 자동 복구하는 것을 기본 전략으로 한다.
- 프로듀서 측은
Resilience4j, 컨슈머 측은Spring Cloud Stream의 재시도 기능을 사용해 구현했다.
- 재시도 횟수, 최종 실패 건수, 성공 건수 등을 전부 메트릭으로 기록한다.
-
Prometheus·Grafana대시보드를 통해 시간대별 재시도/실패 추이를 확인할 수 있도록 구성한다.
Resilience4j를 이용해Kafka메시지 발행 단계에 재시도 정책을 적용한다.- 재시도 횟수, 성공/실패 여부는
Micrometer메트릭으로 기록하고,Prometheus·Grafana대시보드에서 모니터링한다.
Spring Cloud Stream의 재시도 기능을 이용해Kafka메시지 소비 단계에 재시도 정책을 적용한다.- 메시지 헤더의
deliveryAttempt값을 이용해 재시도 횟수를 판단하고, 성공/최종 실패 건수를 메트릭으로 기록해 모니터링에 활용한다.
Threadly에서 Kafka로 전달하는 이벤트는 핵심 도메인 데이터를 변경하는 명령이 아니라, 알림/메일 발송을 위한 부가적인 기능이다.
- 알림이 일부 누락되더라도 데이터 정합성이 깨지지는 않는다.
- 반대로, 알림 처리 장애 때문에 메인 트랜잭션이 반복 롤백되거나 시스템 부하가 증가하는 것은 피해야 한다.
이 특성을 바탕으로 다음과 같이 설계했다.
-
Producer·Consumer양쪽에 재시도 정책을 적용해, 일시적 장애는 재시도로 최대한 흡수한다. - 설정된 재시도 횟수(예: 3회)를 초과해도 실패하는 경우, 이는 구성, 인프라, 외부 시스템 등 환경 레벨의 구조적인 문제로 판단한다.
Producer·Consumer재시도 정책에는 지수 백오프(Exponential Backoff)를 적용해, 실패가 반복될수록 재시도 간격을 늘려 일시적인 장애가 회복될 수 있는 시간을 확보하고, 불필요하게 시스템을 더 압박하지 않도록 했다.- 이처럼 제한된 횟수·간격 조정까지 포함한 재시도 전략으로도 복구되지 않는 경우, 단순 자동 재시도로는 해결이 어렵다고 보고, 최종 실패 메트릭과 로그를 통해 운영자가 원인을 분석하고 대응하는 흐름을 택했다.
Consumer 측에서 재시도 초과 메시지를 DLQ(Dead Letter Queue)로 보내고, 별도 배치나 도구로 재처리하는 방식도 고려했지만 현재 단계에서는 적용하지 않았다.
- 프로젝트 규모와 메시지 중요도에 비해 DLQ 운영 복잡도가 크다고 판단했다.
- 알림은 부가 기능이므로, 일정 수준의 알림 누락은 시스템 안정성을 위한 트레이드오프로 허용하기로 했다.
- 이미 재시도 정책과 지수 백오프를 통해 일시적인 장애는 최대한 재시도 단계에서 흡수하고 있기 때문에, 그 이후에도 남는 실패 건은 DLQ에 쌓아 반복 처리하기보다는 환경·구성·외부 시스템을 포함한 구조적 원인을 분석하고 개선해야 할 대상으로 본다.
- 대신, 재시도·최종 실패를 전부 메트릭과 로그로 남겨, 장애 징후를 빠르게 인지하고 수동으로 대응할 수 있는 구조를 우선 도입했다.