使用 Amazon CDK 为 Step Functions 创建一个 Lambda 状态机 - Amazon Step Functions
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Amazon CDK 为 Step Functions 创建一个 Lambda 状态机

本教程将介绍如何使用 Amazon Cloud Development Kit (Amazon CDK) 创建包含 Amazon Lambda 函数的 Amazon Step Functions 状态机。Amazon CDK 是一个基础设施即代码 (IAC) 框架,可以让您用完整的编程语言定义 Amazon 基础设施使。您可以用 CDK 支持的语言之一编写包含一个或多个堆栈的应用程序。然后,可以将其合成为 Amazon CloudFormation 模板并部署到您的 Amazon 帐户。我们将使用此方法来定义包含 Lambda 函数的 Step Functions 状态机,然后使用 Amazon Web Services Management Console来运行状态机。

在开始本教程之前,您必须按照《Amazon Cloud Development Kit (Amazon CDK) 开发人员指南》中开始使用 Amazon CDK - 先决条件所述,设置您的 Amazon CDK 开发环境。然后,在 Amazon CLI 中使用以下命令安装 Amazon CDK:

npm install -g aws-cdk

本教程产生的结果与使用 Amazon CloudFormation 为 Step Functions 创建一个 Lambda 状态机相同。但是,在本教程中,Amazon CDK 不需要您创建任何 IAM 角色,Amazon CDK 会为您创建。Amazon CDK 版本还包括一个 Succeed 步骤,用于说明如何向状态机添加其他步骤。

提示

要将使用带有 TypeScript 的 Amazon CDK 启动 Step Functions 工作流的示例无服务器应用程序部署到您的 Amazon Web Services 账户,请参阅《Amazon Step Functions 研讨会》中的模块10 - 使用 Amazon CDK 部署

第 1 步:设置您的 Amazon CDK 项目

  1. 在您的主目录或其他目录中,运行以下命令为您的新 Amazon CDK 应用程序创建一个目录。

    重要

    请确保将目录命名为 step。Amazon CDK 应用程序模板使用目录的名称来生成源文件和类的名称。如果您使用其他名称,则您的应用将与本教程不匹配。

    TypeScript
    mkdir step && cd step
    JavaScript
    mkdir step && cd step
    Python
    mkdir step && cd step
    Java
    mkdir step && cd step
    C#

    确保您已安装.NET 版本 6.0 或更高版本。有关信息,请参阅受支持的版本

    mkdir step && cd step
  2. 使用 cdk init 命令初始化应用程序。指定所需的模板(“应用程序”)和编程语言,如以下示例所示。

    TypeScript
    cdk init --language typescript
    JavaScript
    cdk init --language javascript
    Python
    cdk init --language python

    初始化项目后,激活项目的虚拟环境并安装 Amazon CDK 的基线依赖关系。

    source .venv/bin/activate python -m pip install -r requirements.txt
    Java
    cdk init --language java
    C#
    cdk init --language csharp

第 2 步:使用 Amazon CDK 创建状态机

首先,我们将展示定义 Lambda 函数和 Step Functions 状态机的单独代码片段。然后,我们将解释如何在您的 Amazon CDK 应用程序中将它们组合在一起。最后,您将了解如何合成和部署这些资源。

创建 Lambda 函数

以下 Amazon CDK 代码定义了 Lambda 函数,并提供了其内联源代码。

TypeScript
const helloFunction = new lambda.Function(this, 'MyLambdaFunction', { code: lambda.Code.fromInline(` exports.handler = (event, context, callback) => { callback(null, "Hello World!"); }; `), runtime: lambda.Runtime.NODEJS_18_X, handler: "index.handler", timeout: cdk.Duration.seconds(3) });
JavaScript
const helloFunction = new lambda.Function(this, 'MyLambdaFunction', { code: lambda.Code.fromInline(` exports.handler = (event, context, callback) => { callback(null, "Hello World!"); }; `), runtime: lambda.Runtime.NODEJS_18_X, handler: "index.handler", timeout: cdk.Duration.seconds(3) });
Python
hello_function = lambda_.Function( self, "MyLambdaFunction", code=lambda_.Code.from_inline(""" exports.handler = (event, context, callback) => { callback(null, "Hello World!"); }"""), runtime=lambda_.Runtime.NODEJS_18_X, handler="index.handler", timeout=Duration.seconds(25))
Java
final Function helloFunction = Function.Builder.create(this, "MyLambdaFunction") .code(Code.fromInline( "exports.handler = (event, context, callback) => { callback(null, 'Hello World!' );}")) .runtime(Runtime.NODEJS_18_X) .handler("index.handler") .timeout(Duration.seconds(25)) .build();
C#
var helloFunction = new Function(this, "MyLambdaFunction", new FunctionProps { Code = Code.FromInline(@"` exports.handler = (event, context, callback) => { callback(null, 'Hello World!'); }"), Runtime = Runtime.NODEJS_12_X, Handler = "index.handler", Timeout = Duration.Seconds(25) });

