代码之家  ›  专栏  ›  技术社区  ›  Ari

递归AWS Lambda函数调用-最佳实践

  •  1
  • Ari  · 技术社区  · 3 年前

    我的任务是研究一个基于awslambda构建的服务,它执行一个长时间运行的任务,即打开和关闭vm。请注意,我来自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.
    }
    

    我的计划是建议我们重新设计整个服务,改用队列/工作者类型的框架,理想情况下,端点一次处理一个工作负载,并且是无状态的。

    1 回复  |  直到 3 年前
        1
  •  2
  •   Jeremy Thompson    3 年前

    我想的是“耦合”,看这里: https://www.jeffersonfrank.com/insights/aws-lambda-design-considerations

    联轴器

    lambda不应该以请求-响应的方式直接耦合到另一个,而是异步的。考虑这样一个场景:当一个S3事件调用一个Lambda函数时,Lambda还需要在同一个微服务中调用另一个Lambda,以此类推。

    enter image description here

    您可能很想实现直接耦合,比如允许lambda1使用awsdk调用lambda2等等。这会导致以下一些问题:

    这个过程可以重新设计为事件驱动的:lambda耦合

    enter image description here

    这不仅解决了直接耦合方法引入的所有问题,而且还提供了在每个Lambda发生错误时重放DLQ的方法。不会丢失任何消息或需要在外部存储任何消息,并且请求与处理分离。

        2
  •  1
  •   Sarthak Jain    3 年前

    AWS Step Functions 是实现这一目标的一种方法。Step函数用于以任意方式编排多个Lambda函数—并行执行、顺序执行或两者的混合。如果需要,您还可以在等待步骤、条件检查和重试之间进行设置。

    整个step函数可能如下所示(假设您希望1、2、3并行执行)。当所有这些都完成后,您需要执行4,然后再次并行执行5和6)

    enter image description here

    {
      "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
        }
      }
    }