

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 在 Step Functions 中 AWS CDK 建立標準工作流程
<a name="tutorial-lambda-state-machine-cdk"></a>

您可以使用AWS Cloud Development Kit (AWS CDK)基礎設施即程式碼 (IAC) 架構來建立包含 AWS Lambda函數AWS Step Functions的狀態機器。

您將使用 CDK支援的其中一種語言來定義 AWS 基礎設施。定義基礎設施後，您會將應用程式合成至 CloudFormation 範本，並將其部署至 AWS 您的帳戶。

 您將使用此方法定義包含 Lambda 函數的 Step Functions 狀態機器，然後從使用 Step Functions 的 執行狀態機器 AWS 管理主控台。

開始本教學課程之前，您必須設定AWS CDK開發環境，如 *AWS Cloud Development Kit (AWS CDK) 開發人員指南*中的 [AWS CDK- 先決條件入門](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html#getting_started_prerequisites)中所述。然後，在 AWS CDK使用下列命令安裝 AWS CLI：

```
npm install -g aws-cdk
```

本教學課程會產生與 相同的結果[使用 在 Step Functions 中 CloudFormation 建立工作流程](tutorial-lambda-state-machine-cloudformation.md)。不過，在本教學課程中， AWS CDK不需要您建立任何IAM角色； 會為您AWS CDK執行。AWS CDK 版本也包含一個[工作流程狀態成功](state-succeed.md)步驟，說明如何將其他步驟新增至您的狀態機器。

**提示**  
若要部署使用 AWS CDK搭配 TypeScript 啟動Step Functions工作流程的範例無伺服器應用程式，請參閱* AWS Step Functions 研討會*中的[使用 部署AWS CDK](https://catalog.workshops.aws/stepfunctions/iac/deploy-with-cdk)。

## 步驟 1：設定您的 AWS CDK 專案
<a name="lambda-state-machine-cdk-step-1"></a>

1. 在您的主目錄中，或者如果您願意，請執行下列命令來為您的新AWS CDK應用程式建立目錄。
**重要**  
請務必將目錄命名為 `step`。AWS CDK 應用程式範本使用 目錄的名稱來產生來源檔案和類別的名稱。若使用不同名稱，您的應用程式將與本教學課程不相符。

------
#### [ TypeScript ]

   ```
   mkdir step && cd step
   ```

------
#### [ JavaScript ]

   ```
   mkdir step && cd step
   ```

------
#### [ Python ]

   ```
   mkdir step && cd step
   ```

------
#### [ Java ]

   ```
   mkdir step && cd step
   ```

------
#### [ C\$1 ]

   請確定您已安裝 .NET 6.0 版或更新版本。如需詳細資訊，請參閱[支援的版本](https://dotnet.microsoft.com/en-us/download/dotnet)。

   ```
   mkdir step && cd step
   ```

------

1. 使用 **cdk init** 命令初始化應用程式。指定所需的範本 ("app") 和程式設計語言，如下列範例所示。

------
#### [ TypeScript ]

   ```
   cdk init --language typescript
   ```

------
#### [ JavaScript ]

   ```
   cdk init --language javascript
   ```

------
#### [ Python ]

   ```
   cdk init --language python
   ```

   初始化專案之後，請啟用專案的虛擬環境，並安裝 AWS CDK的基準相依性。

   ```
   source .venv/bin/activate
   python -m pip install -r requirements.txt
   ```

------
#### [ Java ]

   ```
   cdk init --language java
   ```

------
#### [ C\$1 ]

   ```
   cdk init --language csharp
   ```

------

## 步驟 2：使用 AWS CDK建立狀態機器
<a name="lambda-state-machine-cdk-step-2"></a>

首先，我們將介紹定義Lambda函數和Step Functions狀態機器的個別程式碼片段。然後，我們將說明如何將它們放在您的AWS CDK應用程式中。最後，您將了解如何合成和部署這些資源。

### 建立 Lambda 函數
<a name="lambda-state-machine-cdk-create-function"></a>

下列AWS 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\$1 ]

```
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`。
+ 函數的原始程式碼，內嵌為AWS CDK應用程式的原始程式碼中的字串。
+ 其他函數屬性，例如要使用的執行時間 （節點 18.x)、函數的進入點和逾時。

### 建立 狀態機器
<a name="lambda-state-machine-cdk-create"></a>

我們的狀態機器有兩個狀態：Lambda函數任務和[工作流程狀態成功](state-succeed.md)狀態。函數需要我們建立Step Functions[任務工作流程狀態](state-task.md)叫用函數的 。此任務狀態用作狀態機器中的第一個步驟。成功狀態會使用任務狀態的 `next()`方法新增至狀態機器。下列程式碼會先叫用名為 的函數`MyLambdaTask`，然後使用 `next()`方法來定義名為 的成功狀態`GreetedWorld`。

------
#### [ 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\$1 ]

```
var stateMachine = new StateMachine(this, "MyStateMachine", new StateMachineProps {
    DefinitionBody = DefinitionBody.FromChainable(new LambdaInvoke(this, "MyLambdaTask", new LambdaInvokeProps
    {
        LambdaFunction = helloFunction
    })
    .Next(new Succeed(this, "GreetedWorld")))
});
```

------

### 建置和部署AWS CDK應用程式
<a name="lambda-state-machine-cdk-app"></a>

在您新建立的AWS 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\$1 ]

   `src/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")))
               });
           }
       }
   }
   ```

------

1. 儲存來源檔案，然後在應用程式的主目錄中執行 `cdk synth`命令。

   AWS CDK 會執行應用程式並從中合成CloudFormation範本。AWS CDK然後 會顯示範本。
**注意**  
如果您使用 TypeScript 建立AWS 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();
   ```

1. 若要將 Lambda 函數和 Step Functions 狀態機器部署到您的帳戶 AWS ，請發出 `cdk deploy`。系統會要求您核准 AWS CDK 產生的 IAM 政策。

## 步驟 3：啟動狀態機器執行
<a name="lambda-state-machine-cdk-step-3"></a>

建立狀態機器後，您可以開始執行。

### 開始狀態機器執行
<a name="to-start-the-state-machine-execution"></a>

1. 開啟 [Step Functions 主控台](https://console.aws.amazon.com/states/home)，然後選擇您使用 建立的狀態機器名稱AWS CDK。

1. 在狀態機器頁面上，選擇**開始執行**。

   隨即顯示**開始執行**對話方塊。

1. （選用） 輸入自訂執行名稱以覆寫產生的預設值。
**非 ASCII 名稱和記錄**  
Step Functions 接受包含非 ASCII 字元的狀態機器、執行、活動和標籤名稱。由於這類字元會阻止 Amazon CloudWatch 記錄資料，因此我們建議您僅使用 ASCII 字元，以便您可以追蹤 Step Functions 指標。

1. 選擇 **Start Execution (開始執行)**。

   狀態機器的執行開始，並顯示顯示執行中執行的新頁面。

1. Step Functions 主控台會將您導向至標題為執行 ID 的頁面。此頁面稱為*執行詳細資訊*頁面。在此頁面上，您可以在執行進行時或完成後檢閱執行結果。

   若要檢閱執行結果，請在**圖形檢視**中選擇個別狀態，然後選擇[步驟詳細資訊](concepts-view-execution-details.md#exec-details-intf-step-details)窗格上的個別索引標籤，分別檢視每個狀態的詳細資訊，包括輸入、輸出和定義。如需您可以在執行詳細資訊頁面上檢視之*執行資訊的詳細資訊*，請參閱 [執行詳細資訊概觀](concepts-view-execution-details.md#exec-details-interface-overview)。

## 步驟 4：清除
<a name="lambda-state-machine-cdk-step-4"></a>

測試狀態機器之後，建議您同時移除狀態機器和相關的 Lambda 函數，以釋放 中的資源 AWS 帳戶。在應用程式的主目錄中執行 `cdk destroy`命令，以移除您的狀態機器。

## 後續步驟
<a name="lambda-state-machine-cdk-next-steps"></a>

若要進一步了解如何使用 開發 AWS 基礎設施AWS CDK，請參閱 [AWS CDK開發人員指南](https://docs.aws.amazon.com/cdk/v2/guide/home.html)。

如需有關以所選語言編寫 AWS CDK 應用程式的資訊，請參閱：

------
#### [ TypeScript ]

 [在 TypeScript AWS CDK中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html) 

------
#### [ JavaScript ]

 [在 JavaScript AWS CDK中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-javascript.html) 

------
#### [ Python ]

 [在 Python AWS CDK中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html) 

------
#### [ Java ]

 [在 Java AWS CDK中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-java.html) 

------
#### [ C\$1 ]

 [在 C\$1 AWS CDK中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html) 

------

如需本教學中使用的 AWS 建構程式庫模組的詳細資訊，請參閱下列 AWS CDK API 參考概觀：
+  [aws-lambda](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html) 
+  [aws-stepfunctions](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions-readme.html) 
+  [aws-stepfunctions-tasks](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions_tasks-readme.html) 