Lambda 集成与 Lambda 代理:优点和缺点

Posted

技术标签:

【中文标题】Lambda 集成与 Lambda 代理:优点和缺点【英文标题】:Lambda Integration vs. Lambda Proxy: Pros and Cons 【发布时间】:2017-07-17 09:19:14 【问题描述】:

您认为在 AWS API Gateway 中使用和不使用代理功能的 Lambda 集成的优缺点是什么(更具体地说,在使用无服务器框架时)?以下是我目前的想法:

Lambda 与代理集成

专业版:人们可以快速进行原型设计和编码,而无需担心所有需要的配置细节(以及重新发明一些***,如通用模板映射等)。 专业版:返回任何状态代码和自定义标头非常容易,同时还有一种通用的方式来读取请求的正文、标头、参数。 缺点:一切都在代码中完成,因此自动生成文档有点困难。依赖项(标头、模型、返回的状态代码)“隐藏”在代码中。

没有代理的 Lambda 集成

缺点:设置它涉及很多更多工作,并且此配置可能会在不同的资源中重复。 专业版:它允许我们解耦 lambda 接收和返回的内容,以及它如何映射到不同的 HTTP 状态代码、标头和有效负载。 专业版:非常有用,因为它预先规定了返回的内容,以及在标头和有效负载方面的要求。 专业版:从长远来看,设置所有内容时的艰苦工作很有用,因为可以将所有内容导出到 Swagger,因此其他人可以使用它为其生成不同的 SDK。

你的想法是什么?您通常使用 Lambda 代理还是普通的 Lambda 集成?你更喜欢什么,为什么?

编辑:到目前为止,由于提到的原因(解耦和说明依赖关系 - 标头、状态代码等 - 预先),我倾向于始终选择不使用代理功能。

【问题讨论】:

不太确定我是否同意你的优缺点,我觉得这个问题很有趣,我想看看其他人的想法,但基于意见的问题不是 *** 的用途。跨度> 【参考方案1】:

没有代理。

我在生产中部署了多个 SLS,其中一些作为内部工具产生了收入。我专门不使用代理。我不想在我的应用程序中依赖 AWS 的结构,所以如果我们不再是朋友,我可以毫不费力地迁移。

至于代理的优点,我认为它们是缺点,因为感觉你也有,缺点是优点。在“让我们移动得超级快”之前,我已经看到了这一切。是的,我们需要敏捷并迅速行动,但不能以思考为代价。我一直和我的工程师一起得到这个,文档/设计不足是一回事,另一件事是一起说“计划的坚果让我们编写代码”。这就是你如何让自己陷入困境,无论你进入市场的速度有多快。如果没有代理(以及对您的项目结构的一些早期规划,也许还有一些好的 DDD 思维),万一世界被烧毁,从 AWS 迁移非常简单。

除此之外,我发现让新的主机跟上 AWS 的速度非常困难。一旦你知道这一切都是肉汁,但开发人员是开发人员,而不是基础设施工程师(我们这些同时做两者的人非常罕见)。抽象化有助于人们在开始他们的艰巨旅程时提高工作效率。我宁愿我的编码器代码也不需要每 20 分钟就 CFN 来打扰我。

【讨论】:

非代理(自定义集成)实际上是锁定到 AWS 堆栈,而不是代理。 @yawl 这取决于您要移动代码的哪一部分。使用非代理允许 lambda 开发保持相对堆栈无关。它可以被剪切并放入一个完全不同的服务中。所有特定于 AWS 的实施都托管在 API Gateway 中,API Gateway 将请求和响应映射到标准化格式。 API Gateway 可以被不同的服务替换,该服务可以被编程为返回相同的输入并期望 lambda 代码具有相同的输出。【参考方案2】:

我们还从 Proxy 开始,因为启动和运行一堆功能真的感觉很快。很快我们就意识到,我们创建了一个与 Proxy 强制我们读取输入和写入输出的方式非常紧密的耦合,并且我们的函数不应该知道这一点,并且应该有更清晰和更简单的接口。然后我们想开始使用AWS Step Functions and that's when we realized we had created functions that really only work with the Proxy integration 编排其中的一些功能。不使用 Step Functions,它们当然不会轻易迁移出去。

不再有代理。

【讨论】:

【参考方案3】:

(编辑:如 cmets 所述,我在 2018 年提到的 AWS 措辞已被删除。也就是说,我对 Lambda 代理与自定义集成的想法仍然存在。)

看起来像 AWS recommends choosing Lambda Proxy Integration for new API development。

注意

Lambda 自定义集成(以前称为 Lambda 集成)是一项遗留技术。我们建议您将 Lambda 代理集成用于任何新 API。有关更多信息,请参阅使用 Lambda 代理集成构建 API Gateway API