您可以在这个简短的示例代码中看到:

  • 函数的逻辑名称 MyLambdaFunction

  • 函数的源代码,以字符串形式嵌入到 Amazon CDK 应用程序的源代码中。

  • 其他函数属性,例如要使用的运行时间(节点 18.x)、函数的入口点和超时。

创建状态机

我们的状态机有两种状态:Lambda 函数任务和 Succeed 状态。该函数要求我们创建一个 Step Functions Task 来调用我们的函数。此 Task 状态用作状态机的第一个步骤。使用 Task 状态的next()方法将 success 状态添加到状态机中。以下代码首先调用名为 MyLambdaTask 的函数,然后使用 next() 方法定义名为 GreetedWorld 的 success 状态。

TypeScript
const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', { definition: new tasks.LambdaInvoke(this, "MyLambdaTask", { lambdaFunction: helloFunction }).next(new sfn.Succeed(this, "GreetedWorld")) });
JavaScript
const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', { definition: new tasks.LambdaInvoke(this, "MyLambdaTask", { lambdaFunction: helloFunction }).next(new sfn.Succeed(this, "GreetedWorld")) });
Python
state_machine = sfn.StateMachine( self, "MyStateMachine", definition=tasks.LambdaInvoke( self, "MyLambdaTask", lambda_function=hello_function) .next(sfn.Succeed(self, "GreetedWorld")))
Java
final StateMachine stateMachine = StateMachine.Builder.create(this, "MyStateMachine") .definition(LambdaInvoke.Builder.create(this, "MyLambdaTask") .lambdaFunction(helloFunction) .build() .next(new Succeed(this, "GreetedWorld"))) .build();
C#
var stateMachine = new StateMachine(this, "MyStateMachine", new StateMachineProps { DefinitionBody = DefinitionBody.FromChainable(new LambdaInvoke(this, "MyLambdaTask", new LambdaInvokeProps { LambdaFunction = helloFunction }) .Next(new Succeed(this, "GreetedWorld"))) });

构建并部署 Amazon CDK 应用程序

在新创建的 Amazon CDK 项目中,编辑包含堆栈定义的文件,使其与下面的示例代码类似。您将从前面的部分中了解 Lambda 函数和 Step Functions 状态机的定义。

  1. 如下例所示更新堆栈。

    TypeScript

    使用以下代码更新 lib/step-stack.ts

    import * as cdk from 'aws-cdk-lib'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'; export class StepStack extends cdk.Stack { constructor(app: cdk.App, id: string) { super(app, id); const helloFunction = new lambda.Function(this, 'MyLambdaFunction', { code: lambda.Code.fromInline(` exports.handler = (event, context, callback) => { callback(null, "Hello World!"); }; `), runtime: lambda.Runtime.NODEJS_18_X, handler: "index.handler", timeout: cdk.Duration.seconds(3) }); const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', { definition: new tasks.LambdaInvoke(this, "MyLambdaTask", { lambdaFunction: helloFunction }).next(new sfn.Succeed(this, "GreetedWorld")) }); } }
    JavaScript

    使用以下代码更新 lib/step-stack.js

    import * as cdk from 'aws-cdk-lib'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'; export class StepStack extends cdk.Stack { constructor(app, id) { super(app, id); const helloFunction = new lambda.Function(this, 'MyLambdaFunction', { code: lambda.Code.fromInline(` exports.handler = (event, context, callback) => { callback(null, "Hello World!"); }; `), runtime: lambda.Runtime.NODEJS_18_X, handler: "index.handler", timeout: cdk.Duration.seconds(3) }); const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', { definition: new tasks.LambdaInvoke(this, "MyLambdaTask", { lambdaFunction: helloFunction }).next(new sfn.Succeed(this, "GreetedWorld")) }); } }
    Python

    使用以下代码更新 step/step_stack.py

    from aws_cdk import ( Duration, Stack, aws_stepfunctions as sfn, aws_stepfunctions_tasks as tasks, aws_lambda as lambda_ ) class StepStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) hello_function = lambda_.Function( self, "MyLambdaFunction", code=lambda_.Code.from_inline(""" exports.handler = (event, context, callback) => { callback(null, "Hello World!"); }"""), runtime=lambda_.Runtime.NODEJS_18_X, handler="index.handler", timeout=Duration.seconds(25)) state_machine = sfn.StateMachine( self, "MyStateMachine", definition=tasks.LambdaInvoke( self, "MyLambdaTask", lambda_function=hello_function) .next(sfn.Succeed(self, "GreetedWorld")))
    Java

    使用以下代码更新 src/main/java/com.myorg/StepStack.java

    package com.myorg; import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.Duration; import software.amazon.awscdk.services.lambda.Code; import software.amazon.awscdk.services.lambda.Function; import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.stepfunctions.StateMachine; import software.amazon.awscdk.services.stepfunctions.Succeed; import software.amazon.awscdk.services.stepfunctions.tasks.LambdaInvoke; public class StepStack extends Stack { public StepStack(final Construct scope, final String id) { this(scope, id, null); } public StepStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); final Function helloFunction = Function.Builder.create(this, "MyLambdaFunction") .code(Code.fromInline( "exports.handler = (event, context, callback) => { callback(null, 'Hello World!' );}")) .runtime(Runtime.NODEJS_18_X) .handler("index.handler") .timeout(Duration.seconds(25)) .build(); final StateMachine stateMachine = StateMachine.Builder.create(this, "MyStateMachine") .definition(LambdaInvoke.Builder.create(this, "MyLambdaTask") .lambdaFunction(helloFunction) .build() .next(new Succeed(this, "GreetedWorld"))) .build(); } }
    C#

    使用以下代码更新 scr/Step/StepStack.cs

    using Amazon.CDK; using Constructs; using Amazon.CDK.AWS.Lambda; using Amazon.CDK.AWS.StepFunctions; using Amazon.CDK.AWS.StepFunctions.Tasks; namespace Step { public class StepStack : Stack { internal StepStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { var helloFunction = new Function(this, "MyLambdaFunction", new FunctionProps { Code = Code.FromInline(@"exports.handler = (event, context, callback) => { callback(null, 'Hello World!'); }"), Runtime = Runtime.NODEJS_18_X, Handler = "index.handler", Timeout = Duration.Seconds(25) }); var stateMachine = new StateMachine(this, "MyStateMachine", new StateMachineProps { DefinitionBody = DefinitionBody.FromChainable(new LambdaInvoke(this, "MyLambdaTask", new LambdaInvokeProps { LambdaFunction = helloFunction }) .Next(new Succeed(this, "GreetedWorld"))) }); } } }
  2. 保存源文件,然后在应用程序的主目录中运行 cdk synth 命令。

    Amazon CDK 运行应用程序并合成 Amazon CloudFormation 模板。然后,Amazon CDK 会显示该模板。

    注意

    如果您使用 TypeScript 创建 Amazon CDK 项目,则运行 cdk synth 命令可能会返回以下错误。

    TSError: ⨯ Unable to compile TypeScript: bin/step.ts:7:33 - error TS2554: Expected 2 arguments, but got 3.

    修改 bin/step.ts 文件,如以下示例所示,可解决此错误。

    #!/usr/bin/env node import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { StepStack } from '../lib/step-stack'; const app = new cdk.App(); new StepStack(app, 'StepStack'); app.synth();
  3. 要将 Lambda 函数和 Step Functions 状态机部署到您的 Amazon 账户,请发出 cdk deploy。将要求您批准 Amazon CDK 生成的 IAM 策略。

