介绍
临时的依赖故障可能恢复,而无效订单应保持失败状态。你将配置选择性重试和永久失败路径,然后观察实际尝试和存储结果。
请先完成 构建多步骤订单工作流。这个全新 VM 提供自己的工作程序和空表;不会复用之前的状态机、角色或执行。
相关认证考点
本实验为以下认证考点提供动手练习。
- Solutions Architect – Associate (SAA-C03) · 任务 2.1: 工作流错误处理、有界重试与失败结果。
- Developer – Associate (DVA-C02) · 任务 1.1: 工作流错误处理、有界重试与失败结果。
- DevOps Engineer – Professional (DOP-C02) · 任务 5.1: 基础练习:工作流错误处理、有界重试与失败结果。
- Solutions Architect – Professional (SAP-C02) · 任务 2.4: 基础练习:工作流错误处理、有界重试与失败结果。
授权工作流调用其工作程序
本步骤中,检查提供的业务工作程序,并为 Step Functions 创建独立执行角色。
使用 Terminal 旁的 AWS View,将 CLI 查询与本实验的实际资源和结果对比。保留提供的参考数据。
这个全新 VM 提供工作程序函数和独立的订单、诊断及参考表。尚无状态机或工作流角色。工作程序接受订单,写入数量和总金额,稍后还能读取摘要。对于模拟故障测试,flaky 模式会在第一次尝试中、任何业务写入之前抛出 TransientOrderError;permanent 模式会在写入之前抛出 InvalidOrder。诊断尝试与业务订单分开保存。其 Lambda 执行角色已授权这些作为配套环境的表操作。
从项目目录开始。shell 赋值保存返回的标识符;--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)
写入普通权限文档。shell 插入 $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 从一秒延迟开始;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 显示相同配置;尚无执行或业务订单。运行恢复定义检查。
观察实际重试、Catch 与权限结果
本步骤中,运行临时失败、永久失败和被拒绝的调用。
工作程序的第一次 flaky 尝试更新诊断尝试计数,并在写入订单之前抛出错误。下一次尝试可以成功。有次数上限的 shell 循环每两秒读取执行状态,直到不再运行;$(...) 捕获输出,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 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 进入明确的永久失败状态。原生历史与实际订单区分了尝试次数和业务写入;权限拒绝没有产生工作程序或业务影响。你移除了自己创建的工作流资源和结果,同时保留提供的配套资源。
下一个实验将处理业务写入之后发生的失败,此时重试可能重复产生业务效果。



