我的任务是研究基于 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.
}
这似乎非常低效且不可靠(如果我错了,请纠正我)。在这个过程中存储了很多状态,我认为这会产生很多故障点。
我的计划是建议我们重新设计整个服务以改用队列/工作器类型的框架,理想情况下端点将一次处理一个工作负载,并且是无状态的。
队列将由服务填充(Jenkins?Lambda?手动?),然后第二个服务将从队列中读取(理想情况下也可以根据需要横向扩展)。
答案 0 :(得分:2)
我想到的是“耦合”,请看这里: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 耦合
这不仅解决了直接耦合方法引入的所有问题,而且还提供了一种在每个 Lambda 发生错误时重放 DLQ 的方法。消息不会丢失或需要外部存储,需求与处理解耦。
答案 1 :(得分:2)
AWS Step Functions 是实现这一目标的一种方式。 Step Functions 用于以您想要的任何方式编排多个 Lambda 函数 - 并行执行、顺序执行或两者的混合。如果需要,您还可以放置等待步骤、条件检查、重试。
您的整体步骤函数可能看起来像这样(假设您希望并行执行 1、2、3。然后当所有这些都完成后,您希望并行执行 4,然后再次并行执行 5 和 6)>
配置也很简单。它接受像下面这样的 JSON
{
"Comment": "An example of the Amazon States Language using a parallel state to execute two branches at the same time.",
"StartAt": "Parallel",
"States": {
"Parallel": {
"Type": "Parallel",
"Next": "Task4",
"Branches": [
{
"StartAt": "Task1",
"States": {
"Task1": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-south-1:XXX:function:XXX",
"End": true
}
}
},
{
"StartAt": "Task2",
"States": {
"Task2": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-south-1:XXX:function:XXX",
"End": true
}
}
},
{
"StartAt": "Task3",
"States": {
"Task3": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-south-1:XXX:function:XXX",
"End": true
}
}
}
]
},
"Task4": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-south-1:XXX:function:XXX",
"Next": "Parallel2"
},
"Parallel2": {
"Type": "Parallel",
"Next": "Final State",
"Branches": [
{
"StartAt": "Task5",
"States": {
"Task5": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-south-1:XXX:function:XXX",
"End": true
}
}
},
{
"StartAt": "Task6",
"States": {
"Task6": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-south-1:XXX:function:XXX",
"End": true
}
}
}
]
},
"Final State": {
"Type": "Pass",
"End": true
}
}
}