使用 AWS Step Functions 和 AWS Lambda

处理无服务器应用程序中的错误

在本教程中,您将了解如何使用 AWS Step Functions 处理工作流运行时错误。AWS Step Functions 是一种无服务器编排服务,可助您轻松地将多个 Lambda 函数协调到易于调试和更改的灵活工作流中。AWS Lambda 是一项计算服务,让您无需预置或管理服务器即可运行代码。 

Lambda 函数有时会运行失败,例如,当出现未处理的异常、其运行时间超过配置的超时时间或内存不足时。在每个 Lambda 函数中编写和维护错误处理逻辑以处理 API 限制或套接字超时等情况可能既耗时又复杂,对于分布式应用程序而言更是如此。在每个 Lambda 函数中嵌入此代码会在它们之间创建依赖关系,而且随着情况的变化,很难维护所有这些连接。

为避免这种情况,并减少您要编写的错误处理代码的数量,您可以使用 AWS Step Functions 创建支持函数错误处理的无服务器工作流。不论是由开发人员造成的函数异常错误(如未找到文件),还是突发错误(如内存不足),您都可以配置 Step Functions 以基于发生的错误类型使用条件逻辑进行响应。通过以这种方式将工作流逻辑与业务逻辑分离,您可以修改工作流对错误的响应方式,而无需更改 Lambda 函数的业务逻辑。

在本教程中,您将使用 AWS Step Functions 设计和运行无服务器工作流,AWS Step Functions 将妥善处理这些错误。您将创建一个 AWS Lambda 函数,该函数将模拟对 RESTful API 的调用,并返回各种响应代码和异常。然后,您将使用 AWS Step Functions 创建一个具有重试和捕获功能的状态机,根据引发的异常以不同逻辑做出响应。

使用此教程需要拥有 AWS 账户

AWS Step Functions 或 AWS Lambda 不收取任何额外费用。您在本教程中创建的资源符合免费套餐条件。 

详细了解免费套餐 >>


第 1 步:创建 Lambda 函数以模拟 API

在此步骤中,您将创建一个 Lambda 函数来模拟一些基本 API 交互。Lambda 函数根据您在事件参数中输入的错误代码,引发异常以模拟来自虚构 API 的响应。


a.  打开 AWS 管理控制台,您就可以让本分步指南处于打开状态。此屏幕加载后,请输入您的用户名和密码以便开始操作。接下来,在搜索栏中键入 Lambda,选择 Lambda 以打开服务控制台。

(单击可放大)


b.选择创建函数

(单击可放大)


c.让从头开始创作保持选中状态。接下来,按照如下所述配置 Lambda 函数:

名称中,键入 MockAPIFunction
对于运行时,选择 Python 3.6
对于角色,选择创建自定义角色

系统将打开新的 IAM 窗口。保留角色名称lambda_basic_execution,然后单击 允许。您将自动返回到 Lambda 控制台。

单击创建函数​。

(单击可放大)


d.在 MockAPIFunction 屏幕上,向下滚动到函数代码部分。在本教程中,您将创建一个函数,该函数使用编程模型在 Python 中创作 Lambda 函数。在代码窗口中,将所有代码替换为以下代码,然后选择保存

class TooManyRequestsException(Exception): pass
class ServerUnavailableException(Exception): pass
class UnknownException(Exception): pass

def lambda_handler(event, context):
    statuscode = event["statuscode"]    
    if statuscode == "429":
        raise TooManyRequestsException('429 Too Many Requests')
    elif statuscode == "503":
        raise ServerUnavailableException('503 Server Unavailable')
    elif statuscode == "200":
        return '200 OK'
    else:
        raise UnknownException('Unknown error')

(单击可放大)


e.创建 Lambda 函数后,滚动至窗口顶部,并在页面右上角记下其 Amazon 资源名称 (ARN)。Amazon 资源名称 (ARN) 可唯一地标识 AWS 资源,并帮助您跟踪和使用 AWS 服务和 API 调用中的 AWS 项目和策略。当您需要从 Step Functions 引用特定资源时,需要提供 ARN。

(单击可放大)


第 2 步:创建 AWS Identity and Access Management (IAM) 角色

AWS Step Functions 可以执行代码并访问其他 AWS 资源(例如,存储在 Amazon S3 存储桶中的数据)。为了维护安全,您必须使用 AWS Identity and Access Management (IAM) 向 Step Functions 授予对这些资源的访问权限。


a.在另一个浏览器窗口中,导航至 AWS 管理控制台,然后在搜索栏中键入 IAM。击 IAM 以打开服务控制台。

