Lambda集成与Lambda代理:优缺点

53
你认为AWS API Gateway中使用Lambda集成时,使用代理功能和不使用代理功能的优缺点是什么(特别是在使用Serverless框架时)?目前我的想法如下:
Lambda集成(使用代理功能)
- 优点:可以快速原型设计和编码,无需担心所有必要的配置细节(并且不需要重新发明一些通用模板映射等)。 - 优点:非常容易返回任何状态代码和自定义标头,同时有一种通用的方式来读取请求的正文、标头和参数。 - 缺点:所有代码都是在代码中完成的,因此自动生成文档有点更加困难。依赖项(标头、模型、返回状态代码)“隐藏”在代码中。
Lambda集成(不使用代理功能)
- 缺点:涉及大量工作来设置它,并且这个配置可能在不同的资源中被复制。 - 优点:它允许将Lambda接收和返回以及如何映射到不同的HTTP状态代码、标头和有效负载进行解耦。 - 优点:非常有用,因为它预先规定了它返回什么,以及在标头和有效负载方面需要什么。 - 优点:在设置所有内容时辛苦是有意义的,因为可以将所有内容导出到Swagger,以便他人可以使用它来生成不同的SDK。
你的想法是什么?通常你使用Lambda代理还是普通的Lambda集成?你更喜欢哪种方式,为什么?
编辑:目前,我倾向于始终选择不使用代理功能,因为可以解耦并事先说明依赖项(标头、状态代码等)。

4
我不确定我是否同意你的利弊分析,同时我认为这个问题很有趣,想知道其他人的看法。但是,基于个人观点的问题并不适合在stackoverflow上提问。请理解。 - Josep Valls
5个回答

18

(编辑:如评论所述,我在2018年指出的AWS措辞已被删除。尽管如此,我的关于Lambda代理与自定义集成的想法仍然保持不变。)

看起来AWS 推荐为新的API开发选择Lambda Proxy Integration。

注意

Lambda自定义集成(以前称为Lambda集成)是一种传统技术。我们建议您为任何新的API使用Lambda代理集成。更多信息,请参阅使用Lambda代理集成构建API Gateway API

我知道使用代理集成来快速启动API端点和Lambda集成比使用自定义集成要快,但我很惊讶它是所有API/Lambda开发的推荐方式:

  • 我认为API Gateway应该负责处理“HTTP细节”。使用代理集成会把这个责任(至少是其子集)强加到Lambda函数上。(即知道如何解释并决定HTTP头部、查询参数、状态码等)
  • 在这样做的过程中,我感觉它混淆了支持Lambda函数的责任——Lambda现在既需要处理被调用时所需的“业务”逻辑,并且还需要处理解释传入的HTTP值并决定发送的HTTP响应值。
  • 当然,您可以实现一个额外的Lambda函数层来抽象掉HTTP细节,但这不是API Gateway应该做的吗?
  • 它降低了在服务HTTP请求之外的任何上下文中重用任何给定Lambda函数的能力,除非非HTTP客户端将请求格式化为HTTP请求。

  • 9
    那些冗长的措辞已被删除。 - Chazt3n
    4
    是的,那些词不再使用,新的词是:“Lambda代理集成... 对于许多用例,这种集成类型是首选。” https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-getting-started-with-rest-apis.html - yawl

    4
    我们最初采用代理(Proxy)是因为它让我们能够快速地启动一堆功能。很快,我们就意识到,我们与代理的耦合度非常高,而我们的函数不应该知道这一点,应该拥有更清晰和更简单的接口。然后,我们想要使用AWS Step Functions来编排其中一些函数,但我们意识到我们创建的函数只适用于代理集成,而不适用于Step Functions,并且它们肯定不容易迁移。不再使用代理。

    3

    由于Body Mapping模板-代理更好。

    aws api gateway body mapping template dynamodb apache velocity

    我不喜欢使用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编写测试。
    另外,也许代理集成更快 - 因为缺少“中间服务”。

    2

    没有代理。

    我在生产中有几个SLS部署,一些产生收入,一些作为内部工具。我专门使用无代理。我不想依赖AWS的结构来运行我的应用程序,这样如果我们不再是朋友,我可以轻松迁移而不会太痛苦。

    至于代理的优点,我认为它们是缺点,因为感觉你必须这样做,而缺点却成了优点。我以前见过这种情况,“让我们快速前进”。是的,我们需要敏捷并快速移动,但不能以思考为代价。我经常遇到这种情况,我的工程师总是低估文档/设计,但完全放弃计划只是编码。这就是你把自己逼入困境的方式,无论你有多快进入市场。没有代理(并且对项目结构进行一些早期规划,也许还有一些良好的DDD思考),如果世界崩溃了,迁移非常简单。

    此外,我发现很难让新手掌握AWS的知识。一旦你知道了,一切都很顺利,但开发人员只是开发人员,不是基础设施工程师(那些同时做这两件事的人非常罕见)。抽象化可以帮助人们在开始他们艰难的旅程时提高生产力。我宁愿我的程序员编码,而不需要每20分钟打扰我关于CFN的问题。


    6
    非代理(自定义集成)实际上是对 AWS 堆栈的锁定,而不是代理。 - yawl
    1
    @yawl 这取决于您要移动的代码部分。使用非代理允许Lambda开发保持相对堆栈无关。它可以被剪切并粘贴到完全不同的服务中。所有特定于AWS的实现都托管在API网关中,该网关执行请求和响应映射到标准化格式。API网关可以被另一个服务替换,该服务可以编程返回Lambda代码相同的输入并期望相同的输出。 - Ben Arena

    1
    作为最佳实践,我个人会选择代理集成(与代理资源不同)。原因如下:
    • 如果您不使用代理集成,则需要学习VTL。此外,您如何测试VTL逻辑?我认为这种逻辑更多是业务相关的。而且,根据我的经验,调试VTL非常糟糕。
    • 将HTTP响应映射逻辑放在代码中使其易于测试。此外,您可以使用适配器模式轻松将HTTP响应映射逻辑与端点的业务逻辑解耦。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接