第 3 步:启动状态机执行

在创建您的状态机后,可以开始执行。

启动状态机执行

  1. 打开 Step Functions 控制台,然后选择您使用 Amazon CDK 创建的状态机的名称。

  2. 在状态机页面,选择启动执行

    随即显示启动执行对话框。

  3. (可选)要识别您的执行,您可以在名称框中为其指定一个名称。默认情况下,Step Functions 会自动生成一个唯一的执行名称。

    注意

    Step Functions 允许您为状态机、执行、活动、速率控制和包含非 ASCII 字符的标签创建名称。这些非 ASCII 名称不适用于 Amazon CloudWatch。为确保您可以跟踪 CloudWatch 指标,请选择一个仅使用 ASCII 字符的名称。

  4. 选择启动执行

    状态机的执行将启动,并显示一个说明正在运行的执行的新页面。

  5. Step Functions 控制台会将您引导到一个以您的执行 ID 为标题的页面。该页面被称为执行详细信息页面。在此页面上,您可以随着执行的进展或者在执行完成后查看执行结果。

    要查看执行结果,请在图表视图上选择各个状态,然后在步骤详细信息窗格中选择各个选项卡,分别查看每个状态的详细信息,包括输入、输出和定义。有关可在执行详细信息页面上查看的执行信息的详细信息,请参阅“执行详细信息”页面 – 界面概述

第 4 步:清除

测试状态机完成后,我们建议您删除状态机和相关的 Lambda 函数,以释放 Amazon Web Services 账户中的资源。在您的应用程序的主目录中运行 cdk destroy 命令,以删除状态机。

后续步骤

要了解有关使用 Amazon CDK 开发 Amazon 基础设施的信息,请参阅Amazon CDK 开发人员指南

有关使用所选语言编写 Amazon CDK 应用程序的信息,请参阅:

TypeScript

在 TypeScript 中使用 Amazon CDK

JavaScript

在 JavaScript 中使用 Amazon CDK

Python

在 Python 中使用 Amazon CDK

Java

在 Java 中使用 Amazon CDK

C#

在 C# 中使用 Amazon CDK

有关本教程中使用的 Amazon 构造库模块的更多信息,请参见以下 Amazon CDK API 参考概述: