amazon-web-services - 递归 AWS Lambda 函数调用 - 最佳实践
问题描述
我的任务是查看基于 AWS Lambda 构建的服务,该服务执行打开和关闭虚拟机的长期运行任务。请注意,我来自 Azure 团队,所以我不熟悉 AWS 服务的样式或最佳实践。
原始开发人员采用的方法是将整个工作负载发送到一个 Lambda 函数,然后让该函数占用一部分工作负载,然后使用剩余的工作负载递归调用自身,直到所有项目都消失(工作负载 = 0)。
伪代码:
// Assume this gets sent to a HTTP Lambda endpoint as a whole
let workload = [1, 2, 3, 4, 5, 6, 7, 8]
// The Lambda HTTP endpoint
function Lambda(workload) {
if (!workload.length) {
return "No more work!"
}
const toDo = workload.splice(0, 2) // get first two items
doWork(toDo)
// Then... except it builds a new HTTP request with aws sdk
Lambda(workload) // 3, 4, 5, 6, 7, 8, etc.
}
这似乎非常低效且不可靠(如果我错了,请纠正我)。在这个过程中存储了很多状态,我认为这会产生很多故障点。
我的计划是建议我们重新设计整个服务以使用 Queue/Worker 类型的框架,理想情况下,端点一次处理一个工作负载,并且是无状态的。
队列将由一个服务填充(Jenkins?Lambda?手动?),然后第二个服务将从队列中读取(理想情况下也可以根据需要横向扩展)。
解决方案
更新:AWS EventBridge 现在看起来像是首选解决方案。
我想到的是“耦合”,请参见此处:https ://www.jeffersonfrank.com/insights/aws-lambda-design-considerations
耦合
耦合超越了 Lambda 设计考虑——它更多的是关于整个系统。微服务中的 Lambda 有时是紧密耦合的,但只要在微服务的小黑匣子中的 Lambda 之间传递的数据不是过纯的 HTTP 并且不是同步的,这没什么好担心的。
Lambda 不应该以请求响应的方式直接相互耦合,而是异步耦合。考虑当 S3 事件调用 Lambda 函数时的场景,然后该 Lambda 还需要在同一微服务中调用另一个 Lambda,依此类推。
aws lambda 耦合
您可能很想实现直接耦合,例如允许 Lambda 1 使用 AWS 开发工具包调用 Lambda 2 等等。这引入了以下一些问题:
- 如果 Lambda 1 正在同步调用 Lambda 2,则需要等待后者先完成。Lambda 1 可能不知道 Lambda 2 也同步调用了 Lambda 3,而 Lambda 1 现在可能需要等待 Lambda 2 和 3 都成功完成。Lambda 1 可能会超时,因为它需要先等待所有 Lambda 完成,并且您还要在等待时为每个 Lambda 付费。
- 如果 Lambda 3 设置了并发限制并且也被另一个服务调用怎么办?Lambda 2 和 3 之间的调用将失败,直到它再次具有并发性。错误可以一直返回到 Lambda 1,但是 Lambda 1 然后如何处理错误?它必须存储 S3 事件不成功并且需要重播它。
这个过程可以重新设计为事件驱动:lambda 耦合
这不仅解决了直接耦合方法引入的所有问题,而且还提供了在每个 Lambda 发生错误时重放 DLQ 的方法。不会有消息丢失或需要外存,需求与处理解耦。
推荐阅读
- csv - 将 dbf 文件转换为 csv
- windows - 如何使用加密 api 获取颁发者证书公钥
- php - Wordpress 自定义面包屑(多种分类法)
- python - 为具有相似或相同参数的不同函数提供一个依赖于上下文的调用者
- android - API 29 上未显示 Android 通知
- python - 为什么在基本环境中的 Miniconda 与 conda 列表的 pkgs 文件夹中列出的 python 包存在差异?
- javascript - jQuery:在输入值上使用 replace() 不起作用
- sql - SQL减去列
- python - 安装后找不到dash-auth
- c# - 使用输入文件进行 Azure 单元测试