跳至主要内容

精通 AWS Step Functions:新手全面指南

本文是一份深入指南,介绍 AWS Step Functions、其关键特性,以及如何高效使用。

使用 AI 探索

每个复杂系统都是多个子系统协同编排的结果。构建并维护此类系统始终是一项常见挑战,尤其是在涉及云基础设施时。

幸运的是,各类工具已被开发出来以简化不同复杂度下的工作流编排。在这些工具中,AWS Step Functions 以其实用性和众多优势而脱颖而出。

本文聚焦于如何在 AWS 云中使用 Step Functions 来编排工作流。我们将从 Step Functions 是什么、它的优势与关键特性讲起。

随后,将引导您从配置 AWS 环境到浏览界面,逐步开始使用 Step Functions。在此基础上,本文将带您一步步创建并部署一个真实世界的工作流。

什么是 AWS Step Functions?

AWS Step Functions 是一项无服务器编排服务,旨在帮助创建可视化工作流,从而无缝协调 AWS Lambda 函数与其他 AWS 资源。

它具备广泛的集成能力,可与 Amazon EC2、Amazon ECS、本地服务器、Amazon API Gateway 以及 Amazon SQS 队列等进行对接,确保工作流能够全面覆盖并与广泛的 AWS 服务生态进行交互。

AWS Step Functions 的多样性使其适用于广泛的应用场景。无论是管理订单履约、处理数据、支撑 Web 应用,还是编排任意复杂的任务序列,Step Functions 都能为工作流自动化与管理提供稳健方案。

关键特性与优势

在深入 AWS Step Functions 的技术细节之前,让我们先了解其主要特性与优势。

关键特性

Step Functions 提供多种功能以简化工作流的创建与管理,主要包括:

  • HTTPS 端点集成:允许工作流调用任何支持 HTTPS 的 Web 服务,以便在用户流程中集成各类 Web API。
  • 分布式组件协调:可协调分布式系统中的各组件,这对于复杂的多服务应用至关重要。
  • 内置状态管理:通过细致监控每次工作流执行的进度,该能力在执行期间维护应用状态,并管理各步骤之间的数据传递。
  • 人工审批:在自动化中引入“人参与”至关重要。该功能提供在自动化工作流中加入人工干预的机制,以便在必要时进行手动审批。

优势

AWS Step Functions 的关键特性为开发者与组织提供多重益处,从而改进其运营与开发工作流。

面向开发者

面向组织

  • 为开发者提供友好、低代码的平台,高效设计复杂工作流,显著简化开发流程。
  • AWS Step Functions 的可伸缩性让开发者无需承担基础设施管理负担。
  • 内置的错误处理与状态管理提升了应用的整体可靠性与健壮性。
  • Step Functions 降低人工干预、优化资源使用的能力可带来可观的成本节约。
  • 快速设计与执行工作流可缩短开发周期,加速新功能与产品的交付。
  • 自动化与错误处理特性提升可靠性并减少人为失误,使业务流程更高效。

真实案例与应用场景

基于上述特性与优势,Step Functions 能在多个领域发挥关键作用,帮助企业设计、自动化并高效扩展其工作流。

本节将探讨不同行业如何使用 AWS Step Functions 来提升竞争力、创新力与效率。

微服务协同

采用微服务架构的组织常利用 AWS Step Functions 管理各服务之间的交互。

例如,一家零售公司可部署 Step Functions 来编排用户认证、库存管理、支付处理与订单派送等步骤,确保连贯一致的购物体验。

安全与 IT 运维

AWS Step Functions 可用于自动化重复性任务,如安全检查、系统更新与合规验证。

例如,在 IT 安全领域,Step Functions 可用于设计事件响应工作流,通过系统性地管理从初始告警到问题解决的各阶段,降低人为失误并缩短响应时间。

数据工作流与 ETL 流程

对于数据密集型企业,AWS Step Functions 可编排数据处理与 ETL 任务。这可能涉及从多个来源抽取数据、转换为一致格式,并加载至分析平台或数据湖的工作流。

