Dead-Letter Queue(DLQ)

차분한열정·2022년 4월 30일
1

AWS SQS

목록 보기
2/3

1. 개요

Dead-Letter Queue는 하나 이상의 Source Queue가 성공적으로 컨슘되지 못한 메시지들을 재전송하기 위해 사용하는 별도의 큐이다. DLQ에 쌓인 메시지들을 보면 왜 이 메시지들이 컨슈머에 의해 처리되지 못했는지를 알 수 있다. 만약 컨슈머 어플리케이션의 버그를 찾아서 수정했다면 AWS 콘솔 화면에서 redrive를 수행함으로써 해당 메시지들을 다시 소스 큐에 집어넣을 수 있다. SQS는 DLQ를 자동으로 생성해주지 않기 때문에 그것을 사용하려면 미리 생성해두어야 한다. FIFO 큐의 DLQ는 그것도 FIFO 큐여야 한다. 마찬가지로 Standard 큐의 DLQ는 Standard 큐여야 한다.

2. 설정

소스 큐에서 Maximum receives 값을 설정하면 이 횟수 안에 성공적으로 컨슘되지 못한 메시지들이 DLQ로 전송된다. maxReceiveCount는 정확히 말해서 컨슈머가 메시지를 컨슘하고자 시도했지만 DLQ로 메시지가 옮겨지기 전까지 큐에서 삭제하지 못했던 시도의 건수들을 의미한다. 이 값은 너무 낮게 설정하면 컨슈머에게 너무 가혹하고, 복원력이 약한 시스템을 만들기 때문에 적절히 높은 값을 설정하는 게 좋다.

DLQ에 메시지가 쌓인다면, 컨슈머 어플리케이션을 디버깅해서 왜 컨슘이 실패했는지를 분석하고 패치한 다음, DLQ redrive를 하면 다시 메시지들을 소스 큐로 편하게 클릭 한 방으로 전송할 수 있다.

3. ApproximateAgeOfOldestMessage 메트릭

해당 큐에서 삭제되지 않고 가장 오래 남아있는 메시지의 대략적인 존재 기간이다. 주의할 점은 DLQ에 메시지가 넘어가면 DLQ 입장에서 이 메트릭의 기준은 메시지의 최초 전송 시각이 아닌 해당 DLQ로 이동된 시각을 기준으로 한다. 만약 소스 큐에서 1일 머무른 메시지가 DLQ로 이동했고 해당 DLQ의 retention period가 4일이었다면 메시지는 DLQ에서 3일 후에 삭제되고 해당 메시지의 ApproximateAgeOfOldestMessage 값은 3일이다. 따라서 DLQ의 retention period는 항상 소스 큐의 retention period보다 길게 설정해야 한다.

4. 각 타입의 큐가 메시지 컨슘 실패를 처리하는 방식

(1) Standard 큐

Standard 큐는 retention period가 끝나기 전까지는 계속 재시도를 한다. 하지만 이런 식으로 하면 계속 컨슈머에 의해 처리되지 못한 메시지들이 쌓이게 되어 하드웨어에 무리를 줘서 정상적인 메시지 처리에도 영향을 줄 수 있기 때문에 보통 몇 번의 시도 후에는 DLQ로 빠지도록 설정해주는 게 좋다(maxReceiveCount 값 설정?)

(2) FIFO 큐

FIFO 큐는 message group으로부터 오는 메시지들을 순서대로, 정확히 한번 처리하기 때문에 문제가 있는 메시지가 있는 message group은 계속 사용불가 상태가 된다. 하지만 여전히 다른 message group으로부터는 메시지를 컨슘할 수 있다. 만약 메시지 순서가 정말 중요한 상황이라면 FIFO 큐에서 DLQ를 쓰면 안 된다.(DLQ를 쓰는 자체가 순서를 깨뜨리는 것이므로?)

5. redrive

컨슈커의 로직 문제를 해결하고 DLQ에 있던 메시지들을 다시 소스큐로 보내는 것을 redrive라고 한다. redrive된 메시지들은 아예 새로운 메시지로 인식되고 새로운 messageid, enqueueTime, retention period를 적용받게 된다. redrive를 하면 보통 원래의 소스 큐로 메시지를 보내는 것이 일반적이지만 다른 큐를 설정해서 redrive를 할 수도 있다. 그리고 redrive를 할 때 그 속도 또한 정할 수 있다.
redrive 관련해서 주의해야할 점은
(1) AWS 콘솔에서 메시지를 직접 보는 행위 자체를 maxReceiveCount(?) 수로 포함시키기 때문에 너무 자주 보면 해당 메시지가 DLQ로 이동해버릴 수 있다. 따라서 Maximum Receives 값을 올리거나 콘솔에서는 메시지를 확인하지 말아야 한다.
(2) DLQ로 메시지를 직접 보내면 그것이 NumberOfMessagesSent 지표에 잡히지만 만약 소스큐에서의 처리 실패로 DLQ로 들어가면 해당 지표에 잡히지 않는다. 따라서 DLQ의 NumberOfMessageSent 지표와 NumberOfMessageReceived 지표 값은 동일하지 않을 수 있다.

6. 주의점

SQS는 분산 시스템이기 때문에 컨슈머가 ReceiveMessage API 메소드 콜을 했을 때 성공적으로 리턴을 받았고 SQS는 메시지를 전달한 것으로 표시했지만 정작 컨슈머는 메시지를 받지 못하는 경우도 있을 수 있다. 이러한 경우에 다시 메시지를 전달하려는 시도가 발생하지 않기 때문에 DLQ에 관한 maximum receives 설정을 1로 하는 것은 권장되지 않는다.

profile
성장의 기쁨

0개의 댓글