构建多步骤订单工作流

AWSBeginner
立即练习

介绍

履约系统必须先保存订单,再读取其完成后的摘要。你将通过工作流连接这些任务,并将执行历史与实际业务结果对比。

请先完成 通过 Lambda 读取和写入 DynamoDB,以及它要求的 IAM 角色和日志前置实验。这个独立 VM 提供工作程序和表;工作流由你创建。EventBridge 路由属于独立的学习支线。

相关认证考点

本实验为以下认证考点提供动手练习。

授权工作流调用其工作程序

本步骤中,检查提供的业务工作程序,并为 Step Functions 创建独立执行角色。

工作流与工作程序权限

工作流角色调用函数。独立的 Lambda 角色执行表操作。

使用 Terminal 旁的 AWS View,将 CLI 查询与本实验的实际资源和结果对比。保留提供的参考数据。

工作流连接任务和决策。状态机定义这些状态;一次执行使用特定输入运行该定义。这个全新 VM 提供工作程序函数和独立的订单、诊断及参考表。尚无状态机或工作流角色。工作程序接受订单,写入数量和总金额,稍后还能读取摘要。其 Lambda 执行角色已授权这些作为配套环境的表操作。

从项目目录开始。shell 赋值保存返回的标识符;--query 选择响应字段,--output text 生成可复用字符串。

cd /home/labex/project
WORKER_NAME=labex-ev03-worker
WORKER_ARN=$(aws lambda get-function-configuration \
  --function-name labex-ev03-worker \
  --query FunctionArn \
  --output text)
aws lambda get-function-configuration \
  --function-name labex-ev03-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-ev03-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-ev03-workflow-role \
  --policy-name InvokeWorker \
  --policy-document file://workflow-invoke.json
aws iam get-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker

策略只有一个精确的函数 ARN。Step Functions 不会获得工作程序的 DynamoDB 权限:工作程序使用独立的 Lambda 角色执行这些调用。运行授权检查。

定义决策和两个实际任务

本步骤中,定义订单工作流,验证数量、存储订单并读取实际摘要。

输入、保存的结果与摘要

StoreOrder 将实际载荷保存到 saved.result 下;ReadSummary 选择该订单 ID 并读取完成后的摘要。

Amazon States Language(ASL)是一种 JSON 状态机定义。StartAt 选择第一个状态。Choice 在条件匹配时进入一个分支,否则进入 Default。Task 调用服务。Next 连接状态;End: true 表示成功结束,而 Fail 表示以错误结束。

优化的 Lambda 任务集成使用 arn:aws:states:::lambda:invoke。Parameters 提供函数参数:以 .$ 结尾的键会评估 JSONPath,$ 选择完整的当前输入。Lambda 集成返回元数据和 Payload。ResultSelector 只保留该载荷,ResultPath 将其插入 saved 下,同时保留原始订单输入,下一项任务再选择保存的订单 ID。它的 OutputPath 只返回实际摘要载荷。

写入字面定义,然后使用 jq --arg 替换工作程序占位符:

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",
      "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": "Quantity must be positive"
    }
  }
}
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-ev03-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,Role:roleArn,Definition:definition}'

响应指定状态机和工作流角色,定义在两个任务中都指定提供的工作程序。尚未处理任何订单。点击 Terminal 旁的 AWS View,查看实际状态机定义以及空的执行和订单列表。运行定义检查。

验证业务结果与被拒绝的执行

本步骤中,运行有效订单、无效数量,以及缺少调用权限的执行。

start-execution 启动异步任务并返回执行 ARN。下面有次数上限的 shell 循环每两秒读取一次状态,直到执行不再运行。$(...) 捕获命令输出,seq 提供循环次数,条件匹配时 break 退出循环。如果循环后仍为 RUNNING,继续之前先检查服务。

EXECUTION_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name valid-order \
  --input '{"id":"workflow-order","quantity":3}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 60); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$EXECUTION_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$EXECUTION_ARN" \
  --query '{Status:status,Output:output}'
aws stepfunctions get-execution-history \
  --execution-arn "$EXECUTION_ARN" \
  --query 'events[].type'
aws dynamodb get-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"workflow-order"}}' \
  --query Item

Step Functions 官方 Console 执行列表示例

官方 Console 将执行名称、状态和时间并列显示。其中的名称和工作流与本实验的 Standard 状态机不同。将你的 CLI 状态与历史和存储数据对比;使用 AWS View 查看本实验的结果。

来源:AWS Step Functions。

状态为 SUCCEEDED,输出包含订单 ID、total_cents:850 和 completed:true。实际 DynamoDB 项目的数量为 3,总金额为 850。历史包含两个 TaskSucceeded 事件:存储订单和读取摘要。仅有执行状态不能证明业务结果;应对比两者。

使用数量零测试 Choice 分支:

INVALID_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name invalid-order \
  --input '{"id":"invalid-order","quantity":0}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 30); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$INVALID_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$INVALID_ARN" \
  --query '{Status:status,Error:error}'
aws dynamodb get-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"invalid-order"}}' \
  --query Item

状态为 FAILED,错误为 OrderRejected,且没有 invalid-order 项目。Choice 在调用工作程序之前拒绝了它。

现在只移除工作流的 Invoke 策略。工作程序的角色和数据权限仍然独立。操作员仍被允许启动执行,但工作流角色无法调用其任务:

aws iam delete-role-policy --role-name labex-ev03-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}' \
  --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-ev03-orders \
  --key '{"id":{"S":"denied-order"}}' \
  --query Item
aws iam put-role-policy \
  --role-name labex-ev03-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-ev03-workflow-role --policy-name InvokeWorker
aws iam delete-role --role-name labex-ev03-workflow-role
aws dynamodb delete-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"workflow-order"}}'
aws dynamodb delete-item \
  --table-name labex-ev03-attempts \
  --key '{"id":{"S":"workflow-order"}}'
aws logs delete-log-group --log-group-name /aws/lambda/labex-ev03-worker

成功读取资源清单,证明剩余资源状态:

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

没有活动状态机、订单或日志组。只保留提供的工作程序角色,参考项目未改变。保留提供的工作程序和表:它们属于环境准备资源,与你创建的工作流和资源不同。网络或身份验证错误绝不能证明删除成功。

移除本实验创建的普通文件:

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

AWS View 显示状态机、执行和订单为空,参考资源仍保留。结束 VM 之前,运行清理检查。

总结

你创建了限定范围的工作流执行角色,连接 Choice 和两个实际 Lambda 任务,将实际结果传给下一项任务,并将执行历史与业务数据对比。无效输入和缺少调用权限都没有产生订单。你移除了自己创建的工作流资源和模拟结果,同时保留提供的配套资源。

下一个实验将添加针对临时失败的重试,以及对永久错误的明确处理。