例如,一家分析公司可以实施 Step Functions 来自动化其数据管道,确保高效处理数据以支持战略决策。

机器学习运维

在机器学习的运维层面,Step Functions 同样有用,涵盖数据准备、模型训练、评估与部署等流程。

某医疗科技公司可使用 Step Functions 管理其诊断算法的定期再训练管道,随着新数据到来持续保持模型性能。

媒体处理流水线

在媒体与娱乐行业,AWS Step Functions 可编排复杂的媒体处理工作流,包括视频编码、图像处理与内容分析。

媒体公司可应用 Step Functions,确保新内容一经上传,便自动触发格式转换、缩略图提取与元数据丰富,随后再发布。

开始使用 AWS Step Functions

本文后续章节将介绍 Step Functions 与其他 AWS 服务的组合使用。因此,在进入高级概念之前,有必要先理解 Step Functions 的基础知识。

本节旨在帮助您入门 AWS Step Functions,从理解构建模块到熟悉 AWS Step Functions 界面。

Step Functions 的构建模块

任何系统或模块都由多个子组件构成,Step Functions 亦是如此。其基于以下模块:(1) 状态机,(2) 任务。

我们通过一个示例来理解这些概念。

  • 状态机:定义事件顺序、条件逻辑与任务整体执行流程的工作流。简言之,状态机可视为一个工作流。
  • 任务:执行特定操作的动作。它接收输入并生成输出。例如查询数据库、调用 API 或触发 Lambda 函数等。

考虑一个使用 AWS Step Functions 执行日托注册流程的用例。在深入使用 Step Functions 之前,先了解整体步骤:

  • 收集注册信息:流程的第一步是从家长处收集注册信息。这可以通过 Web 表单完成,但在我们的用例中使用 JSON。提交后会触发一个 Lambda 函数,该函数将注册信息传递给工作流的下一步。
  • 验证注册信息:下一步使用 Lambda 函数验证注册信息。它检查所有必填字段是否已填写,以及孩子的年龄是否在日托可接受范围内。若验证通过,工作流继续下一步;否则向家长返回错误信息。
  • 检查名额:在验证注册信息后,另一 Lambda 函数检查日托名额是否充足。若有名额,流程继续下一步;若无,则向家长发送日托已满的通知。
  • 确认注册:最后一步由 Lambda 函数确认注册,并向家长发送确认信息,其中包含开学日期与费用明细。

该工作流包含一个具有四个主要任务的状态机,名称不言自明。

  • checkInformation
  • checkAgeRange
  • checkSpotsAvailability
  • confirmRegistration

Daycare Registration workflow using AWS Step functions.

使用 AWS Step Functions 的日托注册工作流

构建您的第一个 AWS Step Function

上文提供了更多理论知识,本节将进入技术细节,从使用 Step Functions 的先决条件开始,到实现端到端工作流并将其部署。

实现 Step Functions 的先决条件

在深入用例细节之前,先了解成功实施所需的先决条件:

  • AWS 账号:用于访问 AWS 服务,可通过 AWS 官网创建。
  • 具备 AWS 服务 的基础知识:熟悉 AWS Lambda 与 Amazon Simple Notification Service (SNS) 是本用例的必要条件。
  • JSON 知识:需要对 JSON 有基本了解,以理解输入与输出数据格式。
  • AWS IAM:需要了解 AWS 身份与访问管理 (IAM),以为所用的 Lambda 函数设置正确的权限。
  • 编码技能:具备 Python 的基础编码技能,以编写 Lambda 函数。

浏览 AWS Step Functions 界面

让我们先探索 Step Functions 界面。登录 AWS 账户后,按照以下四个主要步骤进行:

  • 在顶部搜索栏输入“Step Functions”关键字。
  • 从结果中选择相应图标。
  • 点击“Get Started”以开始创建第一个 Step Function。
  • 最后,由于我们要创建自定义状态机,选择“Create your own”选项卡。

Four main steps to access a Step Function interface

进入 Step Functions 界面的四个主要步骤

完成第四步后,我们即可在“Design”选项卡中开始设计状态机。该选项卡包含三大功能:“Actions”、“Flow” 与 “Patterns”。

The three main components of the "Design" tab

“Design” 选项卡的三大组件

  • Actions:对应工作流中的各个独立操作,并映射到特定 AWS 服务,例如调用 Lambda 函数、向 SNS 发布消息、在 ECS 上运行任务或在 AWS Glue 中启动作业。
  • Flow:表示控制状态机执行路径的流程控制结构。包括用于分支逻辑的“Choice”、并发执行路径的“Parallel”、遍历集合的“Map”、作为空操作或状态数据增强的“Pass”、用于时间延迟的“Wait”、用于成功结束工作流的“Success”以及因错误结束的“Fail”等。
  • Patterns:常见工作流场景的预定义模板或最佳实践,便于构建复杂状态机。示例包括处理 S3 对象、JSON 文件、CSV 文件的数据处理任务,或用于编排异步作业执行的通用模式如 Job Poller。

创建工作流

前面的初始工作流旨在概览状态机的主要组成部分。本节将回顾具体的实现过程。

为此,我们需要四个 Lambda 函数,每个对应一个特定任务。

以下七个步骤展示了创建 Lambda 函数所需的全部操作。四个函数的创建流程相同;唯一的差异在于函数的具体实现内容。

全文所用代码可在GitHub 页面获取。尽管代码易于理解,仍强烈建议您完整阅读本文以获得更佳体验。

7 main steps to create a Lambda Function

创建 Lambda 函数的 7 个主要步骤

完成上述七步后,将出现如下窗口,展示以下关键信息:

Details of the checkInformation lambda function

checkInformation Lambda 函数详情

现在,请为其余三个任务(函数)checkAgeRange、checkSpotsAvailability 和 confirmRegistration 重复相同过程。

下面给出了输入 JSON 的示例。理解它非常重要,因为这会影响函数的实现方式。

  • 该 JSON 包含被注册孩子的信息,包括名字、姓氏和出生日期。
  • 还包括父母信息、孩子将参加日托的星期几,以及任何附加说明。
{ 
  "registration_info": { 
	"child": { 
  	"firstName": "Mohamed", 
  	"lastName": "Diallo", 
  	"dateOfBirth": "2016-07-01" 
	}, 
	"parents": { 
  	"mother": { 
    	"firstName": "Aicha", 
    	"lastName": "Cisse", 
    	"email": "[email protected]", 
    	"phone": "123-456-7890" 
  	}, 
  	"father": { 
    	"firstName": "Ibrahim", 
    	"lastName": "Diallo", 
    	"email": "[email protected]", 
    	"phone": "098-765-4321" 
  	} 
	}, 
	"daysOfWeek": [ 
  	"Monday", 
  	"Tuesday", 
  	"Wednesday", 
  	"Thursday", 
  	"Friday" 
	], 
	"specialInstructions": "Mohamed has a peanut allergy." 
  } 
} 

每个 Lambda 函数说明如下:

函数

描述

checkInformation

  • 从事件中提取注册信息
  • 检查所有必填字段是否存在
  • 若全部检查通过则返回成功响应;若缺少必填字段则返回错误信息

checkAgeRange

  • 从事件中提取孩子的出生日期并计算其年龄
  • 检查孩子年龄是否在日托可接受范围内
  • 若年龄检查通过则返回成功响应;否则返回孩子不在可接受年龄范围内的错误信息

checkSpotsAvailability

  • 检查日托名额是否充足
  • 若有名额则返回成功响应;若已满则返回错误信息

confirmRegistration

  • 根据孩子的年龄范围与开始日期(注册日期后两周)计算费用
  • 确认注册并向家长发送确认信息
  • 返回包含确认信息的成功响应

每个函数的底层实现如下:

checkInformation 函数

 import json 
  
 def checkInformation(event, context): 
	 registration_info = event['registration_info'] 
  
	 required_fields = ['child', 'parents', 'daysOfWeek'] 
	 for field in required_fields: 
    	if field not in registration_info: 
        	return { 
            	'statusCode': 400, 
            	'body': f'Missing required field: {field}' 
        	} 

	 return { 
    	'statusCode': 200, 
    	'body': json.dumps(registration_info) 
	 } 

checkAgeRange 函数

 import json 
 import datetime 
  
 def checkAgeRange(event, context): 
	
	registration_info = json.loads(event['body']) 
  
	dob = registration_info['child']['dateOfBirth'] 
  
	today = datetime.date.today() 
	dob_date = datetime.datetime.strptime(dob, '%Y-%m-%d').date() 
	age = today.year - dob_date.year - ((today.month, today.day) < (dob_date.month, dob_date.day)) 
  
	if age < 2 or age > 5: 
    	return { 
        	'statusCode': 400, 
        	'body': json.dumps('Child is not within the acceptable age range for this daycare.') 
    	} 
  

	registration_info['child']['age'] = age 
  
	return { 
    	'statusCode': 200, 
    	'body': json.dumps(registration_info) 
	} 

checkSpotsAvailability 函数

import json 
  
def checkSpotsAvailability(event, context): 
 
	registration_info = json.loads(event['body']) 
  
	spots_available = 20  # This should be dynamically determined, not hardcoded 
  
	if spots_available <= 0: 
    	return { 
        	'statusCode': 400, 
        	'body': json.dumps('No spots available in the daycare.') 
    	} 
  
	return { 
    	'statusCode': 200, 
    	'body': json.dumps(registration_info) 
	} 

confirmRegistration 函数

import json 
import datetime 
  
def confirmRegistration(event, context): 
	
	registration_info = json.loads(event['body']) 
	age = registration_info['child']['age']  # This was added in the checkAgeRange function 
  
	if age >= 2 and age < 3: 
    	fees = 800 
	elif age >= 3 and age < 4: 
    	fees = 750 
	elif age >= 4 and age < 5: 
    	fees = 700 
	else:  # age >= 5 
    	fees = 650 
  
	start_date = datetime.date.today() + datetime.timedelta(weeks=2) 
  
	confirmation_details = { 
    	'fees': fees, 
    	'start_date': start_date.isoformat() 
	} 
  
	response = {**registration_info, **confirmation_details} 
  
	return { 
    	'statusCode': 200, 
    	'body': json.dumps(response) 
	} 

一切就绪后,我们即可使用 Step Functions 的图形化界面创建日托状态机。

下图为最终状态机。让我们了解实现该工作流的关键步骤:

State machine workflow for the daycare use case

日托用例的状态机工作流

在开始之前,需注意:状态机依据 Lambda 函数输出中的 statusCode 字段来决定下一个状态。

  • 若值为 200,表示检查成功,进入下一步。
  • 若 statusCode 为 400,表示检查失败,此时根据执行该任务的函数返回相应消息。

检查信息

  • 状态机从此步骤开始。
  • 调用 Lambda 函数以检查注册表单中的必填信息是否齐全。
  • 若信息完整则进入下一步;否则以失败状态结束并提示信息不完整。

检查年龄范围

  • 仅在信息检查成功后才会进入此步骤。
  • 调用另一个 Lambda 函数检查孩子年龄是否处于日托可接受范围。
  • 若年龄在范围内则进入下一步;否则以失败状态结束并提示年龄无效。

检查名额

  • 仅在年龄检查成功后才会进入此步骤。
  • 调用 Lambda 函数检查日托是否有可用名额。
  • 若有名额则进入下一步;否则以失败状态结束并提示无可用名额。

确认注册

  • 这是最后一步,且仅在有可用名额时才会进入。
  • 调用 Lambda 函数确认注册,并根据孩子年龄计算费用。
  • 流程在此步后以成功状态结束,完成注册。

