Kafka Retry & Dead Letter Queue
Kafka Retry & Dead Letter Queue
Retry & DLQ
Kafka Retry
- Consumer가 message를 처리하던 중 오류가 발생하면 해당 Message를 다시 Polling하여 처리해야 한다.
- 이를 Retry라고 하며, 간단하게 Kafka 설정으로 동작할 수 있다.
- Inventory 마이크로서비스 application.yml 의 cloud.stream.bindings.event-in 하위의 설정을 주석해제하고 저장한다.
bindings:
event-in:
group: product
destination: kafkatest
contentType: application/json
consumer:
max-attempts: 3
back-off-initial-interval: 1000
back-off-max-interval: 1000
back-off-multiplier: 1.0
defaultRetryable: false
- 3번의 retry를 수행하는데 Retry시 백오프 초기간격이 1초, 이후 최대 1초 간격으로 retry를 실행한다.
- Inventory 서비스의 PolicyHandler.java에서 아래 오류 발생 코드를 주입한다:
@StreamListener(KafkaProcessor.INPUT)
public void wheneverOrderPlaced_DecreaseStock(@Payload OrderPlaced orderPlaced) {
...
throw new RuntimeException(); //always fail
}
- Order와 Product 마이크로서비스를 기동한다.
cd order
mvn spring-boot:run
cd inventory
mvn spring-boot:run
- 재고를 등록한다
http :8082/inventories id=1 stock=1000
- Order 서비스에 포스팅하여 Kafka Event를 발행한다.
http :8081/orders productId=1 qty=3
- Inventory에서 Message를 subscribe하여 내용을 출력한다.
- throw new RuntimeException에 의해 Kafka retry가 수행되는지 Console의 log로 확인한다.
- 허나,
- 해당 메시지는 처리될 수 없으므로 파티션 Lag가 항상 잔존하게 된다.
./kafka-consumer-groups --bootstrap-server localhost:9092 --group inventory --describe
- 이는 별도의 Topic에 저장한 후 백오피스에서 처리해야 할 대상인 것이다.
Kafka Dead Letter Queue(DLQ)
- Kafka에서 retry를 통해서도 처리하지 못하는 message를 Posion pill이라고 한다.
- Kafka에서 Posion pill은 별도의 메시지 저장소인 DLQ로 보내지게 된다.
- DLQ는 또 하나의 topic이며 Consumer에서 정상적으로 처리되지 못한 message들이 쌓여있다.
- DLQ를 설정하기 위해서 아래와 같이 Inventory의 application.yml를 변경한다.
- cloud.stream.kafka 아래에 있는 아래 설정을 주석해제 한다.
bindings:
event-in:
consumer:
enableDlq: true
dlqName: dlq-kafkatest
dlqPartitions: 1
- 저장 후 Inventory 마이크로서비스를 재기동한다.
서비스가 기동되면서 Retry를 반복하게 되고, 그래도 처리하지 못한 메시지를 DLQ로 보내는 것이 Console에 확인된다. Sent to DLQ a message with key='null' and payload='{123, 34, 101, 118, 101, 110, 116, 84, 121, 112, 1...' received from 0
- 설정에서 지정한 DLQ 토픽이 생성되었는지 확인한다.
cd kafka
docker-compose exec -it kafka /bin/bash
cd /bin
./kafka-topics --bootstrap-server http://localhost:9092 --list
Kafka DLQ Test
- Order 서비스에 포스팅하여 Kafka Event를 추가 발행한다.
http POST :8081/orders productId=1 qty=1
- Product에서 retry 3번 시도 후, 자동으로 DLQ로 보낸다.
- 아래 명령어를 통해 DLQ에 해당 message가 쌓였는지 확인한다.
./kafka-console-consumer --bootstrap-server http://localhost:9092 --topic dlq-kafkatest --from-beginning
- 커밋모드가 자동일때 Dlq에 처리되지 않은 메세지를 보낸 후, 자동으로 Offset을 증가시켜 Lag가 쌓이지 않게 된다.
./kafka-consumer-groups --bootstrap-server localhost:9092 --group inventory --describe