荣幸参与和csdn和aws联合举办的buildon实验活动,主要目的还是学习stepfucntion的使用,这个服务能够集成大量aws service感觉可以出现很多有趣的用法。官方给出的文档已经非常详细了,这里只是对一些比较难理解的点进行了记录和解释,欢迎交流和学习~
本次实验通过stepfunction创建事件驱动的 serverless 服务,整体架构如下图
涉及到的服务包括,Amazon Step Functions、Amazon EventBridge、Amazon Lambda、Amazon API Gateway、Amazon S3、Amazon DynamoDB和Amazon Cognito
主要收获
- 使用stepfunction创建工作流
- Amazon States Language的写法和含义
- eventbridge的事件生成捕获和驱动
大部分的资源已经通过cloudformation的方式预置了,属于是常规操作,想要了解cloudformation的更多细节可以看之前的几篇文章。我们只需要围绕一个主要的stepfunction用工即可
Workflow Studio
创建并设计状态机,aws提供了可视化界面来简化工作
设计界面预置了很多状态和集成服务。其中状态是状态机中的元素,状态通过其名称 来引用,这可以是任意字符串,但在整个状态机的范围内必须唯一,总共由以下几个
- Do some work in your state machine (a Task state)
- Make a choice between branches of execution (a Choice state)
- Stop an execution with a failure or success (a Fail or Succeed state)
- Pass its input to its output, or inject some fixed data into the workflow (a Pass state)
- Provide a delay for a certain amount of time, or until a specified date and time (a Wait state)
- Begin parallel branches of execution (a Parallel state)
- Dynamically iterate steps (a Map state)
最终设计出的stepfunction如下
整个stepfunction就是将特定输入经过一系列处理按照特定逻辑转化为一系列输出的过程
其中两个回调事件比较特殊,通过指定如下api,经过自定义事件总线发送事件
{
"Entries": [
{
"Detail": {
"Message": "The order has reached the end of the workflow, and so a final event is emitted to alert other services to this.",
"userId.$": "$.detail.userId",
"orderId.$": "$.detail.orderId"
},
"DetailType": "OrderProcessor.orderFinished",
"EventBusName": "Serverlesspresso",
"Source": "awsserverlessda.serverlesspresso"
}
]
}
相关的ddb表存储数据,共四张表。例如下面这个表记录的店铺信息
等待具有任务令牌的回调(用于执行一些外部操作),在官方文档中给出了例子,Step Functions 发布了一条 Amazon SQS 消息,其中包含任务令牌作为消息的一部分。外部系统与 Amazon SQS 集成,并将消息从队列中拉出。完成后,它会返回结果和原始任务令牌。然后,Step Functions 继续其工作流程
具体需要发送api调用来恢复stepfunction的执行
aws stepfunctions send-task-success --task-output '{"orderId":1}' --task-token YOUR_TASK_TOKEN
最后的超时设置
官方文档给出的示例如下,任务在 300 秒内未能完成,或者未在 60 秒的间隔内发送检测信号通知,则任务会被标记为 failed
"ActivityState": {
"Type": "Task",
"Resource": "arn:aws:states:us-east-1:123456789012:activity:HelloWorld",
"TimeoutSeconds": 300,
"HeartbeatSeconds": 60,
"Next": "NextState"
}
Amazon States Language
Step Functions
工作流程使用 Amazon
状态语言 (ASL) 定义。ASL
是一种基于 JSON
的结构化语言,用于定义状态机、工作状态的集合(任务状态)、确定要转换到下一个状态的状态(选择状态)、因错误停止执行(失败状态)、等等。工作流是基于 JSON
的文档,您可以将其签入 GitHub
,并使用基础设施作为代码工具(如 Amazon SAM 或 CDK)进行部署。
Payload Template
状态机解释器通过payload template传递不同状态之间的输入输出
If any field within the Payload Template (however deeply nested) has a name ending with the characters “.$”, its value is transformed according to rules below and the field is renamed to strip the suffix
- If the field value begins with only one “$”, the value MUST be a Path. In this case, the Path is applied to the Payload Template’s input and is the new field value.
- If the field value begins with “$$”, the first dollar sign is stripped and the remainder MUST be a Path. In this case, the Path is applied to the Context Object and is the new field value.
- If the field value does not begin with “$”, it MUST be an Intrinsic Function. The interpreter invokes the Intrinsic Function and the result is the new field value.
- If the path is legal but cannot be applied successfully, the interpreter fails the machine execution with an Error Name of “States.ParameterPathFailure”. If the Intrinsic Function fails during evaluation, the interpreter fails the machine execution with an Error Name of “States.IntrinsicFailure”.
- A JSON object MUST NOT have duplicate field names after fields ending with the characters “. " a r e r e n a m e d t o s t r i p t h e " . " are renamed to strip the ". "arerenamedtostripthe".” suffix.
例如
"X": {
"Type": "Task",
"Resource": "arn:aws:states:us-east-1:123456789012:task:X",
"Next": "Y",
"Parameters": {
"flagged": true,
"parts": {
"first.$": "$.vals[0]", // payload参数
"last3.$": "$.vals[-3:]"
},
"weekday.$": "$$.DayOfWeek", //context对象
"formattedOutput.$": "States.Format('Today is {}', $$.DayOfWeek)" //内部函数
}
}
Input and Output Processing
Fields named “InputPath”, “Parameters”, “ResultSelector”, “ResultPath”, “OutputPath” 支持对J不同状态之间传递的JSON文本的格式和内容进行控制
aws控制台上提供了data flow simulator的功能帮助我们调试数据流转换,遗憾的是中国区貌似还未提供此功能
看看每种类型的介绍如下
- state input:状态机中的每个状态将接收 JSON 作为输入并将 JSON 作为输出传递。可以使用一个或多个提供的状态筛选器减少状态输入
- inputpath:使用 InputPath 筛选器选择要使用的 JSON 状态输入部分,通过json表达式指定要使用的 JSON 部分
- parameter:可用来创建作为aws服务输入传递的键值对集合,如 Lambda 函数调用。这些值可以是静态的或者可以使用 JSONPath 表达式
- task result:来自 AWS 服务集成或活动工作线程的响应
- ResultSelector:使用 ResultSelector 筛选器以使用任务结果部分构建新的 JSON 对象。
- ResultPath:使用 ResultPath 将结果添加到原始状态输入中。指定的路径表示结果的添加位置。
- OutputPath:OutputPath 筛选器允许您在最终结果成为状态输出之前对其进行筛选。
- State Output:最终输出
不同数据状态之间的转换逻辑如下图
官方的电影数据的转换图示图下,字比较小建议下载放大看
实验中全部的参数输入和输出都是按照States Language的语法来写的,这个图应该有助于理解input/output的转化
Event-driven
事件驱动架构具有三个关键组件:事件生产者、事件路由器和事件消费者。生产者向路由器发布事件,路由器过滤并将事件推送给消费者。生产者服务和消费者服务是解耦的,这使得它们可以独立扩展、更新和部署。
eventbrdige会按照预先设定的规则对特定的事件进行匹配和捕获(事件种类众多),并触发目标操作
除了aws托管事件外,我们可以自定义事件的发送和处理
该项目实际上在2个地方等待外部事件激活工作流
- 等待客户下单(发送令牌回调事件)
- 等待商家完成订单(发送令牌回调事件)
实验中为我们提供了OrderManager
工作流stepfunction进行发送回调的操作
在之后就是和前端页面进行端到端集成测试,按照给出的步骤完成就可以了,iot和cognito用户池的配置没有进一步解释有点遗憾。
- 前端是使用Amazon Amplify部署的 Vue.js 应用程序。
- 前端应用程序使用 Amazon Cognito 来允许客户注册和登录他们的账户,后端使用相同的 Cognito 配置来识别用户。
- 前端使用Amazon API Gateway终端节点与关键服务进行通信。
- 使用与Amazon IoT Core的 WebSocket 连接来接收实时消息
最终实现的效果还是很喜人,本次收获还是蛮大的~