aws api gateway&lambda:多个端点/功能与单个端点

Chr*_*ris 36 api amazon-web-services aws-lambda aws-api-gateway

我有一个AWS api代理lamba函数.我目前使用不同的端点和单独的lambda函数:

api.com/getData --> getData
api.com/addData --> addData
api.com/signUp --> signUp
Run Code Online (Sandbox Code Playgroud)

管理所有端点和功能的过程变得很麻烦.当我将一个端点用于一个lambda函数时,是否有任何缺点,该函数根据查询字符串决定做什么?

api.com/exec&func=getData --> exec --> if(params.func === 'getData') { ... }
Run Code Online (Sandbox Code Playgroud)

Dav*_*ple 40

将多个方法映射到单个lambda函数是完全有效的,并且今天许多人正在使用这种方法,而不是为每个离散方法创建api网关资源和lambda函数.

您可以考虑将所有请求代理到单个函数.请查看以下有关创建API网关=> Lambda代理集成的文档:http: //docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html

他们的榜样很棒.请求如下:

POST /testStage/hello/world?name=me HTTP/1.1
Host: gy415nuibc.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
headerName: headerValue

{
    "a": 1
}
Run Code Online (Sandbox Code Playgroud)

最终将以下事件数据发送到您的AWS Lambda函数:

{
  "message": "Hello me!",
  "input": {
    "resource": "/{proxy+}",
    "path": "/hello/world",
    "httpMethod": "POST",
    "headers": {
      "Accept": "*/*",
      "Accept-Encoding": "gzip, deflate",
      "cache-control": "no-cache",
      "CloudFront-Forwarded-Proto": "https",
      "CloudFront-Is-Desktop-Viewer": "true",
      "CloudFront-Is-Mobile-Viewer": "false",
      "CloudFront-Is-SmartTV-Viewer": "false",
      "CloudFront-Is-Tablet-Viewer": "false",
      "CloudFront-Viewer-Country": "US",
      "Content-Type": "application/json",
      "headerName": "headerValue",
      "Host": "gy415nuibc.execute-api.us-east-1.amazonaws.com",
      "Postman-Token": "9f583ef0-ed83-4a38-aef3-eb9ce3f7a57f",
      "User-Agent": "PostmanRuntime/2.4.5",
      "Via": "1.1 d98420743a69852491bbdea73f7680bd.cloudfront.net (CloudFront)",
      "X-Amz-Cf-Id": "pn-PWIJc6thYnZm5P0NMgOUglL1DYtl0gdeJky8tqsg8iS_sgsKD1A==",
      "X-Forwarded-For": "54.240.196.186, 54.182.214.83",
      "X-Forwarded-Port": "443",
      "X-Forwarded-Proto": "https"
    },
    "queryStringParameters": {
      "name": "me"
    },
    "pathParameters": {
      "proxy": "hello/world"
    },
    "stageVariables": {
      "stageVariableName": "stageVariableValue"
    },
    "requestContext": {
      "accountId": "12345678912",
      "resourceId": "roq9wj",
      "stage": "testStage",
      "requestId": "deef4878-7910-11e6-8f14-25afc3e9ae33",
      "identity": {
        "cognitoIdentityPoolId": null,
        "accountId": null,
        "cognitoIdentityId": null,
        "caller": null,
        "apiKey": null,
        "sourceIp": "192.168.196.186",
        "cognitoAuthenticationType": null,
        "cognitoAuthenticationProvider": null,
        "userArn": null,
        "userAgent": "PostmanRuntime/2.4.5",
        "user": null
      },
      "resourcePath": "/{proxy+}",
      "httpMethod": "POST",
      "apiId": "gy415nuibc"
    },
    "body": "{\r\n\t\"a\": 1\r\n}",
    "isBase64Encoded": false
  }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以访问所有标题,url参数,正文等,您可以使用它来在单个Lambda函数中以不同方式处理请求(基本上实现您自己的路由).

作为一种观点,我看到了这种方法的一些优点和缺点.其中许多取决于您的具体用例:

  • 部署:如果每个lambda函数都是离散的,那么您可以单独部署它们,这可以降低代码更改带来的风险(微服务策略).相反,您可能会发现需要单独部署功能会增加复杂性并且非常繁琐.
  • 自我描述:API Gateway的界面使您可以非常直观地查看RESTful端点的布局 - 名词和动词一目了然.实现您自己的路由可能会牺牲这种可见性.
  • Lambda大小和限制:如果您代理所有 - 那么您最终需要选择适合所有RESTful端点的实例大小,超时等.如果创建离散函数,则可以更仔细地选择最符合特定调用需求的内存占用,超时,死信行为等.

  • 很好的答案.对我而言我唯一没有想到的优势是:Lambda大小和限制.但是,我认为优势超过了这个因素.我也可能将它分成两个端点来满足不同类型的请求.1.具有有限lambda资源的简单数据库查询和2.使用更强大的资源计算繁重的函数. (4认同)

Pål*_*ver 19

AWS 官方博文“组织大型无服务器应用程序的最佳实践”中也讨论了类似的场景中也讨论了类似的场景。

\n

一般建议是将“整体 lambda”拆分为单独的 lambda,并将路由移至 API 网关。

\n

这是博客中关于“整体 lambda”方法的描述:

\n
\n

这种方法通常是不必要的,\xe2\x80\x99s 通常最好利用 API Gateway 中可用的本机路由功能。\n...\nAPI Gateway 还能够验证参数,从而减少\n需求用于使用自定义代码检查参数。它还可以提供针对未经授权的访问的保护,以及一系列更适合在服务级别处理的其他功能。

\n
\n

从这里开始:\n具有整体 lambda 函数的 AWS 应用程序

\n

对此

\n

具有单独 lambda 函数的 AWS 应用程序

\n

  • “/orders” Lambda 是否在同一处理程序中处理 GET、POST、PUT 等请求?或者每个方法都有一个单独的 Lambda?它会在 API 网关中分支,还是在“主”“/orders” Lambda 中分支? (2认同)

小智 13

我一直在使用Lambda-API网关构建5~6个微服务,经历了几次尝试失败并取得了成功.

简而言之,根据我的经验,最好只使用一个APIGateway通配符映射将所有API调用委托给lambda,例如

/api/{+proxy} -> Lambda
Run Code Online (Sandbox Code Playgroud)

如果你曾经使用像葡萄这样的任何框架你知道在制作API时,
"中间件",
"全局异常处理",
"级联路由",
"参数验证"

等功能真的很重要.随着API的增长,几乎不可能使用API​​网关映射管理所有路由,也不支持API网关支持这些功能.

更进一步,为开发或部署打破每个端点的lambda实际上并不是真的.

从你的例子来看,

api.com/getData --> getData  
api.com/addData --> addData  
api.com/signUp --> signUp  
Run Code Online (Sandbox Code Playgroud)

想象你有数据ORM,用户身份验证逻辑,通用视图文件(如data.erb)..然后你将如何分享?

你可能会破坏,

api/auth/{+proxy} -> AuthServiceLambda  
api/data/{+proxy} -> DataServiceLambda  
Run Code Online (Sandbox Code Playgroud)

但不像"每个端点".您可以查找有关如何拆分服务的微服务概念和最佳实践

像功能的web框架,结帐这个因为我需要这在我公司拉姆达我们刚刚建立的Web框架.


Ins*_*or6 9

我想评论只是为Dave Maple的答案添加几点,但我还没有足够的声望点,所以我会在这里添加评论.

我开始沿着指向一个Lambda函数的多个端点的路径前进,该函数可以通过访问Event的'resource'属性来处理每个端点.在尝试之后,我现在将它们分成单独的函数,原因是Dave建议加上:

  • 当函数分离时,我发现更容易通过日志和监视器.
  • 作为初学者,我最初没有注意到的一个细微差别是你可以拥有一个代码库并部署与多个Lambda函数完全相同的代码.这使您可以在代码库中获得功能分离的好处以及整合方法的优势.
  • 您可以使用AWS CLI自动执行多个功能中的任务,以减少/消除管理单独功能的缺点.例如,我有一个脚本,使用相同的代码更新10个函数.

  • @Blackwood,这是一个完全有效的答案恕我直言,并满足OP的需求(这是考虑到利弊,而不提供明确的解决方案). (7认同)
  • @Blackwood:我认为这个答案直接解决了OP所提出的问题并且完全相关.我也有兴趣知道这是Lambda的新手,现在我的想法非常明确! (4认同)

小智 5

将 API 请求映射到 AWS 中的 Lambda 的责任是通过网关的 API 规范来处理的。

URL 路径和 HTTP 方法的映射以及数据验证应该留给网关。还有权限和 API 范围的问题;您将无法以正常方式利用 API 范围和 IAM 权限级别。

就编码而言,在 Lambda 处理程序内部复制此机制是一种反模式。沿着这条路线走下去,很快就会得到类似于 Node Express 服务器的路由,而不是 Lambda 函数。

在 API Gateway 后面设置了 50 多个 Lambda 后,我可以说函数处理程序应尽可能保留为转储,从而使它们能够独立于调用它们的上下文而重复使用。