Amazon Web Services 한국 블로그

새로운 기능 – Amazon SQS 스탠다드 대기열을 위한 향상된 배달 못한 편지 대기열(DLQ) 관리 환경

수십만 명의 고객이 Amazon Simple Queue Service(SQS)를 사용하여 마이크로서비스, 분산 시스템 및 서버리스 앱을 분리하고 확장하는 메시지 기반 애플리케이션을 구축합니다. 대기열 소비자가 메시지를 성공적으로 처리할 수 없는 경우 배달 못한 편지 대기열(DLQ)에 이를 저장하도록 SQS를 구성할 수 있습니다.

소프트웨어 개발자 또는 아키텍트는 DLQ에서 사용되지 않은 메시지를 검사하고 검토하여 처리할 수 없는 이유를 파악하고, 패턴을 식별하고, 코드 오류를 해결하고, 궁극적으로 이러한 메시지를 원래 대기열에서 다시 처리해야 합니다. 이러한 사용되지 않은 메시지의 수명 주기는 수동적이고 시간이 많이 소요되는 오류 처리 워크플로의 일부입니다.

사용되지 않은 메시지를 DLQ에서 소스 대기열로 쉽게 리드라이브할 수 있는 SQS 표준 대기열에 대한 새로운 향상된 DLQ 관리 환경이 오늘 정식 출시되었습니다.

이 새로운 기능은 SQS 콘솔에서 사용할 수 있으며 처리 중인 오류의 식별과 해결로 구성된 오류 처리 워크플로의 중요한 단계에 집중하는 데 도움이 됩니다. 이 새로운 개발 환경으로 사용되지 않은 메시지 샘플을 쉽게 검사하고 클릭 한 번으로 사용자 정의 코드를 작성, 유지 관리 및 보호하지 않고도 원래 대기열로 메시지를 되돌릴 수 있습니다. 이 새로운 환경은 또한 메시지를 일괄적으로 리드라이브하여 전체 비용을 절감합니다.

DLQ 및 Lambda 프로세서 설정
DLQ 설정에 이미 익숙하다면 설정을 건너뛰고 새로운 DLQ 리드라이브 환경으로 넘어가세요.

먼저 소스 대기열과 배달 못한 편지 대기열이라는 2개의 대기열을 생성합니다.

소스 대기열을 편집하고 배달 못한 편지 대기열(Dead-letter queue) 섹션을 구성합니다. 여기서는 DLQ를 선택하고 최대 수신(Maximum receives)을 구성합니다. 최대 수신은 메시지가 DLQ로 전송되기 전에 다시 처리되는 횟수입니다. 이 데모에서는 1로 설정했습니다. 즉, 실패한 모든 메시지는 즉시 DLQ로 이동합니다. 실제 환경에서는 요구 사항 및 애플리케이션과 관련하여 오류가 의미하는 바에 따라 더 높은 숫자를 설정할 수 있습니다.

또한 DLQ를 편집하여 소스 대기열만 이 DLQ를 사용할 수 있도록 합니다. 이 구성은 선택 사항입니다. 이 리드라이브 허용 정책(Redrive allow policy)이 사용 중지되면 SQS 대기열에서 이 DLQ를 사용할 수 있습니다. 여러 대기열에 단일 DLQ를 재사용하려는 경우가 있습니다. 그러나 일반적으로 비용에 영향을 주지 않고 리드라이브 단계를 간소화하기 위해 소스 대기열당 독립적인 DLQ를 설정하는 것이 모범 사례로 간주됩니다. 대기열 수가 아닌 API 호출 수에 따라 요금이 부과됩니다.

DLQ가 올바르게 설정되면 프로세서가 필요합니다. AWS Lambda를 사용하여 간단한 메시지 소비자를 구현해 보겠습니다.

Python으로 작성된 Lambda 함수는 수신 메시지 배치를 반복하고 메시지 본문에서 두 값을 가져온 다음 이 두 값의 합계를 인쇄합니다.

import json

def lambda_handler(event, context):
    for record in event['Records']:
        payload = json.loads(record['body'])

        value1 = payload['value1']
        value2 = payload['value2']

        value_sum = value1 + value2
        print("the sum is %s" % value_sum)
        
    return "OK"

위의 코드에서는 각 메시지의 본문에 검증 또는 오류 처리 없이 합산할 수 있는 2개의 정수 값이 포함되어 있다고 가정합니다. 이는 나중에 문제로 이어질 것입니다.

메시지를 처리하기 전에 SQS에서 메시지를 읽고 메시지 트리거를 구성할 수 있는 충분한 권한을 이 Lambda 함수에 부여해야 합니다. IAM 권한의 경우 sqs:ReceiveMessage, sqs:DeleteMessagesqs:GetQueueAttributes를 호출할 수 있는 권한을 부여하는 AWSLambdaSQSQueueExecutionRole이라는 관리형 정책을 사용합니다.

Lambda 콘솔을 사용하여 SQS 트리거를 설정합니다. SQS 콘솔에서도 동일한 결과를 얻을 수 있습니다.

이제 SQS 콘솔에서 소스 대기열에 메시지 전송 및 수신(Send and receive messages)을 사용하여 새 메시지를 처리할 준비가 되었습니다. 메시지 본문에 {"value1": 10, "value2": 5}라고 쓰고 메시지 전송(Send message)을 선택합니다.

Lambda 함수의 CloudWatch Logs를 살펴보면 성공적인 호출이 확인됩니다.

START RequestId: 637888a3-c98b-5c20-8113-d2a74fd9edd1 Version: $LATEST
the sum is 15
END RequestId: 637888a3-c98b-5c20-8113-d2a74fd9edd1
REPORT RequestId: 637888a3-c98b-5c20-8113-d2a74fd9edd1	Duration: 1.31 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 39 MB	Init Duration: 116.90 ms	

DLQ 리드라이브로 문제 해결
이제 다른 생산자가 잘못된 형식으로 메시지를 게시하기 시작하면 어떻게 될까요? {"value1": "10", "value2": 5}를 예로 들어 보겠습니다. 첫 번째 숫자는 문자열이며 이는 프로세서에서 문제가 될 가능성이 큽니다.

실제로 CloudWatch Logs에서 다음과 같은 내용을 찾았습니다.

START RequestId: 542ac2ca-1db3-5575-a1fb-98ce9b30f4b3 Version: $LATEST
[ERROR] TypeError: can only concatenate str (not "int") to str
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 8, in lambda_handler
    value_sum = value1 + value2
END RequestId: 542ac2ca-1db3-5575-a1fb-98ce9b30f4b3
REPORT RequestId: 542ac2ca-1db3-5575-a1fb-98ce9b30f4b3	Duration: 1.69 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 39 MB	

문제가 되는 메시지에서 무엇이 잘못되었는지 파악하기 위해 새로운 SQS 리드라이브 기능을 사용하여 배달 못한 편지 대기열에서 DLQ 리드라이브(DLQ redrive)를 선택합니다.

메시지 폴링(Poll for messages)을 사용하고 DLQ에서 사용되지 않은 모든 메시지를 가져옵니다.

그런 다음 사용되지 않은 메시지를 선택하여 검사합니다.

문제가 확인되어 이 경우를 적절히 처리하기 위해 처리 코드를 업데이트하기로 결정합니다. 이상적인 세계에서 이는 메시지 생산자에서 수정되어야 하는 업스트림 문제입니다. 그러나 해당 시스템을 제어할 수 없고 이 새로운 유형의 메시지를 처리하는 것이 비즈니스에 매우 중요하다고 가정해 보겠습니다.

따라서 다음과 같이 처리 로직을 업데이트합니다.

import json

def lambda_handler(event, context):
    for record in event['Records']:
        payload = json.loads(record['body'])
        value1 = int(payload['value1'])
        value2 = int(payload['value2'])
        value_sum = value1 + value2
        print("the sum is %s" % value_sum)
        # do some more stuff
        
    return "OK"

이제 코드가 사용되지 않은 메시지를 처리할 준비가 되었으므로 DLQ에서 소스 대기열로 새 리드라이브 태스크를 시작합니다.

기본적으로 SQS는 사용되지 않은 메시지를 소스 대기열로 리드라이브합니다. 그러나 다른 대상을 지정하고 사용자 정의 속도를 제공하여 초당 최대 메시지 수를 설정할 수도 있습니다.

콘솔에서 리드라이브 상태를 모니터링하여 리드라이브 작업이 완료될 때까지 기다립니다. 이 새 섹션에는 항상 가장 최근 리드라이브 태스크의 상태가 표시됩니다.

메시지가 소스 대기열로 다시 이동되었으며 Lambda 함수에 의해 성공적으로 처리되었습니다. CloudWatch Logs에서 모든 것이 정상으로 보입니다.

START RequestId: 637888a3-c98b-5c20-8113-d2a74fd9edd1 Version: $LATEST
the sum is 15
END RequestId: 637888a3-c98b-5c20-8113-d2a74fd9edd1
REPORT RequestId: 637888a3-c98b-5c20-8113-d2a74fd9edd1	Duration: 1.31 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 39 MB	Init Duration: 116.90 ms	

추가 비용 없이 바로 사용 가능
이제 새로운 DLQ 리드라이브 환경을 활용하여 추가 비용 없이 개발 및 문제 해결 워크플로를 간소화할 수 있습니다. 이 새로운 콘솔 환경은 SQS를 사용할 수 있는 모든 AWS 리전에서 사용할 수 있으며, 여러분의 의견을 기다리고 있습니다.

Alex