如需进一步了解 Lambda 函数,Streaming Data with AWS Kinesis and Lambda 课程将教您如何在 AWS 上使用无服务器技术处理流数据。

创建 IAM 角色

下一步是定义 IAM 角色,以便 Step Functions 能调用我们的 Lambda 函数。按以下步骤进行:

First 9 steps to create an IAM role

创建 IAM 角色的前九个步骤

The 11th steps to create an IAM role

创建 IAM 角色的第 10 与第 11 步

随后,可从“Config”选项卡开始,将该 IAM 角色分配给状态机,方法如下:

3 main steps to grant the IAM role

授予 IAM 角色的 3 个主要步骤

保存后,我们应看到如下消息,以确认一切顺利。

Success message for the state machine creation

状态机创建成功消息

当我们对状态机感到满意后,下一步是点击右上角的“Create”按钮进行创建。

Illustration of the execution of the state machine

状态机执行示意图

部署与测试您的工作流

我们的工作流已部署,现在是测试状态机的时候了。我们将测试两个场景:

  • 一个失败用例:年龄范围验证有效,但尝试注册的孩子超过 5 岁。对应于初始 JSON。
  • 一个成功用例:孩子为 3 岁。

Result of a success case

成功用例的结果

Result of a failure case

失败用例的结果

优化您的 Step Functions

任何流程的优化都应从采用与之相关的最佳实践入手,从而提升性能并提高成本效益。以下最佳实践有助于充分发挥 AWS Step Functions 的价值。

  • 性能最佳实践:包括尽量减少状态转换次数、使用合适的超时设置、优化 AWS Lambda 函数等策略。
  • 成本效益最佳实践:包括选择合适的状态机类型(Standard 或 Express)、管控 AWS Lambda 成本、理解并管理 Step Functions 定价等策略。

结论

本文提供了理解与使用 AWS Step Functions 的全面指南。我们首先介绍了 AWS Step Functions 的关键特性与优势。

随后,引导读者完成 AWS 环境的搭建,并熟悉 AWS Step Functions 界面。

此外,本文还带您构建第一个 AWS Step Function,从创建基础工作流到部署与测试;在此基础上,探讨了 AWS Step Functions 的高级功能与应用场景,并讨论了如何对其进行优化以实现最高效率与成本效益。

总结

我们的文章AWS、Azure 与 GCP 的数据科学与 AI 服务对比以及Python 中的 AWS Boto 入门,都是进一步学习的优秀后续资源。

第一篇提供了数据与 AI 相关工作的核心服务对比,从数据工程、数据分析、数据科学到数据应用开发。该速查表可帮助您理解三大平台在数据科学与 AI 方面的云服务版图。

第二篇则对 Python 中的 AWS Boto 做了简明介绍,教您如何借助云技术优化数据工作流。对于希望通过 Python 自动化 AWS 运维的人而言,这是极佳的入门资料。

AWS 服务众多,掌握 AWS Step Functions 的关键在于理解应用需求,并使用恰当的 AWS 服务与功能组合来满足这些需求。

Zoumana Keita

作者

Zoumana Keita

一位多才多艺、乐于分享知识并回馈他人的数据科学家。Zoumana 是 YouTube 内容创作者,也是 Medium 上的顶尖科技写作者。他热爱演讲、编程与教学。Zoumana 拥有两个硕士学位:其一是在法国巴黎获得的计算机科学硕士,专注于机器学习;其二是在美国德州理工大学获得的数据科学硕士。他的职业生涯始于法国 Groupe OPEN 的软件开发工程师,随后加入 IBM 担任机器学习顾问,为保险公司构建端到端的 AI 解决方案。之后,Zoumana 加入了 Axionable——一家总部位于巴黎与蒙特利尔的首家“可持续 AI”初创公司。在那里,他担任数据科学家,为来自法国、蒙特利尔、新加坡和瑞士的客户交付 AI 产品,主要聚焦 NLP 场景。此外,他将 5% 的时间投入到研发工作。目前,他在 IFC(世界银行集团)担任高级数据科学家。

主题