실패한 단계 재시도 및 영구 오류 처리

AWSBeginner
지금 연습하기

소개

의존 서비스의 일시적인 실패는 복구될 수 있지만 잘못된 주문은 실패 상태로 남아야 합니다. 선택적인 재시도와 영구 실패 경로를 설정한 다음 실제 시도와 저장된 결과를 관찰합니다.

여러 단계의 주문 워크플로 구축을 먼저 완료하세요. 이 새 VM에는 자체 작업자와 빈 테이블이 제공됩니다. 이전 머신, 역할과 실행은 재사용하지 않습니다.

인증 시험 관련 주제

이 실습은 다음 시험 주제에 대한 실습 경험을 제공합니다.

워크플로에 작업자 호출 권한 부여

이 단계에서는 제공된 비즈니스 작업자를 확인하고 Step Functions를 위한 별도의 실행 역할을 만듭니다.

Terminal 옆에서 AWS View를 사용하여 CLI 쿼리를 이 실습의 실제 리소스 및 결과와 비교하세요. 제공된 참조 데이터를 유지하세요.

이 새 VM에는 작업자 함수와 독립적인 주문/진단/참조 테이블이 제공됩니다. 아직 상태 머신이나 워크플로 역할은 없습니다. 작업자는 주문을 받고 수량과 합계를 쓰며 나중에 요약을 읽을 수 있습니다. 테스트용 오류 주입에서 flaky 모드는 비즈니스 쓰기 전에 첫 시도에서 TransientOrderError를 발생시킵니다. permanent 모드는 쓰기 전에 InvalidOrder를 발생시킵니다. 진단 시도는 비즈니스 주문과 별개입니다. Lambda 실행 역할에는 이미 이러한 별도의 테이블 작업 권한이 있습니다.

프로젝트 디렉터리에서 시작하세요. 셸 할당은 반환된 식별자를 저장하고 --query는 응답 필드를 선택하며 --output text는 재사용할 수 있는 문자열을 생성합니다.

cd /home/labex/project
WORKER_NAME=labex-ev04-worker
WORKER_ARN=$(aws lambda get-function-configuration \
  --function-name labex-ev04-worker \
  --query FunctionArn \
  --output text)
aws lambda get-function-configuration \
  --function-name labex-ev04-worker \
  --query '{Name:FunctionName,Role:Role,Runtime:Runtime,Timeout:Timeout}'
aws stepfunctions list-state-machines

작업자는 Python3.12와 자체 Lambda 역할을 사용하며 머신 목록은 비어 있습니다. Step Functions에는 자체 실행 역할이 필요합니다. 신뢰 정책은 Step Functions 서비스가 해당 역할을 맡도록 허용하고 권한 정책은 생성된 세션이 정확히 이 작업자를 호출하도록 허용합니다. 따옴표가 있는 here-document는 리터럴 JSON을 쓰고 file://는 이를 요청으로 읽습니다.

cat > workflow-trust.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "states.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
JSON
ROLE_ARN=$(aws iam create-role \
  --role-name labex-ev04-workflow-role \
  --assume-role-policy-document file://workflow-trust.json \
  --query Role.Arn \
  --output text)

일반 권한 문서를 작성하세요. 셸은 $WORKER_ARN을 넣어 이 권한을 제공된 작업자로 제한합니다.

cat > workflow-invoke.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "lambda:InvokeFunction",
      "Resource": "$WORKER_ARN"
    }
  ]
}
EOF
aws iam put-role-policy \
  --role-name labex-ev04-workflow-role \
  --policy-name InvokeWorker \
  --policy-document file://workflow-invoke.json
aws iam get-role-policy --role-name labex-ev04-workflow-role --policy-name InvokeWorker

정책에는 정확한 함수 ARN 하나가 있습니다. Step Functions는 작업자의 DynamoDB 권한을 받지 않습니다. 작업자는 별도의 Lambda 역할로 해당 호출을 수행합니다. 권한 부여 검사를 실행하세요.

제한된 재시도와 영구 실패 경로 설정

이 단계에서는 선택적인 복구 동작을 갖는 실제 두 작업 워크플로를 구축합니다.

일시적 재시도와 영구 실패

이 작업자의 일시적인 오류는 재시도로 복구될 수 있습니다. 영구 오류는 Catch를 따라 명시적인 실패 결과로 이동합니다.

ASL Retry는 재시도할 수 있는 작업 오류를 나열합니다. ErrorEquals는 함수의 오류 유형과 일치해야 합니다. IntervalSeconds:1은 1초 지연으로 시작하고 BackoffRate:2는 다음 지연을 배수로 늘립니다. MaxAttempts:2는 최초 시도 후 최대 두 번의 재시도를 허용합니다. 이 재시도는 모든 가능한 실패가 아니라 TransientOrderError만 처리합니다.

