AWS Lambda
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

教程:将 AWS Lambda 与 Amazon API Gateway 结合使用

在本示例中,您将使用 Amazon API Gateway 创建一个简单 API。Amazon API Gateway 是资源和方法的集合。在本教程中,您将创建一个资源 (DynamoDBManager) 并在其上定义一种方法 (POST)。该方法由 Lambda 函数 (LambdaFunctionOverHttps) 支持。也就是说,当您通过 HTTPS 终端节点调用 API 时,Amazon API Gateway 会调用 Lambda 函数。

DynamoDBManager 资源上的 POST 方法支持以下 DynamoDB 操作:

  • 创建、更新和删除项目。

  • 读取项目。

  • 扫描项目。

  • 与 DynamoDB 不相关且可用于测试的其他操作(echo、ping)。

您在 POST 请求中发送的请求负载可标识 DynamoDB 操作并提供必需数据。例如:

  • 下面是 DynamoDB 创建项目操作的示例请求负载:

    { "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1", "name": "Bob" } } }
  • 下面是 DynamoDB 读取项目操作的示例请求负载:

    { "operation": "read", "tableName": "lambda-apigateway", "payload": { "Key": { "id": "1" } } }
  • 下面是 echo 操作的示例请求负载。您使用请求正文中的以下数据将一个 HTTP POST 请求发送到终端节点。

    { "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }

注意

API 网关 提供高级功能,例如:

  • 传递整个请求 – Lambda 函数可以接收整个 HTTP 请求(而不仅仅是请求正文),并可以使用 AWS_PROXY 集成类型设置 HTTP 响应(而不仅仅是响应正文)。

  • “捕获全部”方法 – 使用 ANY“捕获全部”方法将 API 资源的所有方法映射到具有单个映射的单个 Lambda 函数。

  • “捕获全部”资源 – 使用新路径参数 ({proxy+}) 将资源的所有子路径映射到 Lambda 函数,而无需任何额外配置。

要了解有关这些 API 网关功能的更多信息,请参阅为代理资源配置代理集成

先决条件

This tutorial assumes that you have some knowledge of basic Lambda operations and the Lambda console. If you haven't already, follow the instructions in 开始使用 AWS Lambda to create your first Lambda function.

To follow the procedures in this guide, you will need a command line terminal or shell to run commands. Commands are shown in listings preceded by a prompt symbol ($) and the name of the current directory, when appropriate:

~/lambda-project$ this is a command this is output

For long commands, an escape character (\) is used to split a command over multiple lines.

On Linux and macOS, use your preferred shell and package manager. On Windows 10, you can install the Windows Subsystem for Linux to get a Windows-integrated version of Ubuntu and Bash.

创建执行角色

创建执行角色,向您的函数授予访问 AWS 资源的权限。

创建执行角色

  1. 打开 IAM 控制台中的“角色”页面

  2. 选择 Create role (创建角色)

  3. 创建具有以下属性的角色。

    • Trusted entity (可信任的实体) – Lambda.

    • 角色名称 (角色名称)lambda-apigateway-role

    • 权限 – 具有对 DynamoDB 和 CloudWatch Logs 的权限的自定义策略。

      { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1428341300017", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": "*" }, { "Sid": "", "Resource": "*", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow" } ] }

自定义策略具有函数要将数据写入 DynamoDB 并上传日志所需的权限。记下角色的 Amazon 资源名称 (ARN) 以便稍后使用。

创建函数

以下示例代码接收 Kinesis 事件输入并对其所包含的消息进行处理。为了展示这个过程,代码会将一些传入的事件数据写入 CloudWatch Logs。

注意

有关使用其他语言的示例代码,请参阅 示例函数代码

例 index.js

console.log('Loading function'); var AWS = require('aws-sdk'); var dynamo = new AWS.DynamoDB.DocumentClient(); /** * Provide an event that contains the following keys: * * - operation: one of the operations in the switch statement below * - tableName: required for operations that interact with DynamoDB * - payload: a parameter to pass to the operation being performed */ exports.handler = function(event, context, callback) { //console.log('Received event:', JSON.stringify(event, null, 2)); var operation = event.operation; if (event.tableName) { event.payload.TableName = event.tableName; } switch (operation) { case 'create': dynamo.put(event.payload, callback); break; case 'read': dynamo.get(event.payload, callback); break; case 'update': dynamo.update(event.payload, callback); break; case 'delete': dynamo.delete(event.payload, callback); break; case 'list': dynamo.scan(event.payload, callback); break; case 'echo': callback(null, "Success"); break; case 'ping': callback(null, "pong"); break; default: callback('Unknown operation: ${operation}'); } };

创建函数

  1. 将示例代码复制到名为 index.js 的文件中。

  2. 创建部署程序包。

    $ zip function.zip index.js
  3. 使用 create-function 命令创建 Lambda 函数。

    $ aws lambda create-function --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs8.10 \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role

测试 Lambda 函数。

使用示例事件数据手动调用函数。建议您使用控制台来调用函数,因为控制台 UI 提供了用于查看执行结果(包括执行摘要、代码写入的日志和函数返回的结果)的用户友好型界面(因为控制台始终执行同步执行—使用 RequestResponse 调用类型来调用 Lambda 函数)。

测试 Lambda 函数

  1. 将以下 JSON 复制到文件中并将其保存为 input.txt

    { "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
  2. 执行下面的 invoke 命令:

    $ aws lambda invoke --function-name LambdaFunctionOverHttps \ --payload fileb://input.txt outputfile.txt

使用 Amazon API Gateway 创建 API

在本步骤中,您会将 Lambda 函数与您使用 Amazon API Gateway 创建的 API 中的方法关联并测试端到端体验。也就是说,在将 HTTP 请求发送到 API 方法时,Amazon API Gateway 将调用您的 Lambda 函数。

首先,通过将 Amazon API Gateway 与一种资源 (DynamoDBManager) 和一种方法 (POST) 结合使用来创建 API (DynamoDBOperations)。将 POST 方法与您的 Lambda 函数关联。然后,测试端到端体验。

创建 API

在本教程中,运行以下 create-rest-api 命令来创建 DynamoDBOperations API。

$ aws apigateway create-rest-api --name DynamoDBOperations { "id": "bs8fqo6bp0", "name": "DynamoDBOperations", "createdDate": 1539803980, "apiKeySource": "HEADER", "endpointConfiguration": { "types": [ "EDGE" ] } }

保存 API ID 以供在后续命令中使用。您还需要 API 根资源的 ID。要获取该 ID,请运行 get-resources 命令。

$ API=bs8fqo6bp0 $ aws apigateway get-resources --rest-api-id $API { "items": [ { "path": "/", "id": "e8kitthgdb" } ] }

此时,您仅具有根资源,但您可在下一步中添加更多资源。

在 API 中创建资源

运行以下 create-resource 命令以在您在前一节中创建的 API 中创建资源 (DynamoDBManager)。

$ aws apigateway create-resource --rest-api-id $API --path-part DynamoDBManager \ --parent-id e8kitthgdb { "path": "/DynamoDBManager", "pathPart": "DynamoDBManager", "id": "resource-id", "parentId": "e8kitthgdb" }

记下响应中的 ID。这是您创建的 DynamoDBManager 资源的 ID。

在资源上创建 POST 方法

运行以下 put-method 命令可在您的 API 中的 DynamoDBManager 资源上创建 POST 方法。

$ RESOURCE=iuig5w $ aws apigateway put-method --rest-api-id $API --resource-id $RESOURCE \ --http-method POST --authorization-type NONE { "apiKeyRequired": false, "httpMethod": "POST", "authorizationType": "NONE" }

我们为 --authorization-type 参数指定了 NONE,这意味着针对此方法的未经验证的请求受支持。此方法很适合用于测试,但在生产中,您应使用基于密钥或基于角色的身份验证。

将 Lambda 函数设置为 POST 方法的目标

运行以下命令可将 Lambda 函数设置为 POST 方法的集成点。这是在您对 POST 方法终端节点发出 HTTP 请求时,Amazon API Gateway 所调用的方法。此命令及其他命令使用包含您的账户 ID 和区域的 ARN。将这些命令保存到变量中(您可以在用于创建函数的角色 ARN 中找到您的账户 ID)。

$ REGION=us-east-2 $ ACCOUNT=123456789012 $ aws apigateway put-integration --rest-api-id $API --resource-id $RESOURCE \ --http-method POST --type AWS --integration-http-method POST \ --uri arn:aws:apigateway:$REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:$REGION:$ACCOUNT:function:LambdaFunctionOverHttps/invocations { "type": "AWS", "httpMethod": "POST", "uri": "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps/invocations", "passthroughBehavior": "WHEN_NO_MATCH", "timeoutInMillis": 29000, "cacheNamespace": "iuig5w", "cacheKeyParameters": [] }

--integration-http-method 是 API 网关 用于与 AWS Lambda 通信的方法。--uri 是 Amazon API Gateway 可将请求发送到的终端节点的唯一标识符。

设置对 JSON 的 POST 方法响应和集成响应的 content-type,如下所示:

  • 运行以下命令以设置对 JSON 的 POST 方法响应。这是您的 API 方法返回的响应类型。

    $ aws apigateway put-method-response --rest-api-id $API \ --resource-id $RESOURCE --http-method POST \ --status-code 200 --response-models application/json=Empty { "statusCode": "200", "responseModels": { "application/json": "Empty" } }
  • 运行以下命令以设置对 JSON 的 POST 方法集成响应。这是 Lambda 函数返回的响应类型。

    $ aws apigateway put-integration-response --rest-api-id $API \ --resource-id $RESOURCE --http-method POST \ --status-code 200 --response-templates application/json="" { "statusCode": "200", "responseTemplates": { "application/json": null } }

部署 API

在本步骤中,您会将您创建的 API 部署到名为 prod 的阶段。

$ aws apigateway create-deployment --rest-api-id $API --stage-name prod { "id": "20vgsz", "createdDate": 1539820012 }

向 API 授予调用权限

既然您已使用 Amazon API Gateway 创建并部署了一个 API,您便可以进行测试了。首先,您需要添加权限,以便 Amazon API Gateway 在您将 HTTP 请求发送到 POST 方法时能够调用 Lambda 函数。

为此,您需要向与 Lambda 函数关联的权限策略添加权限。运行以下 add-permission AWS Lambda 命令可为 Amazon API Gateway 服务委托人 (apigateway.amazonaws.com) 授予调用 Lambda 函数 (LambdaFunctionOverHttps) 的权限。

$ aws lambda add-permission --function-name LambdaFunctionOverHttps \ --statement-id apigateway-test-2 --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:$REGION:$ACCOUNT:$API/*/POST/DynamoDBManager" { "Statement": "{\"Sid\":\"apigateway-test-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1yprki7/*/POST/DynamoDBManager\"}}}" }

您必须授权此权限才能启用测试(如果您转到 Amazon API Gateway 并选择 Test 来测试 API 方法,则需要此权限)。请注意,--source-arn 将通配符 (*) 指定为了阶段值(仅指示测试)。这使您无需部署 API 即可进行测试。

现在,再次运行同一命令,但这次您将向已部署的 API 授予调用 Lambda 函数的权限。

$ aws lambda add-permission --function-name LambdaFunctionOverHttps \ --statement-id apigateway-prod-2 --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:$REGION:$ACCOUNT:$API/prod/POST/DynamoDBManager" { "Statement": "{\"Sid\":\"apigateway-prod-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1yprki7/prod/POST/DynamoDBManager\"}}}" }

您授予此权限是为了让已部署的 API 有权调用 Lambda 函数。请注意,--source-arn 指定了 prod,这是我们在部署 API 时使用的阶段名称。

创建 Amazon DynamoDB 表

创建 Lambda 函数使用的 DynamoDB 表。

创建 DynamoDB 表

  1. 打开 DynamoDB 控制台

  2. 选择 Create Table

  3. 使用以下设置创建表。

    • 表名称lambda-apigateway

    • 主键id(字符串)

  4. 选择 Create

使用 HTTP 请求触发函数

在本步骤中,您已准备好向 POST 方法终端节点发送 HTTP 请求。您可使用 Curl 或 Amazon API Gateway 提供的方法 (test-invoke-method)。

您可使用 Amazon API Gateway CLI 命令向资源 (DynamoDBManager) 终端节点发送 HTTP POST 请求。因为您已部署 Amazon API Gateway,所以可以使用 Curl 来调用相应的方法来实现同一操作。

Lambda 函数支持使用 create 操作在 DynamoDB 表中创建项目。要请求此操作,请使用以下 JSON:

例 create-item.json

{ "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1234ABCD", "number": 5 } } }

将测试输入保存到一个名为 create-item.json 的文件中。运行 test-invoke-method Amazon API Gateway 命令可将 HTTP POST 方法请求发送到资源 (DynamoDBManager) 终端节点。

$ aws apigateway test-invoke-method --rest-api-id $API \ --resource-id $RESOURCE --http-method POST --path-with-query-string "" \ --body file://create-item.json

或者,您也可以使用以下 Curl 命令:

$ curl -X POST -d "{\"operation\":\"create\",\"tableName\":\"lambda-apigateway\",\"payload\":{\"Item\":{\"id\":\"1\",\"name\":\"Bob\"}}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager

要发送对您的 Lambda 函数支持的 echo 操作的请求,可使用以下请求负载:

例 echo.json

{ "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }

将测试输入保存到一个名为 echo.json 的文件中。运行 test-invoke-method Amazon API Gateway CLI 命令可使用请求正文中前面的 JSON 代码向资源 (DynamoDBManager) 终端节点发送 HTTP POST 方法请求。

$ aws apigateway test-invoke-method --rest-api-id $API \ --resource-id $RESOURCE --http-method POST --path-with-query-string "" \ --body file://echo.json

或者,您也可以使用以下 Curl 命令:

$ curl -X POST -d "{\"operation\":\"echo\",\"payload\":{\"somekey1\":\"somevalue1\",\"somekey2\":\"somevalue2\"}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager