实现 亚马逊云科技 Lambda 错误处理模式

作者: 朱利安·伍德 陈 杰 夫和李杰夫 |

这篇文章由首席云应用程序架构师 Jeff Chen 和高级云应用程序架构师 Jeff Li 撰写

事件驱动架构 是一种架构风格,可以帮助您提高敏捷性并构建可靠、可扩展的应用程序。将应用程序拆分为松散耦合的服务可以帮助每项服务独立扩展。分布式、松散耦合的应用程序依靠事件来传达应用程序变更状态。每项服务都使用来自其他服务的事件并发出事件以将状态变化通知其他服务。

在设计分布式应用程序时,处理错误变得更加重要。如果服务无法处理无效的负载、依赖资源可能不可用或服务可能超时,它可能会失败。可能存在可能导致失败的权限错误。亚马逊云科技 服务提供了许多处理错误情况的功能,您可以使用这些功能来提高应用程序的灵活性。

这篇文章探讨了处理故障的三种用例和设计模式。

概述

亚马逊云科技 L am bda 、亚马逊简单队列服务 (Amazon SQS) 、亚马逊 简单通知服务 (Amazon SNS) 和亚马逊 EventB ridge 是构建无服务器事件驱动应用程序 的 核心构建模块。

《 了解调用 Lambda 函数的不同方法》一文 列出了调用 Lambda 函数的三种不同方式:同步、异步和基于轮询的调用。有关服务列表及其使用的调用方法,请参阅 文档

Lambda 与 亚马逊 API Gatew ay 的集成 就是同步调用的一个例子。客户端向 API 网关发出请求,后者向 Lambda 发送请求。API Gateway 等待函数响应并将响应返回给客户端。没有内置的重试或错误处理。如果请求失败,则客户端会再次尝试请求。

Lambda 与 SNS 和 EventBridge 的集成就是异步调用的例子。例如,SNS 会向 Lambda 发送事件进行处理。当 Lambda 收到事件时,它会将其放在内部事件队列中,并向 SNS 返回已收到消息的确认。另一个 Lambda 进程从内部队列读取事件并调用您的 Lambda 函数。如果 SNS 无法将事件传送到您的 Lambda 函数,则该服务会根据重试策略自动重试相同的操作。

Lambda 与 SQS 的集成使用基于轮询的调用。Lambda 运行一组轮询器,这些轮询器会轮询您的 SQS 队列中是否有消息。轮询者分批读取消息,并每批调用一次您的 Lambda 函数。

你可以在许多场景中应用这种模式。例如,您的运营应用程序可以将销售订单添加到运营数据存储中。然后,您可能需要定期将销售订单加载到您的数据仓库,以便信息可用于预测和分析。操作应用程序可以将已完成的销售作为事件进行批处理,并将其放入 SQS 队列中。然后,Lambda 函数可以处理事件并将完成的销售记录加载到您的数据仓库中。

如果您的函数成功处理了批处理,则轮询器将从 SQS 队列中删除消息。如果未成功处理批处理,则轮询者不会从队列中删除消息。 可见性超时 到期后,可以再次对消息进行重新处理。如果 消息保留期 到期,SQS 将从队列中删除消息。

下表显示了上述 亚马逊云科技 服务的调用类型和重试行为。

亚马逊云科技 service example Invocation type Retry behavior
Amazon API Gateway Synchronous No built-in retry, client attempts retries.

亚马逊 SNS

Amazon EventBridge

Asynchronous Built-in retries with exponential backoff.
Amazon SQS Poll-based Retries after visibility timeout expires until message retention period expires.

基于轮询的调用类型和异步调用类型可以使用多种设计模式来保留失败的消息以进行额外处理。这些模式可以帮助您从交付或处理失败中恢复。

您可以通过使用使用 Python 的 亚马逊云科技 云开发套件 (亚马逊云科技 CDK) 部署 此存储库 中的代码 来探索模式并测试场景。

基于 Lambda 民意调查的调用模式

将 Lambda 与 SQS 配合使用时,如果 Lambda 无法处理消息并且消息保留期到期,则 SQS 会删除该消息。无法处理消息可能是由于函数处理失败所致,包括超时或有效负载无效。当目标函数不存在或权限不正确时,也可能发生处理失败。

您可以在源队列 上配置单独的 死信队列 (DLQ) ,让 SQS 保留丢弃的消息。DLQ 保留原始消息,可用于分析根本原因、正确处理错误情况或发送需要手动干预的通知。在基于轮询的调用场景中,Lambda 函数本身不维护 DLQ。它依赖于 SQS 中配置的外部 DLQ。有关更多信息,请参阅将 Lambda 与亚马逊 SQS 搭配 使用

