Dead Letter Queue (DLQ)란 무엇인가?
DLQ는 정상적으로 처리되지 못한 메시지들을 저장하는 특별한 큐입니다.(카프카에서는 단순한 토픽입니다) DLQ의 본질은 특정 횟수 이상의 재시도 후에도 메시지 처리가 실패하거나 복구할 수 없는 오류가 발생했을 때 해당 메시지를 DLQ로 이동시켜 시스템이 계속 정상적으로 작동하면서 메시지를 손실하지 않고, 추후에 메시지를 검토하거나 재처리할 수 있도록 보장하는 방법입니다.
DLQ가 필요한 이유
기존에는 isPublish라는 컬럼을 이벤트 소싱 패턴에 적용시켜놔서 이벤트 발송 실패시 시스템 내부적으로 처리하고 있었습니다. 처리량과 실패율이 낮아 별도의 DLQ가 필요없어보였지만 솔루션 연동과 고객사들이 증가함에 따라 미리 예방하는 차원에서 현재 시점에서 미리 적용하는 것이 옳다고 판단했습니다.
또한 현재는 큰 이슈가 없는 케이스가 적은 이슈라도 프로젝트를 진행하며 실시간 배송 트래킹과 주문 처리시 데이터 손실이 되지 않는 것이 매우 중요하다고 생각했습니다. 데이터가 손실되거나 실시간으로 업데이트 되지 않을 경우 고객과의 신뢰도가 저하될 수 있다고 판단했습니다.
DLQ를 구축함으로서 메시지를 재시도하거나 분석할 수 있어 유지보수에 있어도 명확한 분석이 가능해졌습니다.
이렇게 구축된 DLQ에 쌓인 메시지를 분석하면 반복적으로 발생하는 문제를 식별하고 시스템을 개선할 수 있습니다.
Dead Letter Queue 구현 방법
1. 메시지 처리 로직
public void processMessage(Message message) {
try { // 메시지 처리 비즈니스 로직
processBusinessLogic(message);
}
catch (Exception e) {
handleFailedMessage(message, e);
}
}
이 코드에서 processBusinessLogic이 실패할 경우 메시지는 실패 처리기로 전달됩니다.
2. 실패한 메시지 처리
public void handleFailedMessage(Message message, Exception e) {
if (message.getRetryCount() < MAX_RETRIES) {
retryMessage(message);
} else {
sendToDeadLetterQueue(message, e);
}
}
위의 로직으로 메시지는 최대 재시도 횟수까지 재시도되며, 그 후에는 DLQ에 저장됩니다. 저는 10번을 재시도 하기로 결정했습니다.
3. DLQ로 메시지 전송
public void sendToDeadLetterQueue(Message message, Exception e) {
DLQMessage dlqMessage = new DLQMessage(message.getId(), message.getPayload(), e.getMessage(), LocalDateTime.now() );
dlqQueue.add(dlqMessage);
}
실패한 메시지와 오류 세부 정보와 함께 어떤 내용을 담고 있는지 또 어떤 에러 메시지가 발생했는지 등을 DLQ에 저장했습니다.
DLQ 적용시 유의할 점
- 재시도 정책 설정
- 적절한 최대 재시도 횟수 설정
- 지수 백오프 적용으로 시스템 부하 방지
- 재시도 간격 설정 시 비즈니스 요구사항 고려
- 모니터링 체계 구축
- DLQ 메시지 수 모니터링
- 실패 원인 분석을 위한 로깅 강화
- 이슈 발생시 slack에 알림 발송
DLQ를 적용하는건 유의미한 결과를 낼 수 있었지만 만능은 아니라고 생각했습니다. 궁극적으로는 DLQ에 들어온 이벤트는 개발자가 직접 확인해 에러의 원인을 파악해 이슈를 해결해야하므로 에러 발생시 슬랙과 모니터링 도구와 연동해 즉각적으로 문제 상황을 파악할 수 있도록 구축했습니다.
결론
기존에는 고객 문의나 운영 부서의 검증 중에 데이터 정합성 문제가 발견되는 경우가 간혹 있었습니다. 실시간 배송 추적 시스템에 DLQ 도입 후에는 재시도 로직을 통해 자동으로 오류를 처리하고 실패한 이벤트는 DLQ에 로그로 기록되며 이슈 발생시 슬랙에 전송되어 즉각적인 대응이 가능해졌습니다. 이를 통해 유지보수의 효율성을 높이고 더욱 안정적인 서비스를 구축할 수 있었습니다.
DLQ 도입을 통해 얻은 교훈
- 장애는 피할 수 없지만, 관리할 수 있다
- 안정성과 신뢰성은 시스템의 기본
- 모니터링과 로깅의 중요성
- 점진적인 시스템 개선의 가치
MSA 프로젝트를 운영하다 보면 도메인 간 데이터 정합성 유지와 이슈 발생 시 원인을 파악하는 일이 중요합니다. 복잡한 시스템일수록 로그 관리와 공통 설정의 중요하다고 느꼈습니다.
DLQ는 MSA 간 실시간 이벤트 처리에서 오류가 발생했을 때 효과적으로 대처할 수 있는 방법 중 하나로 이슈가 발생했을 때, 얼마나 자주 발생하는지, 원인은 무엇인지, 가장 적절한 대처 방법은 무엇인지 고민함으로써 최선의 해결책을 찾을 수 있다고 생각합니다.
'Spring' 카테고리의 다른 글
undertow VS tomcat 비동기 처리(Feat.이벤트루프란?) (1) | 2024.11.09 |
---|---|
MSA 환경에서의 @JsonProperty 활용 (1) | 2024.10.13 |
JsonTypeInfo와 함께하는 다형성 구현 (0) | 2024.05.11 |
BlockHound - Blocking 코드 존재여부 확인 (0) | 2023.12.24 |
Spring Security 주요 아키텍처 이해( Part 2) (0) | 2022.05.30 |