Lambda에서 SQS 이벤트 소스 오류 처리하기

Lambda에서 SQS 이벤트 소스 오류 처리하기 (Handling errors for an SQS event source in Lambda)

SQS 이벤트 소스와 관련된 오류를 처리하기 위해 Lambda는 백오프(backoff) 전략이 있는 재시도 전략을 자동으로 사용해요. SQS 이벤트 소스 매핑이 부분 배치 응답(partial batch responses)을 반환하도록 구성해서 오류 처리 동작을 사용자화할 수도 있어요.

실패한 호출의 백오프 전략

호출이 실패하면 Lambda는 백오프 전략을 구현하면서 호출 재시도를 시도해요. 백오프 전략은 실패가 함수 코드의 오류 때문인지 스로틀링 때문인지에 따라 조금 달라져요.

  • 함수 코드가 오류를 일으켰다면 Lambda는 호출 처리를 중지하고 재시도하지 않아요. 그 사이 Lambda는 점진적으로 백오프해서 Amazon SQS 이벤트 소스 매핑에 할당된 동시성을 줄여요. 큐의 가시성 타임아웃(visibility timeout)이 끝나면 메시지가 큐에 다시 나타나요.
  • 호출이 스로틀링 때문에 실패했다면 Lambda는 Amazon SQS 이벤트 소스 매핑에 할당된 동시성을 줄여 재시도를 점진적으로 백오프해요. Lambda는 메시지의 타임스탬프가 큐의 가시성 타임아웃을 초과할 때까지 메시지를 계속 재시도하고, 그 시점에 메시지를 버려요.

부분 배치 응답 구현하기

Lambda 함수가 배치를 처리하는 동안 오류를 만나면, 기본적으로 그 배치의 모든 메시지(Lambda가 성공적으로 처리한 메시지 포함)가 큐에서 다시 보이게 돼요. 그 결과 함수가 같은 메시지를 여러 번 처리하게 될 수 있어요.

실패한 배치에서 이미 성공적으로 처리된 메시지의 재처리를 피하려면 이벤트 소스 매핑을 구성해서 실패한 메시지만 다시 보이게 할 수 있어요. 이를 부분 배치 응답(partial batch response)이라고 해요. 부분 배치 응답을 켜려면 이벤트 소스 매핑을 구성할 때 FunctionResponseTypes 작업에 ReportBatchItemFailures를 지정해요. 이 설정을 쓰면 함수가 부분 성공을 반환할 수 있어서 레코드에 대한 불필요한 재시도 횟수를 줄일 수 있어요.

참고 Powertools for AWS Lambda의 Batch Processor 유틸리티가 부분 배치 응답 로직을 모두 자동으로 처리해요. 이 유틸리티는 배치 처리 패턴 구현을 단순화하고 배치 항목 실패를 올바르게 처리하는 데 필요한 커스텀 코드를 줄여줘요. Python, Java, TypeScript, .NET에서 사용할 수 있어요.

ReportBatchItemFailures이 활성화되면 Lambda는 함수 호출이 실패해도 메시지 폴링을 줄이지 않아요. 일부 메시지가 실패할 것으로 예상되고, 그 실패가 메시지 처리 속도에 영향을 주길 원하지 않는다면 ReportBatchItemFailures를 사용하세요.

참고 부분 배치 응답을 사용할 때 다음을 명심하세요.

  • 함수가 예외를 던지면 전체 배치가 완전한 실패로 간주돼요.
  • FIFO 큐에서 이 기능을 쓴다면 함수는 첫 번째 실패 후 메시지 처리를 중지하고 모든 실패·미처리 메시지를 batchItemFailures에 반환해야 해요. 이는 큐의 메시지 순서를 보존하는 데 도움이 돼요.

부분 배치 보고 활성화하기

  1. 부분 배치 응답 구현 모범 사례를 검토해요.
  2. 다음 명령으로 함수에 ReportBatchItemFailures를 활성화해요. 이벤트 소스 매핑의 UUID를 검색하려면 list-event-source-mappings AWS CLI 명령을 실행해요.
aws lambda update-event-source-mapping \
  --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
  --function-response-types "ReportBatchItemFailures"
  1. 모든 예외를 잡고 실패한 메시지를 batchItemFailures JSON 응답으로 반환하도록 함수 코드를 업데이트해요. batchItemFailures 응답에는 itemIdentifier JSON 값으로 메시지 ID 목록이 포함되어야 해요. 예를 들어 메시지 ID가 id1, id2, id3, id4, id5인 다섯 개 메시지 배치가 있다고 가정해요. 함수가 id1, id3, id5를 성공적으로 처리했다면, 메시지 id2와 id4를 큐에서 다시 보이게 만들기 위해 함수는 다음 응답을 반환해야 해요.
{
  "batchItemFailures": [
    { "itemIdentifier": "id2" },
    { "itemIdentifier": "id4" }
  ]
}

다음은 배치의 실패한 메시지 ID 목록을 반환하는 함수 코드 예시예요. (JavaScript — SDK for JavaScript v3)

// Node.js 20.x Lambda runtime, AWS SDK for Javascript V3
export const handler = async (event, context) => {
  const batchItemFailures = [];

  for (const record of event.Records) {
    try {
      await processMessageAsync(record, context);
    } catch (error) {
      batchItemFailures.push({ itemIdentifier: record.messageId });
    }
  }

  return { batchItemFailures };
};

async function processMessageAsync(record, context) {
  if (record.body && record.body.includes("error")) {
    throw new Error("There is an error in the SQS Message.");
  }
  console.log(`Processed message: ${record.body}`);
}

참고 GitHub에 더 많은 내용이 있어요. Serverless examples 저장소에서 .NET, Go, Java, TypeScript, PHP, Python, Ruby, Rust용 전체 예시를 찾고 설정·실행 방법을 알아보세요.

실패한 이벤트가 큐로 돌아오지 않으면 AWS Knowledge Center의 Lambda 함수 SQS ReportBatchItemFailures 어떻게 트러블슈팅하나요?를 참고하세요.

성공·실패 조건

함수가 다음 중 하나를 반환하면 Lambda는 배치를 완전한 성공으로 처리해요.

  • 빈 batchItemFailures 목록
  • null batchItemFailures 목록
  • 빈 EventResponse
  • null EventResponse

함수가 다음 중 하나를 반환하면 Lambda는 배치를 완전한 실패로 처리해요.

  • 잘못된 JSON 응답
  • 빈 문자열 itemIdentifier
  • null itemIdentifier
  • 잘못된 키 이름을 가진 itemIdentifier
  • 존재하지 않는 메시지 ID 값을 가진 itemIdentifier

CloudWatch 지표

함수가 배치 항목 실패를 올바르게 보고하는지 확인하려면 Amazon CloudWatch에서 NumberOfMessagesDeleted와 ApproximateAgeOfOldestMessage Amazon SQS 지표를 모니터링할 수 있어요.

  • NumberOfMessagesDeleted는 큐에서 제거된 메시지 수를 추적해요. 이 값이 0으로 떨어지면 함수 응답이 실패한 메시지를 올바르게 반환하지 않고 있다는 신호예요.
  • ApproximateAgeOfOldestMessage는 가장 오래된 메시지가 큐에 머문 시간을 추적해요. 이 지표의 급격한 증가는 함수가 실패한 메시지를 올바르게 반환하지 않고 있다는 것을 나타낼 수 있어요.

Powertools for AWS Lambda 배치 프로세서 사용하기

Powertools for AWS Lambda의 배치 프로세서 유틸리티는 부분 배치 응답 로직을 자동으로 처리해 배치 실패 보고 구현의 복잡성을 줄여줘요. 배치 프로세서를 사용하는 예시는 다음과 같아요. (Python)

import json
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes import SQSEvent
from aws_lambda_powertools.utilities.typing import LambdaContext

processor = BatchProcessor(event_type=EventType.SQS)
logger = Logger()

def record_handler(record):
    logger.info(record)
    # Your business logic here
    # Raise an exception to mark this record as failed

def lambda_handler(event, context: LambdaContext):
    return process_partial_response(
        event=event,
        record_handler=record_handler,
        processor=processor,
        context=context
    )

참고 완전한 예시와 설정 지침은 배치 프로세서 문서를 참고하세요.

출처: AWS Lambda 개발자 안내서

더 알아보기 (Learn more)