(单击可放大)


b.单击角色,然后选择创建角色

(单击可放大)


c.在选择受信任实体的类型页面上,从“AWS 服务”下的列表中选择 Step Functions,然后选择下一步: 权限

(单击可放大)


d.在附加权限策略页面上,选择下一步: 查看

 

(单击可放大)


e.在查看页面上,键入 step_functions_basic_execution 作为角色名称,然后单击创建角色

(单击可放大)


f.您的新 IAM 角色已创建,显示在 Lambda 函数的 IAM 角色下方的列表中。

(单击可放大)


第 3 步:创建 Step Functions 状态机

现在您已创建可模拟 API 响应的简单 Lambda 函数,接下来您可以创建 Step Functions 状态机以调用 API 并处理异常。

在此步骤中,您将使用 Step Functions 控制台创建一个状态机,该状态机使用带有“重试”和“捕获”字段的任务状态来处理各种 API 响应代码。您将使用任务状态调用模拟 API Lambda 函数,该函数将返回 API 状态代码,供您输入到状态机。


a.打开 AWS Step Functions 控制台。在创建状态机页面上,选择从头开始创作。在详细信息部分中,将您的状态机命名为 MyAPIStateMachine,然后选择我将使用现有角色

(单击可放大)


b.接下来,您将设计一个状态机,根据您模拟 API 的响应采取不同的操作。如果无法访问 API,工作流将重试。重试是解决瞬态错误非常有用的方法。该工作流还会捕获模拟 API 抛出的不同异常。

状态机定义部分的内容替换为以下代码:

{
  "Comment": "An example of using retry and catch to handle API responses",
  "StartAt": "Call API",
  "States": {
    "Call API": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
      "Next" : "OK",
      "Comment": "Catch a 429 (Too many requests) API exception, and resubmit the failed request in a rate-limiting fashion.",
      "Retry" : [ {
        "ErrorEquals": [ "TooManyRequestsException" ],
        "IntervalSeconds": 1,
        "MaxAttempts": 2
      } ],
      "Catch": [ 
        {
          "ErrorEquals": ["TooManyRequestsException"],
          "Next": "Wait and Try Later"
        }, {
          "ErrorEquals": ["ServerUnavailableException"],
          "Next": "Server Unavailable"
        }, {
          "ErrorEquals": ["States.ALL"],
          "Next": "Catch All"
        }
      ]
    },
    "Wait and Try Later": {
      "Type": "Wait",
      "Seconds" : 1,
      "Next" : "Change to 200"
    },
    "Server Unavailable": {
      "Type": "Fail",
      "Error":"ServerUnavailable",
      "Cause": "The server is currently unable to handle the request."
    },
    "Catch All": {
      "Type": "Fail",
      "Cause": "Unknown error!",
      "Error": "An error of unknown type occurred"
    },
    "Change to 200": {
      "Type": "Pass",
      "Result": {"statuscode" :"200"} ,
      "Next": "Call API"
    },
    "OK": {
      "Type": "Pass",
      "Result": "The request has succeeded.",
      "End": true
    }
  }
}

(单击可放大)


c.在“调用 API”任务状态(第 7 行)中找到“资源”行。要将此 ARN 更新为您刚刚创建的模拟 API Lambda 函数的 ARN,请单击 ARN 文本,然后从列表中选择 ARN。

(单击可放大)


d.单击可视工作流窗格旁边的刷新按钮,让 Step Functions 创建与您刚刚设计的工作流相对应的状态机示意图。查看可视工作流后,单击创建状态机

(单击可放大)


第 4 步:测试错误处理工作流

要测试错误处理工作流,您需要输入错误代码,促使状态机调用模拟 API。


a.单击开始执行

(单击可放大)


b.系统将显示一个新的执行对话框,您可以在其中提供状态机输入。您将扮演 API 的部分角色,并提供我们希望模拟 API 返回的错误代码。将现有文本替换为以下代码,然后选择 开始执行

{
    "statuscode": "200"
}

(单击可放大)


c.在执行详细信息屏幕上,单击输入以查看您为状态机提供的输入。接下来,单击输出以查看状态机执行的结果。您可以看到工作流将状态代码 200 解释为成功的 API 调用。

(单击可放大)


d.在可视工作流下,您可以看到每个执行的执行路径,在工作流中以绿色显示。单击“调用 API”任务状态,然后展开步骤详细信息屏幕中的输入输出字段。

您可以看到,此任务状态已使用您提供的输入成功调用了您的模拟 API Lambda 函数,并捕获了 Lambda 函数的输出“200 OK”。