我知道使用代理集成而不是自定义集成来启动 API 端点和 lambda 集成要“更快”(在短期内),但我很惊讶这是对 all 的建议 API / Lambda 开发:

我认为 API Gateway 负责处理“HTTP 详细信息”。使用代理集成将(至少一部分)责任强制到 Lambda 函数上。 (即知道如何解释和决定 HTTP 标头、查询参数、状态代码等) 在这样做时,我觉得它混淆支持 Lambda 函数的责任 - Lambda 现在需要处理它被调用执行的任何“业务”逻辑,还需要处理解释传入的 HTTP 值并决定传出的 HTTP 响应值。 当然,您可以实现一个额外的 Lambda 函数层来抽象出 HTTP 详细信息,但这不正是 API Gateway 应该做的吗? 它降低了在其他服务 HTTP 请求之外的上下文中重复使用任何给定 Lambda 函数的能力,除非非 HTTP 客户端将请求格式化为 HTTP 请求。

【讨论】:

该措辞已被删除 是的,那些词已经不存在了,新词是:“Lambda 代理集成...对于许多用例来说,这是首选的集成类型。”docs.aws.amazon.com/apigateway/latest/developerguide/…【参考方案4】:

因为body mapping模板-代理更好。

我不喜欢身体映射模板,因为在导出的 Swagger 中它被转义了,例如:

        uri: "arn:aws:apigateway:us-east-1:dynamodb:action/UpdateItem"
        responses:
          default:
            statusCode: "200"
        requestTemplates:
          application/json: "\n    \"TableName\": \"happy-marketer\",\n    \"Key\"\
            : \n        \"pk\": \n            \"S\": \"project\"\n        ,\n \
            \       \"sk\": \n            \"S\": \"$context.authorizer.claims.email\
            \ $util.urlDecode($input.params('name'))\"\n        \n    ,\n    \"\
            UpdateExpression\": \"SET projectStatus = :c\",\n    \"ExpressionAttributeValues\"\
            : \n        \":c\": \n            \"S\": \"Completed\"\n\n        \n\
            \    \n"
        passthroughBehavior: "never"
        httpMethod: "POST"
        type: "aws"
  /projects/name/status/restore:
    options:
      consumes:
      - "application/json"
      produces:
      - "application/json"
      parameters:
      - name: "name"
        in: "path"

正如您所理解的 - 在本地编辑此类“代码”并部署此 swagger 文件是不好的。此外,当您在浏览器中编辑身体映射模板时 - 您不会收到有关错误 JSON / Apache Velocity 的错误。例如这里我们有一个错误:


  "email": "$context.authorizer.claims.email",
  "nameOld": "$util.urlDecode($input.params('name'))",

  #if ($input.path('$.nameNew') != "")
  "nameNew": "$util.urlDecode($input.path('$.nameNew'))",
  #end

  #if ($input.path('$.ownerNew') != "")
  "ownerNew": "$input.path('$.ownerNew')",
  #end
  
  #if ($input.path('$.shared') != "")
  "shared": $input.json('$.shared')
  #end
  
  #if ($input.path('$.StartDate') != "")
  , "startDate": "$input.path('$.StartDate')"
  #end
  
  #if ($input.path('$.DueDate') != "")
  , "dueDate": "$input.path('$.DueDate')"
  #end

错误是 - 在startDate 之前错了,。我在 Go 中的后端代码没有这样的错误。我不想为 Apache Velocity 编写测试。

此外,代理集成可能更快 - 因为缺少“中间服务”。

【讨论】:

【参考方案5】:

作为最佳实践,我个人会选择代理集成(与 proxy resource 不同)。原因如下:

如果您使用代理集成,VTL 是您必须了解的另一件事。另外,你如何测试你的 VTL 逻辑?我会争辩说,这种逻辑比没有更重要。此外,根据我的经验,调试 VTL 也很糟糕。 将 HTTP 响应映射逻辑在代码中 使其易于测试。此外,您可以使用适配器模式轻松地将 HTTP 响应映射逻辑与端点的业务逻辑分离。

【讨论】:

以上是关于Lambda 集成与 Lambda 代理:优点和缺点的主要内容,如果未能解决你的问题,请参考以下文章

AWS API Gateway - Lambda 代理(集成请求) - 内部服务器错误

为 Lambda 代理集成启用 CORS 支持的问题

如何使用 lambda 代理集成来云化 API 网关资源

使用代理集成时,API 网关和 Lambda 出现 CORS 错误**仅**

API GW Lambda 代理集成 CORS 问题

使用代理集成通过 API Gateway 触发 AWS Lambda