以下内容显示了配置 Lambda 以轮询来自 SQS 队列的事件并调用 Lambda 函数时的设计模式。

Lambda synchronously polling catches of messages from SQS

Lambda 同步轮询来自 SQS 的批量消息

要探索这种模式,请 在此存储库 中部署代码 。部署后,你可以使用此指令测试带有快乐和不愉快路径的模式。

Lambda 异步调用模式

对于异步调用,使用 Lambda 时需要考虑两个故障方面。事件源无法将消息传送到 Lambda,并且在处理事件时出现 Lambda 函数错误。

事件源处理向 Lambda 传送消息的失败的方式各不相同。如果 SNS 或 EventBridge 在用尽所有重试尝试后无法将事件发送到 Lambda,则该服务会删除该事件。您可以在 SNS 主题或 EventBridge 事件总线上配置 DLQ 来保存丢弃的事件。这与 SQS 基于轮询的调用模式的工作方式相同。

然后,Lambda 函数可能会由于输入负载语法错误、持续时间超时或函数抛出异常(例如数据资源不可用)而出错。

对于异步调用,您可以配置 Lambda 在其内部队列中保留事件的时长,最多 6 小时。您还可以配置函数出错时 Lambda 重试的次数,介于 0 和 2 之间。当超过最大期限或所有重试尝试都失败时,Lambda 会丢弃该事件。要保留丢弃事件的副本,您可以在 Lambda 函数配置中配置 DLQ,或者最好配置失败事件 目标

Lambda 目标允许您指定异步调用成功或失败后下一步要做什么。您可以配置目标以将调用记录发送到 SQS、SNS、EventBridge 或其他 Lambda 函数。目的地是故障处理的首选,因为它们支持其他目标并包含其他信息。DLQ 保存原始失败事件。有了目标,Lambda 还会在调用记录中传递函数响应的详细信息。这包括堆栈跟踪,这对于分析根本原因可能很有用。

同时使用 DLQ 和 Lambda 目的地

你可以在许多场景中应用这种模式。例如,您的许多应用程序可能包含客户记录。为了遵守《 加州消费者隐私法》(CCPA) ,不同的组织可能需要删除特定客户的记录。您可以设置消费者删除 SNS 主题。每个组织都创建一个 Lambda 函数,该函数处理 SNS 主题发布的事件并删除其托管应用程序中的客户记录。

以下内容显示了将 SNS 主题配置为 Lambda 函数的事件源时的设计模式,该函数使用目标队列进行成功和失败处理。

SNS topic as event source for Lambda

SNS 主题作为 Lambda 的事件源

您可以在 SNS 主题上配置 DLQ 以捕获 SNS 无法传送到 Lambda 的消息。当 Lambda 调用该函数时,它会将成功处理的消息的详细信息发送到成功的 SQS 目的地。对于更简单的用例,您可以使用此模式将事件路由到多个服务。对于协调多项服务, 亚马逊云科技 Step Func tion s 是更好的设计选择。

Lambda 还可以将未成功处理的消息的详细信息发送到失败时的 SQS 目的地。

这种模式的一种变体是将 SQS 目标替换为 EventBridge 目的地,以便多个使用者可以根据目的地处理事件。

要探索如何使用 SQS DLQ 和 Lambda 目标,请在此存储库中部署代码。 部署后,你可以使用此 指令 测试带有快乐和不愉快路径的模式。

使用 DLQ

尽管目的地是处理函数故障的首选方法,但您可以使用 DLQ 进行探索。

以下内容显示了将 SNS 主题配置为 Lambda 函数的事件源时的设计模式,该函数使用 SQS 队列进行故障处理。

Lambda invoked asynchonously

Lambda 异步调用

您可以在 SNS 主题上配置 DLQ 以捕获 SNS 无法传送到 Lambda 函数的消息。您还可以为 Lambda 函数配置单独的 DLQ。Lambda 在最大重试尝试次数后无法处理失败的事件后,Lambda 将该事件保存到此 DLQ。

要探索如何使用 Lambda DLQ,请在此存储库中部署代码。 部署完成后,你可以使用此 指令 测试带有幸福路径和不愉快路径的模式。

结论

这篇文章解释了可用于设计弹性事件驱动的无服务器应用程序的三种模式。事件处理期间的错误处理是设计无服务器云应用程序的重要组成部分。

您可以部署存储库中的代码,以探索如何使用基于轮询的调用和异步调用。查看基于轮询的调用如何向 DLQ 发送失败消息。查看如何使用 DLQ 和 Lambda 目的地来路由和处理不成功的事件。

详细了解 无服务器 领域的事件驱动架构。