

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

# 在 Step Functions 中使用 Lambda 函数继续新的执行
<a name="tutorial-use-lambda-cont-exec"></a>

**提示**  
以下方法使用 Lambda 函数来启动新的工作流程执行。我们**建议**使用 Step Functions Task 状态来启动新的工作流程执行。在以下教程中查看操作方法：**[使用 Step Functions API 继续长时间运行的工作流程（建议）](tutorial-continue-new.md)**。

您可以创建一个使用 Lambda 函数的状态机，用于在当前执行终止之前启动新的执行。通过这种方法在新的执行中继续正在进行的工作，可以将大型任务分解为较小的工作流程，或者无限期地运行工作流程。

本教程背后的理念是，使用外部 Lambda 函数修改您的工作流程，详情请见[在 Step Functions 中使用 Lambda 函数迭代循环](tutorial-create-iterate-pattern-section.md)教程。您将使用相同的 Lambda 函数 (`Iterator`) 将循环迭代特定次数。此外，您将创建另一个 Lambda 函数来启动工作流程的新执行，并在每次启动新执行之后将计数减一。在输入中设置执行次数后，此状态机将结束并重新开始执行达指定的次数。

您将要创建的状态机可实施以下状态。


| 状态 | 用途 | 
| --- | --- | 
| `ConfigureCount` |  配置了 `count`、`index` 和 `step` 值的 `Pass` 状态，`Iterator` Lambda 函数使用这些值来分步执行工作的迭代。  | 
|  `Iterator`  |  引用 `Task` Lambda 函数的 `Iterator` 状态。  | 
| `IsCountReached` | Choice 状态，使用 Iterator 函数的布尔值来决定状态机是否应继续示例工作，或移动到 ShouldRestart 状态。 | 
| `ExampleWork` | Pass 状态，表示 Task 状态将在实际实施中执行工作。 | 
| `ShouldRestart` | Choice 状态，使用 executionCount 值来决定是否应结束一个执行并启动另一个，或直接结束。 | 
| `Restart` | Task 状态，使用 Lambda 函数来启动状态机的新执行。与 Iterator 函数一样，此函数的计数也会递减。Restart 状态将计数的递减值传递给新执行的输入。 | 

## 先决条件
<a name="tutorial-continue-new-prereq"></a>

在开始之前，请仔细阅读[创建使用 Lambda 的 Step Functions 状态机](tutorial-creating-lambda-state-machine.md)教程，确保您熟悉如何同时使用 Lambda 和 Step Functions。

## 第 1 步：创建迭代计数的 Lambda 函数
<a name="tutorial-continue-new-step-1"></a>

**注意**  
如果您已完成[在 Step Functions 中使用 Lambda 函数迭代循环](tutorial-create-iterate-pattern-section.md)教程，可以跳过此步骤并使用该 Lambda 函数。

本节和[在 Step Functions 中使用 Lambda 函数迭代循环](tutorial-create-iterate-pattern-section.md)教程展示了如何使用 Lambda 函数来跟踪计数，例如，状态机中循环的迭代次数。

 以下 Lambda 函数接收 `count`、`index` 和 `step` 的输入值。它返回这些值及更新的 `index` 和一个名为 `continue` 的布尔值。如果 `continue` 小于 `true`，Lambda 函数将 `index` 设置为 `count`。

然后，状态机实施 `Choice` 状态：在 `continue` 为 `true` 时执行一些应用程序逻辑，或在 `continue` 为 `false` 时继续执行 `ShouldRestart`。

### 创建迭代 Lambda 函数
<a name="tutorial-continue-new-create-lambda-function"></a>