(单击可放大)


e.接下来,单击可视工作流中的“确定”任务状态。在步骤详细信息下,您可以看到上一步骤(“调用 API 任务”状态)的输出已传递为此步骤的输入。“确定”状态即为“传递”状态,它只是将其输入传递到其输出,但不执行任何操作。在构建和调试状态机时,“传递”状态非常有用。

(单击可放大)


第 5 步:检查状态机的执行情况


a.滚动到执行详细信息屏幕的顶部,然后单击 MyAPIStateMachine

(单击可放大)


b.再次单击开始执行,这次提供以下输入,然后单击开始执行

{
    "statuscode": "503"
}

(单击可放大)


c.在执行事件历史记录部分中,展开每个执行步骤以确认您的工作流是否按预期运行。我们预料这次执行会失败,所以不必惊慌! 您将注意到:

  1. Step Functions 捕获了您的输入
  2. 该输入已传递到“调用 API 任务”状态
  3. “调用 API 任务”状态使用该输入调用 MockAPIFunction
  4. 已执行 MockAPIFunction
  5. MockAPIFunction 失败,出现 ServerUnavailableException
  6. “调用 API 任务”状态中的捕获语句捕获到该异常
  7. 捕获语句未通过工作流
  8. 您的状态机已完成执行

(单击可放大)


d.接下来,您将模拟 429 异常。滚动到执行详细信息屏幕的顶部,然后单击 MyAPIStateMachine。单击开始执行,提供以下输入,然后单击开始执行

{
    "statuscode": "429"
}

(单击可放大)


e.现在,您将检查工作流的重试行为。在执行事件历史记录部分,再次展开每个执行步骤,以确认 Step Functions 尝试调用 MockAPILambda 函数两次,而这两次都以失败告终。此时,您的工作流将转换为“等待并稍后尝试”状态(如右图所示),希望 API 只是暂时没有响应。

接下来,“等待”状态使用强力将响应代码更改为 200,并且您的工作流成功完成执行。这可能与您在实际应用程序中处理 429 异常的方式不同,我们为了本教程的需要简化了操作。

(单击可放大)


f.运行工作流的另一个实例,这次提供的随机 API 响应不是由您的状态机处理的:

{
    "statuscode": "999"
}

使用执行事件历史记录再次检查执行。完成后,再次单击 MyAPIStateMachine。在执行窗格中,您可以查看工作流的所有执行历史记录,并根据需要单独查看这些历史记录。

(单击可放大)


第 6 步:终止资源

在此步骤中,您将终止您的 AWS Step Functions 以及与 AWS Lambda 相关的资源。

重要说明:终止当前未在使用的资源可降低成本,是最佳实践。不终止资源可能会产生费用。


a.在 AWS Step Functions 控制台窗口顶部,单击状态机

(单击可放大)


b.在状态机窗口中,单击 MyAPIStateMachine,然后选择删除。在对话框中选择删除状态机,以确认操作。Step Functions 确认任何正在进行的执行均已完成后,您的状态机将在一两分钟内被删除。

(单击可放大)


c.接下来,您将删除 Lambda 函数。单击 AWS 管理控制台菜单中的服务,然后选择 Lambda

(单击可放大)


d.在 Functions 屏幕中,单击 MockAPIFunction,选择操作,然后选择删除。再次单击删除确认删除。

(单击可放大)


e.最后,您将删除 IAM 角色。单击 AWS 管理控制台菜单中的服务,然后选择 IAM

(单击可放大)


f.选择您为本教程创建的两个 IAM 角色,然后单击删除角色。在对话框中单击是,删除以确认删除。


现在,您可以退出 AWS 管理控制台了。

(单击可放大)


恭喜!

您已使用 AWS Step Functions 和 AWS Lambda 为网络 API 创建错误处理工作流。借助 AWS Lambda,您几乎可以为任何类型的应用程序或后端服务运行代码,而且完全无需管理。只需上传您的代码,Lambda 会处理运行和扩展高可用性代码所需的一切工作。

将 AWS Step Functions 与 AWS Lambda 结合使用,可以简化为无服务器应用程序编制 AWS Lambda 函数的流程。Step Functions 允许您使用 Lambda 函数控制复杂的工作流,而无需由底层应用程序管理和编排状态。在使用 Amazon EC2 和 Amazon ECS 等计算资源编排微服务时,您也可以使用 Step Functions。

尝试其他教程

探索 AWS Step Functions


本教程对您是否有帮助?