Catch는 작업이 복구하지 못한 오류에 대해 다른 상태를 선택합니다. ResultPath는 오류를 failure 아래에 기록하고 Next는 명시적인 Fail 상태로 이동합니다. 오류를 처리했다고 해서 비즈니스 작업이 성공한 것은 아닙니다. 영구적인 InvalidOrder는 주문을 완료한 것처럼 가장하지 않고 OrderRejected와 함께 FAILED로 종료됩니다.

따옴표가 있는 here-document는 리터럴 JSON을 씁니다. 기존 Choice는 양수가 아닌 수량을 거부하며 두 Task는 저장한 다음 요약을 읽습니다. Payload.$는 현재 입력을 전달하고 ResultSelector는 실제 함수 페이로드를 유지하며 ResultPath는 이를 saved 아래에 보관하고 OutputPath는 실제 요약을 반환합니다.

cat > workflow-template.json <<'JSON'
{
  "StartAt": "CheckQuantity",
  "States": {
    "CheckQuantity": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.quantity",
          "NumericGreaterThan": 0,
          "Next": "StoreOrder"
        }
      ],
      "Default": "Rejected"
    },
    "StoreOrder": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "WORKER_NAME",
        "Payload.$": "$"
      },
      "ResultSelector": {
        "result.$": "$.Payload"
      },
      "ResultPath": "$.saved",
      "Retry": [
        {
          "ErrorEquals": [
            "TransientOrderError"
          ],
          "IntervalSeconds": 1,
          "BackoffRate": 2,
          "MaxAttempts": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "InvalidOrder"
          ],
          "Next": "Rejected",
          "ResultPath": "$.failure"
        }
      ],
      "Next": "ReadSummary"
    },
    "ReadSummary": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "WORKER_NAME",
        "Payload": {
          "stage": "summary",
          "id.$": "$.saved.result.id"
        }
      },
      "OutputPath": "$.Payload",
      "End": true
    },
    "Rejected": {
      "Type": "Fail",
      "Error": "OrderRejected",
      "Cause": "Order could not be completed"
    }
  }
}
JSON
jq --arg worker "$WORKER_NAME" '.States.StoreOrder.Parameters.FunctionName=$worker | .States.ReadSummary.Parameters.FunctionName=$worker' workflow-template.json > workflow.json
MACHINE_ARN=$(aws stepfunctions create-state-machine \
  --name labex-ev04-orders \
  --type STANDARD \
  --role-arn "$ROLE_ARN" \
  --definition file://workflow.json \
  --query stateMachineArn \
  --output text)
aws stepfunctions describe-state-machine \
  --state-machine-arn "$MACHINE_ARN" \
  --query '{Name:name,Definition:definition}'

정의에는 선택적인 retry와 catch 블록이 포함됩니다. AWS View는 같은 설정을 보여 줍니다. 아직 실행이나 비즈니스 주문은 없습니다. 복구 정의 검사를 실행하세요.

실제 Retry, Catch와 권한 결과 관찰

이 단계에서는 일시적인 실패, 영구 실패와 거부된 호출을 실행합니다.

작업자의 첫 flaky 시도는 진단 시도 카운터를 업데이트하고 주문을 쓰기 전에 오류를 발생시킵니다. 다음 시도는 성공할 수 있습니다. 횟수가 제한된 셸 루프는 실행 중 상태가 끝날 때까지 2초마다 상태를 읽습니다. $(...)는 출력을 저장하고 break는 루프를 종료합니다. 루프 이후에도 실행이 RUNNING이면 진행하기 전에 확인하세요.

RETRY_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name retry-order \
  --input '{"id":"retry-order","quantity":2,"mode":"flaky"}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 60); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$RETRY_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$RETRY_ARN" \
  --query '{Status:status,Output:output}'
aws stepfunctions get-execution-history \
  --execution-arn "$RETRY_ARN" \
  --query 'events[?type==`TaskFailed` || type==`TaskSucceeded`].{Type:type,Error:taskFailedEventDetails.error}'
aws dynamodb get-item \
  --table-name labex-ev04-orders \
  --key '{"id":{"S":"retry-order"}}' \
  --query Item
aws dynamodb get-item \
  --table-name labex-ev04-attempts \
  --key '{"id":{"S":"retry-order"}}' \
  --query Item

최종 상태는 SUCCEEDED이며 완료된 요약은 2/600입니다. 기록에는 TransientOrderError TaskFailed 하나 이후 성공적인 저장과 요약 읽기에 해당하는 TaskSucceeded 이벤트 두 개가 있습니다. 네이티브 주문의 수량은 2, 합계는 600이며 진단 시도는 2입니다. 재시도를 포함한 시도 횟수와 비즈니스 쓰기 횟수는 다릅니다.

이제 작업자의 영구 실패 모드를 사용하세요.

PERMANENT_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name permanent-order \
  --input '{"id":"permanent-order","quantity":2,"mode":"permanent"}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 30); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$PERMANENT_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$PERMANENT_ARN" \
  --query '{Status:status,Error:error}'
aws stepfunctions get-execution-history \
  --execution-arn "$PERMANENT_ARN" \
  --query 'events[?type==`TaskFailed` || type==`FailStateEntered`].{Type:type,Error:taskFailedEventDetails.error,State:stateEnteredEventDetails.name}'
aws dynamodb get-item \
  --table-name labex-ev04-orders \
  --key '{"id":{"S":"permanent-order"}}' \
  --query Item

실제 작업자 호출 하나가 InvalidOrder로 실패합니다. Catch는 Rejected에 도달하고 실행은 OrderRejected와 함께 FAILED로 종료됩니다. 일시적 오류 재시도는 이 영구 오류와 일치하지 않습니다. permanent-order 비즈니스 항목은 없습니다.

마지막으로 워크플로의 호출 권한만 제거하세요. 운영자는 실행을 시작할 수 있지만 워크플로 역할은 작업자를 호출할 수 없습니다.

aws iam delete-role-policy --role-name labex-ev04-workflow-role --policy-name InvokeWorker
DENIED_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name denied-order \
  --input '{"id":"denied-order","quantity":2,"mode":"flaky"}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 30); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$DENIED_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$DENIED_ARN" \
  --query '{Status:status,Error:error}'
aws dynamodb get-item \
  --table-name labex-ev04-orders \
  --key '{"id":{"S":"denied-order"}}' \
  --query Item
aws iam put-role-policy \
  --role-name labex-ev04-workflow-role \
  --policy-name InvokeWorker \
  --policy-document file://workflow-invoke.json

이 접근 거부 실행은 작업자를 호출하거나 진단/비즈니스 데이터를 만들지 않고 실패합니다. 지정된 애플리케이션 오류를 재시도해도 누락된 권한 부여는 복구되지 않습니다. 의도한 권한을 복구했습니다. AWS View는 주문 하나 옆에 성공한 재시도 요약과 두 실패를 보여 줍니다.

아래 예시는 저장된 주문 옆에 실제 재시도 요약, 영구 실패와 거부된 실행을 보여 줍니다.

실제 재시도 성공과 영구 실패가 표시된 AWS View

실제 복구 검사를 실행하세요.

워크플로 리소스와 테스트 결과 제거

이 단계에서는 제공된 준비물을 유지하면서 완료된 머신, 워크플로 역할, 주문과 로그를 삭제합니다.

세 실행은 모두 종료되었습니다. 머신을 삭제하면 활성 머신 목록에서 제거됩니다. 역할을 삭제하기 전에 소유한 역할 정책을 제거한 다음 실행으로 만든 테스트 주문과 작업자 로그 그룹을 제거하세요.

aws stepfunctions delete-state-machine --state-machine-arn "$MACHINE_ARN"
aws iam delete-role-policy --role-name labex-ev04-workflow-role --policy-name InvokeWorker
aws iam delete-role --role-name labex-ev04-workflow-role
aws dynamodb delete-item --table-name labex-ev04-orders --key '{"id":{"S":"retry-order"}}'
aws dynamodb delete-item \
  --table-name labex-ev04-attempts \
  --key '{"id":{"S":"retry-order"}}'
aws logs delete-log-group --log-group-name /aws/lambda/labex-ev04-worker

성공한 인벤토리를 읽어 남은 것을 증명하세요.

aws stepfunctions list-state-machines
aws iam list-roles --query 'Roles[].RoleName'
aws dynamodb scan --table-name labex-ev04-orders --query Items
aws logs describe-log-groups --query logGroups
aws dynamodb scan --table-name labex-ev04-reference --query Items

활성 머신, 주문이나 로그 그룹은 없습니다. 제공된 작업자 역할만 남으며 참조 항목은 변경되지 않습니다. 제공된 작업자와 테이블을 유지하세요. 준비 단계의 소유 범위는 직접 만든 워크플로/리소스와 다릅니다. 네트워크 오류나 인증 오류는 삭제를 증명하지 않습니다.

이 실습에서 만든 일반 파일을 제거하세요.

rm -f workflow-trust.json workflow-invoke.json workflow-template.json workflow.json

AWS View는 빈 머신/실행/주문과 유지된 참조를 보여 줍니다. VM을 종료하기 전에 정리 검사를 실행하세요.

요약

특정 일시적 실패에 대한 제한된 재시도와 명시적인 영구 실패로 이동하는 Catch를 설정했습니다. 네이티브 기록과 실제 주문으로 시도와 비즈니스 쓰기를 구별했습니다. 권한 거부는 작업자 실행이나 비즈니스 효과를 만들지 않았습니다. 제공된 준비물을 유지하면서 소유한 워크플로 리소스와 결과를 제거했습니다.

다음 단원은 비즈니스 쓰기 이후 발생하여 재시도가 효과를 반복할 수 있는 실패를 처리합니다.