1. 打开 [Lambda 控制台](https://console.aws.amazon.com/lambda/home)，然后选择**创建函数**。

1. 在**创建函数**页面上，选择**从头开始创作**。

1. 在**基本信息**部分中，配置您的 Lambda 函数：

   1. 对于**函数名称**，请输入 `Iterator`。

   1. 对于**运行时系统**，选择 **Node.js 16.x**。

   1. 保留页面上的所有默认选项，然后选择**创建函数**。

      创建 Lambda 函数后，记下函数位于页面右上角的 Amazon 资源名称 (ARN)，例如：

      ```
      arn:aws:lambda:region:123456789012:function:Iterator
      ```

1. 将以下 Lambda 函数的**代码复制到 Lambda 控制台中***Iterator***页面的代码源**部分。

   ```
   exports.handler = function iterator (event, context, callback) {
     let index = event.iterator.index;
     let step = event.iterator.step;
     let count = event.iterator.count;
    
     index = index + step;
    
     callback(null, {
       index,
       step,
       count,
       continue: index < count
     })
   }
   ```

   此代码接受 `count`、`index` 和 `step` 的输入值。它将 `index` 递增 `step` 的值，并返回这些值及布尔值 `continue`。如果 `index` 小于 `count`，`continue` 的值为 `true`。

1. 选择**部署**，部署代码。

### 测试迭代 Lambda 函数
<a name="tutorial-continue-new-step-1-test"></a>

使用数字值运行 `Iterate` 函数，查看它的工作情况。您可以为模拟迭代的 Lambda 函数提供输入值，以查看使用特定输入值得到的输出。

#### 测试 Lambda 函数
<a name="tutorial-continue-new-test-lambda-function"></a>

1. 在**配置测试事件**对话框中，选择**创建新测试事件**，然后键入 `TestIterator` 作为**事件名称**。

1. 使用以下内容替换示例数据。

   ```
   {
     "Comment": "Test my Iterator function",
     "iterator": {
       "count": 10,
       "index": 5,
       "step": 1
     }
   }
   ```

   这些值模拟在迭代期间来自状态机的内容。Lambda 函数递增索引并将 `continue` 返回为 `true`。当索引不小于 `count` 时，它会将 `continue` 返回为 `false`。在此测试中，索引已增加到 `5`。结果应将 `index` 增加到 `6`，并将 `continue` 设置为 `true`。

1. 选择**创建**。

1. **在 Lambda 控制台的***Iterator***页面上，确保已列出 **TestIterator**，然后选择 “测试”。**

   测试结果将显示在页面顶部。选择**详细信息**并查看结果。

   ```
   {
     "index": 6,
     "step": 1,
     "count": 10,
     "continue": true
   }
   ```
**注意**  
如果在此测试中将 `index` 设置为 `9`，则 `index` 增加到 `10`，`continue` 为 `false`。

## 第 2 步：创建一个 Restart Lambda 函数，启动新的 Step Functions 执行
<a name="tutorial-continue-new-step-3"></a>

1. 打开 [Lambda 控制台](https://console.aws.amazon.com/lambda/home)，然后选择**创建函数**。

1. 在**创建函数**页面上，选择**从头开始创作**。

1. 在**基本信息**部分中，配置您的 Lambda 函数：

   1. 对于**函数名称**，请输入 `Restart`。

   1. 对于**运行时系统**，选择 **Node.js 16.x**。

1. 保留页面上的所有默认选项，然后选择**创建函数**。

   创建 Lambda 函数后，记下函数位于页面右上角的 Amazon 资源名称 (ARN)，例如：

   ```
   arn:aws:lambda:region:123456789012:function:Iterator
   ```

1. 将以下 Lambda 函数的**代码复制到 Lambda 控制台中***Restart***页面的代码源**部分。

   以下代码可将执行次数的计数递减，并启动状态机的新执行，包括已递减的值。

   ```
   var aws = require('aws-sdk');
   var sfn = new aws.StepFunctions();
   
   exports.restart = function(event, context, callback) {
   
     let StateMachineArn = event.restart.StateMachineArn;
     event.restart.executionCount -= 1;
     event = JSON.stringify(event);
   
     let params = {
         input: event,
         stateMachineArn: StateMachineArn
     };
   
     sfn.startExecution(params, function(err, data) {
         if (err) callback(err);
         else callback(null,event);
     });
   
   }
   ```

1. 选择**部署**，部署代码。

## 第 3 步：创建状态机
<a name="tutorial-continue-new-step-4"></a>

现在，您已创建了两个 Lambda 函数，可以创建状态机。在此状态机中，`ShouldRestart` 和 `Restart` 状态表示如何将工作拆分为多个执行。

**Example ShouldRestart 选择状态**  
下面的示例显示 `ShouldRestart` `Choice` 状态。此状态决定是否应重新开始执行。  

```
"ShouldRestart": {
"Type": "Choice",
"Choices": [
  {
    "Variable": "$.restart.executionCount",
    "NumericGreaterThan": 1,
    "Next": "Restart"
  }
],
```

初始执行的输入中包含 `$.restart.executionCount` 值。每次调用 `Restart` 函数后它会减 1，并置入每个后续执行的输入中。

**Example Restart Task 状态**  
下面的示例显示 `Restart` `Task` 状态。此状态使用您之前创建的 Lambda 函数重新启动执行，并递减计数来跟踪剩余的执行启动次数。  

```
"Restart": {
  "Type": "Task",
  "Resource": "arn:aws:lambda:region:123456789012:function:Restart",
  "Next": "Done"
},
```

**创建状态机**

1. 打开 [Step Functions 控制台](https://console.aws.amazon.com/states/home)，从菜单中选择**状态机**，然后选择**创建状态机**。
**重要**  
[确保您的状态机与您之前在[步骤 1 和步骤 2](#tutorial-continue-new-step-1) 中创建的 Lambda 函数位于相同的 AWS 账户和区域下。](#tutorial-continue-new-step-3)

1. 选择**从空白创建**。

1. 为状态机命名，然后选择**继续**，在 Workflow Studio 中编辑状态机。

1. 在本教程中，您将在[代码编辑器](workflow-studio.md#wfs-interface-code-editor)中编写状态机的 [Amazon States Language](concepts-amazon-states-language.md) (ASL) 定义。要执行此操作，请选择**代码**。

1. 删除现有的样板代码并粘贴以下代码。请记住将此代码 ARNs 中的替换为您创建 ARNs 的 Lambda 函数。

   ```
   {
       "Comment": "Continue-as-new State Machine Example",
       "StartAt": "ConfigureCount",
       "States": {
           "ConfigureCount": {
               "Type": "Pass",
               "Result": {
                   "count": 100,
                   "index": -1,
                   "step": 1
               },
               "ResultPath": "$.iterator",
               "Next": "Iterator"
           },
           "Iterator": {
               "Type": "Task",
               "Resource": "arn:aws:lambda:region:123456789012:function:Iterator",
               "ResultPath": "$.iterator",
               "Next": "IsCountReached"
           },
           "IsCountReached": {
               "Type": "Choice",
               "Choices": [
                   {
                       "Variable": "$.iterator.continue",
                       "BooleanEquals": true,
                       "Next": "ExampleWork"
                   }
               ],
               "Default": "ShouldRestart"
           },
           "ExampleWork": {
               "Comment": "Your application logic, to run a specific number of times",
               "Type": "Pass",
               "Result": {
                 "success": true
               },
               "ResultPath": "$.result",
               "Next": "Iterator"
           },
           "ShouldRestart": {
             "Type": "Choice",
             "Choices": [
               {
                 "Variable": "$.restart.executionCount",
                 "NumericGreaterThan": 0,
                 "Next": "Restart"
               }
             ],
             "Default": "Done"
           },
           "Restart": {
             "Type": "Task",
             "Resource": "arn:aws:lambda:region:123456789012:function:Restart",
             "Next": "Done"
           },
           "Done": {
               "Type": "Pass",
               "End": true 
           }
       }
   }
   ```

1. 为状态机指定一个名称。为此，请选择默认状态机名称旁边的编辑图标**MyStateMachine**。然后，找到**状态机配置**，在**状态机名称**框中指定一个名称。

   对于本教程，请输入名称 **ContinueAsNew**。

1. （可选）在**状态机配置**中，指定其他工作流设置，例如状态机类型及其执行角色。

   在本教程中，请保留**状态机设置**中的所有默认选项。

   如果您之前为状态机[创建了具有正确权限的 IAM 角色](procedure-create-iam-role.md)并想使用该角色，请在**权限**中选择**选择现有角色**，然后从列表中选择一个角色。或者选择**输入角色 ARN**，然后为该 IAM 角色的 ARN 获取该角色。

1. 在**确认角色创建**对话框中，选择**确认**继续。

   您也可以选择**查看角色设置**，返回至**状态机配置**。
**注意**  
如果您删除了 Step Functions 创建的 IAM 角色，Step Functions 在以后无法重新创建该角色。同样，如果您修改了该角色（例如，通过在 IAM 策略中从主体中删除 Step Functions），Step Functions 在以后也无法还原其原始设置。

1. 将这个状态机的 Amazon 资源名称 (ARN) 保存在一个文本文件中。您需要提供 ARN，同时向 Lambda 函数提供权限才能启动新的 Step Functions 执行。

## 第 4 步：更新 IAM 策略
<a name="tutorial-continue-new-step-2"></a>

要确保您的 Lambda 函数有启动 Step Functions 新执行的权限，请为您的 `Restart` Lambda 函数所用的 IAM 角色附加内联策略。有关更多信息，请参阅**《IAM 用户指南》中的[嵌入内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#embed-inline-policy-console)。

**注意**  
您可以更新上个示例的 `Resource` 行，引用 `ContinueAsNew` 状态机的 ARN。这会限制该策略，使它只能启动特定状态机的执行。

****  

```
{
 "Version":"2012-10-17",		 	 	 
 "Statement": [
     {
         "Sid": "VisualEditor0",
         "Effect": "Allow",
         "Action": [
             "states:StartExecution"
         ],
         "Resource": "arn:aws:states:us-east-2:123456789012:stateMachine:ContinueAsNew"
     }
 ]
}
```

## 第 5 步：运行状态机
<a name="tutorial-continue-new-step-5"></a>

要开始执行，请在输入中包含状态机的 ARN，并提供 `executionCount` 以规定启动新执行的次数。

1.  在**ContinueAsNew**页面上，选择 “**开始执行**”。

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

1. 在**启动执行**对话框中，执行以下操作：

   1. （可选）输入自定义执行名称，以便覆盖生成的默认执行名称。
**非 ASCII 名称和日志记录**  
Step Functions 对于状态机、执行、活动和标签接受包含非 ASCII 字符的名称。由于此类字符会 CloudWatch 阻止亚马逊记录数据，因此我们建议您仅使用 ASCII 字符，这样您就可以跟踪 Step Functions 的指标。

   1. 在**输入**框中，输入以下 JSON 输入，运行您的工作流。

      ```
      {
        "restart": {
          "StateMachineArn": "arn:aws:states:region:account-id:stateMachine:ContinueAsNew",
          "executionCount": 4
        }
      }
      ```

   1. 使用您的 `ContinueAsNew` 状态机的 ARN 更新 `StateMachineArn` 字段。

   1. 选择**启动执行**。

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

      要查看执行结果，请在**图表视图**上选择各个状态，然后在[步骤详细信息](concepts-view-execution-details.md#exec-details-intf-step-details)窗格中选择各个选项卡，分别查看每个状态的详细信息，包括输入、输出和定义。有关可在*执行详细信息*页面上查看的执行信息的详细信息，请参阅[执行详细信息概览](concepts-view-execution-details.md#exec-details-interface-overview)。

      **图标视图**显示四个执行中的第一个。在完成之前，它将传递 `Restart` 状态并启动新执行。  
![\[执行图显示了四次执行中的第一次执行。\]](http://docs.aws.amazon.com/zh_cn/step-functions/latest/dg/images/execution-test1.png)

      此执行完成后，您可以查看下一个正在运行的执行。选择顶部的**ContinueAsNew**链接以查看执行列表。您应该可以看到最近关闭的执行，以及 `Restart` Lambda 函数启动的正在进行的执行。

      所有执行全部完成后，您应在列表中看到四个成功完成的执行。启动的首个执行显示您所选的名称，后续执行的名称是自动生成的。  
![\[显示所有执行已完成的说明性屏幕截图。\]](http://docs.aws.amazon.com/zh_cn/step-functions/latest/dg/images/execution-test1-complete.png)