Dead Letter (데드 레터)
"Dead Letter"란, 메시지 큐에서 소비자(consumer)에게 전달할 수 없거나 처리 중에 문제가 발생하여 처리가 불가능한 메시지를 말합니다. 보통 메시지를 큐에 전달하려 했으나 여러 번 재시도해도 실패하거나 타임아웃이 발생한 경우, 해당 메시지를 일반 큐에서 제거하고 "Dead Letter Queue (DLQ)"라고 불리는 별도의 큐로 이동시킵니다.
이 과정은 메시지 처리 실패 시 메시지를 손실하지 않고 안전하게 보관하여 나중에 점검하거나 문제를 해결할 수 있도록 하기 위함입니다.
Producer Dead Letter (생산자 데드 레터)
"Producer Dead Letter"는 메시지를 큐로 전송하는 생산자(producer) 측에서 발생한 문제로 인해 큐에 정상적으로 전달되지 못한 메시지를 의미합니다. 프로듀서가 메시지를 발행할 때 네트워크 오류, 메시지 큐 자체의 장애, 또는 메시지 크기 제한 등으로 인해 큐에 메시지가 도달하지 못하는 경우, 이 메시지를 Dead Letter로 처리할 수 있습니다.
이러한 상황에서는 메시지를 버리거나 다른 DLQ에 저장하여 생산자 측 문제를 추적하고 나중에 재전송할 수 있습니다.
Consumer Dead Letter (소비자 데드 레터)
"Consumer Dead Letter"는 소비자가 특정 메시지를 처리하는 도중 실패하거나 오류가 발생하여 메시지를 정상적으로 처리하지 못한 경우를 의미합니다. 일반적으로 메시지 큐는 메시지가 소비자에게 여러 번 재시도된 후에도 실패하는 경우, 해당 메시지를 "Dead Letter Queue"로 이동시킵니다.
이러한 "Consumer Dead Letter"는 일반적으로 소비자가 처리할 수 없는 메시지(잘못된 형식, 누락된 데이터, 또는 예상치 못한 내용)를 담고 있어, 이를 DLQ에 넣고 이후 개발자나 운영자가 수동으로 처리하거나 점검할 수 있습니다.
Kafka에서 Dead Letter Queue 설정 방법
Kafka 자체에는 기본적으로 DLQ 기능이 없지만, 컨슈머 애플리케이션 쪽에서 구현 가능하다.
- DLQ 토픽 생성:
- Kafka에 별도의 DLQ 토픽을 생성.
- 예를 들어, 원본 토픽이 my-topic이라면, DLQ 토픽은 my-topic-dlq와 같은 방식으로 이름을 지정
- 컨슈머 예외 처리 및 DLQ 전송:
- 메시지 처리 중 오류가 발생할 때 예외 처리를 통해 실패한 메시지를 DLQ 토픽으로 전송
- 예를 들어, 메시지 처리 로직에서 예외가 발생하면 KafkaProducer를 사용하여 DLQ 토픽에 메시지를 전송
public void processMessage(String message) {
try {
// 메시지 처리 로직
} catch (Exception e) {
// DLQ로 메시지 전송
ProducerRecord<String, String> record = new ProducerRecord<>("my-topic-dlq", message);
kafkaProducer.send(record);
log.error("Failed to process message, sent to DLQ", e);
}
}
3. Kafka Connect 사용:
Kafka Connect는 Kafka와 다른 시스템 간에 데이터를 쉽게 전송(스트리밍)할 수 있게 해주는 프레임워크이다. 이를 통해 다양한 데이터베이스, 파일 시스템, 클라우드 서비스, 로그 시스템 등과 Kafka를 통합할 수 있음.
- Source Connectors: 외부 시스템에서 Kafka로 데이터를 전송하는 커넥터
- 예를 들어, 데이터베이스에서 데이터를 Kafka로 보내거나, 로그 파일에서 Kafka로 스트리밍
- Sink Connectors: Kafka에서 외부 시스템으로 데이터를 전송하는 커넥터
- 예를 들어, Kafka에서 받은 데이터를 데이터베이스나 HDFS, Elasticsearch 등으로 보냄
Kafka Connect는 standalone mode와 distributed mode로 실행할 수 있으며, connector configuration을 통해 여러 외부 시스템과의 통합을 자동화함.
Dead Letter Queue는 메시지 처리 중 오류가 발생한 메시지를 별도의 큐에 저장해두고, 후속 처리를 통해 문제를 해결할 수 있게 해주는 시스템이다. Kafka Connect에서 DLQ는 주로 메시지 처리 실패 시 데이터를 안전하게 보관하고, 문제가 해결된 후 재처리를 할 수 있도록 도와줌.
Kafka Connect DLQ 기능은 주로 dead-letter-policy와 관련된 설정을 통해 구성된다. 예를 들어, 메시지 처리에 실패할 경우 해당 메시지를 DLQ로 이동시켜 추가적인 검토 및 처리가 가능하게 함.
- Kafka Connect 프레임워크와 Dead Letter Queue 기능을 지원하는 커넥터를 사용하고(ex. Debezium) 커넥터 설정에서 errors.deadletterqueue.topic.name을 지정하여 특정 토픽을 DLQ로 사용 가능.
RabbitMQ에서 Dead Letter Queue 설정 방법
RabbitMQ는 기본적으로 DLQ 기능을 지원함
- DLQ용 큐 생성:
- Dead Letter를 위한 별도의 큐를 생성합니다.
- 예를 들어 my-queue-dlq라는 이름의 큐를 생성
- Dead Letter Exchange 생성:
- x-dead-letter-exchange와 같은 DLX(Dead Letter Exchange)를 생성하여 메시지를 전송할 곳을 설정. DLX는 메시지 처리 실패 시, 또는 메시지가 만료된 경우 메시지를 다른 큐로 라우팅하는 역할을 함.
- 원본 큐 설정에 DLX 추가:
- 원본 큐를 설정할 때 x-dead-letter-exchange 속성을 추가하여 DLX를 지정.
- 예를 들어, my-queue라는 원본 큐가 있을 때 해당 큐의 메시지가 실패하면 DLX를 통해 DLQ 큐로 메시지가 전달
- 메시지 만료 시간(x-message-ttl)을 설정하여 특정 시간이 지나면 DLQ로 이동하도록 설정 가능
// Dead Letter Exchange 및 Queue 설정
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", "my-dlx"); // 익스채인지 설정
args.put("x-dead-letter-routing-key", "my-queue-dlkey"); // 라우팅 키 설정
// 메시지 만료 시간 설정 (TTL)
args.put("x-message-ttl", 60000); // 60초 후 메시지 만료
// 원본 큐 선언
channel.queueDeclare("my-queue", true, false, false, args); // 큐에 엮음
// Dead Letter Queue 선언
channel.queueDeclare("my-queue-dlq", true, false, false, null);
channel.queueBind("my-queue-dlq", "my-dlx", "my-queue-dlkey"); // 큐, 익스채인지, 라우팅 키
- "my-queue"라는 이름의 원본 큐를 선언
- args는 위에서 설정한 Dead Letter Exchange 및 라우팅 키를 포함하는 속성. 이 속성에 따라 메시지가 만료되거나 처리 실패 시 DLX를 통해 my-queue-dlq로 전달됨
- "my-queue-dlq"라는 이름의 Dead Letter Queue(DLQ)를 선언. 이 큐는 Dead Letter로 전달된 메시지를 저장하는 역할을 함
- channel.queueBind는 "my-dlx" DLX와 "my-queue-dlq" 큐를 지정한 라우팅 키 "my-queue-dlkey"를 통해 연결하여, DLX에서 발생한 Dead Letter 메시지가 이 큐에 전달되도록 설정
Dead Letter가 Dead Letter Queue 에 쌓이면 그 다음 단계는?
1. Dead Letter 모니터링 및 알림
- DLQ에 메시지가 쌓이면 이를 모니터링하고, 일정 수 이상이 되거나 특정 조건을 만족하면 자동으로 알림이 오도록 설정
- 알림 시스템을 통해 개발자나 운영팀이 문제를 인식하고 원인을 분석
2. 원인 분석
- DLQ에 쌓인 메시지를 검토하여 처리 실패 원인을 파악.
- 메시지 형식 오류 또는 잘못된 데이터
- 처리 로직의 버그 또는 예외
- 메시지 크기 초과나 타임아웃
- 로그를 통해 오류 상황을 구체적으로 분석하거나, DLQ에 쌓인 메시지 내용 자체를 검토하여 어떤 부분에서 문제가 발생했는지 확인
3. 수동 재처리 또는 자동 재처리
- 문제가 해결된 후 DLQ의 메시지를 다시 원래 큐에 넣어 재처리 가능. 이를 자동화할 수도 있지만, 데이터 일관성을 위해 보통 수동으로 처리
- 자동화 시 재처리 시나리오를 신중하게 정의해야 하며, 동일한 실패가 발생하지 않도록 로직을 수정
'architecture > micro service' 카테고리의 다른 글
[캐시] 캐시 관련 문제들과 캐시웜업 (0) | 2024.11.17 |
---|---|
E2E(end to end) 테스트 (0) | 2024.11.13 |
대용량 데이터 처리 고민 (1) | 2024.11.10 |
transaction outbox pattern + polling publisher pattern (0) | 2024.11.07 |
2PC vs 2PL (1) | 2024.11.06 |