到目前为止, 此博客已经解释了无服务器应用程序的以下概念:
无服务器系列中的第三个博客将解释如何使用Amazon API Gateway,AWS Lambda和Couchbase创建简单的微服务。
阅读以前的博客以获取有关AWS Lambda的更多上下文。
Amazon API Gateway是一项完全托管的服务,使开发人员可以轻松地创建,发布,维护,监控和保护各种规模的API。 Amazon API Gateway处理与接受和处理多达数十万个并发API调用有关的所有任务,包括流量管理,授权和访问控制,监视以及API版本管理。
以下是此体系结构中的关键组件:
- 客户端可以是curl,AWS CLI,Postman客户端或可以调用REST端点的任何其他工具/ API。
- API网关用于配置API。 顶级资源位于path
/books
。 为该资源发布了HTTPGET
和POST
方法。 - 每个API都会触发Lambda函数。 创建了两个Lambda函数,用于列出所有可用
book-create
的书籍book-list
功能,以及用于创建新书籍的书籍book-create
功能。 - Couchbase在EC2中用作持久性存储。 所有JSON文档都将从该数据库中存储和检索。
让我们开始吧!
创建IAM角色
IAM角色将具有策略和信任关系,这些策略和信任关系将允许该角色在API网关中使用并执行Lambda函数。
让我们创建一个新的IAM角色:
aws iam create-role \
--role-name microserviceRole \
--assume-role-policy-document file://./trust.json
--assume-role-policy-document
定义了信任关系策略文档,该文档授予实体担任角色的权限。 trust.json
位于github.com/arun-gupta/serverless/blob/master/aws/microservice/trust.json ,看起来像:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
这种信任关系允许Lambda函数和API网关在执行期间担当此角色。
与此角色相关联的策略为:
aws iam put-role-policy \
--role-name microserviceRole \
--policy-name microPolicy \
--policy-document file://./policy.json
policy.json
位于github.com/arun-gupta/serverless/blob/master/aws/microservice/policy.json ,看起来像:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"apigateway:*"
],
"Resource": "arn:aws:apigateway:*::/*"
},
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": "arn:aws:execute-api:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"lambda:*"
],
"Resource": "*"
}
]
}
这种慷慨的策略允许对CloudWatch中为所有资源生成的日志具有任何权限。 另外,它允许对所有资源的所有Lambda和API网关权限。 通常,仅将所需的策略分配给特定资源。
创建Lambda函数
使用AWS Lambda和Java的无服务器FaaS中介绍了创建Lambda函数的详细步骤。 让我们根据需要创建两个Lambda函数:
aws lambda create-function \
--function-name MicroserviceGetAll \
--role arn:aws:iam::598307997273:role/microserviceRole \
--handler org.sample.serverless.aws.couchbase.BucketGetAll \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--description "Microservice HTTP Endpoint - Get All" \
--runtime java8 \
--region us-west-1 \
--timeout 30 \
--memory-size 1024 \
--environment Variables={COUCHBASE_HOST=ec2-52-53-193-176.us-west-1.compute.amazonaws.com} \
--publish
此功能中需要注意的几个关键项目是:
- 此处明确指定了在上一步中创建的IAM角色
microserviceRole
- 处理程序是
org.sample.serverless.aws.couchbase.BucketGetAll
类。 此类查询使用COUCHBASE_HOST
环境变量定义的Couchbase数据库。
创建第二个Lambda函数:
aws lambda create-function \
--function-name MicroservicePost \
--role arn:aws:iam::598307997273:role/microserviceRole \
--handler org.sample.serverless.aws.couchbase.BucketPost \
--zip-file fileb:///Users/arungupta/workspaces/serverless/aws/microservice/microservice-http-endpoint/target/microservice-http-endpoint-1.0-SNAPSHOT.jar \
--description "Microservice HTTP Endpoint - Post" \
--runtime java8 \
--region us-west-1 \
--timeout 30 \
--memory-size 1024 \
--environment Variables={COUCHBASE_HOST=ec2-52-53-193-176.us-west-1.compute.amazonaws.com} \
--publish
此函数的处理程序是org.sample.serverless.aws.couchbase.BucketPost
类。 此类在由COUCHBASE_HOST
环境变量标识的Couchbase数据库中创建一个新的JSON文档。
这些类的完整源代码位于github.com/arun-gupta/serverless/tree/master/aws/microservice/microservice-http-endpoint 。
API网关资源
使用Amazon API Gateway创建API并进行测试并构建API以公开Lambda函数,提供了有关如何使用API Gateway和Lambda函数来构建强大的后端系统的详细步骤和说明。 如果您想减少追踪,此博客将快速介绍这些步骤。
让我们创建API网关资源。
- 第一步是创建一个API:
aws apigateway \
create-rest-api \
--name Book
输出显示为:
{
"name": "Book",
"id": "lb2qgujjif",
"createdDate": 1482998945
}
id
属性的值为API ID。 在我们的例子中,这是lb2qgujjif
。
- 查找创建的API的ROOT ID,这是下一次AWS CLI调用所必需的:
aws apigateway get-resources --rest-api-id lb2qgujjif
显示输出:
{
"items": [
{
"path": "/",
"id": "hgxogdkheg"
}
]
}
id
属性的值为ROOT ID。 这也是顶级资源的父ID。
- 创建资源
aws apigateway create-resource \
--rest-api-id lb2qgujjif \
--parent-id hgxogdkheg \
--path-part books
显示输出:
{
"path": "/books",
"pathPart": "books",
"id": "vrpkod",
"parentId": "hgxogdkheg"
}
id
属性的值是RESOURCE ID。
API ID和RESOURCE ID用于后续的AWS CLI调用。
API网关POST方法
现在已经创建了资源,让我们在该资源上创建HTTP POST
方法。
- 创建一个
POST
方法
aws apigateway put-method \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method POST \
--authorization-type NONE
查看响应:
{
"apiKeyRequired": false,
"httpMethod": "POST",
"authorizationType": "NONE"
}
- 将Lambda函数设置为POST方法的目标:
aws apigateway put-integration \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method POST \
--type AWS \
--integration-http-method POST \
--uri arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:<act-id>:function:MicroservicePost/invocations
确保将<act-id>
替换为您的AWS账户ID。 这里也使用上一部分的API ID和资源ID。 --uri
用于指定集成输入的URI。 URI的格式是固定的。 此CLI将结果显示为:
{
"httpMethod": "POST",
"passthroughBehavior": "WHEN_NO_MATCH",
"cacheKeyParameters": [],
"type": "AWS",
"uri": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:<act-id>:function:MicroservicePost/invocations",
"cacheNamespace": "vrpkod"
}
- 设置POST方法响应的
content-type
:
aws apigateway put-method-response \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method POST \
--status-code 200 \
--response-models "{\"application/json\": \"Empty\"}"
查看响应:
{
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
- 设置POST方法集成响应的
content-type
:
aws apigateway put-integration-response \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method POST \
--status-code 200 \
--response-templates "{\"application/json\": \"Empty\"}"
查看响应:
{
"statusCode": "200",
"responseTemplates": {
"application/json": "Empty"
}
}
- 部署API
aws apigateway create-deployment \
--rest-api-id lb2qgujjif \
--stage-name test
看到回应
{
"id": "9wi991",
"createdDate": 1482999187
}
- 授予权限以允许API网关调用Lambda函数:
aws lambda add-permission \
--function-name MicroservicePost \
--statement-id apigateway-test-post-1 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-1:<act-id>:lb2qgujjif/*/POST/books"
此外,向部署的API授予权限:
aws lambda add-permission \
--function-name MicroservicePost \
--statement-id apigateway-test-post-2 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-1:<act-id>:lb2qgujjif/test/GET/books"
- 测试API方法:
aws apigateway test-invoke-method \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method POST \
--path-with-query-string "" \
--body "{\"id\": \"1\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}"
查看响应:
{
"status": 200,
"body": "Empty",
"log": "Execution log for request test-request\nThu Dec 29 08:16:05 UTC 2016 : Starting execution for request: test-invoke-request\nThu Dec 29 08:16:05 UTC 2016 : HTTP Method: POST, Resource Path: /books\nThu Dec 29 08:16:05 UTC 2016 : Method request path: {}\nThu Dec 29 08:16:05 UTC 2016 : Method request query string: {}\nThu Dec 29 08:16:05 UTC 2016 : Method request headers: {}\nThu Dec 29 08:16:05 UTC 2016 : Method request body before transformations: {\"id\": \"1\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}\nThu Dec 29 08:16:05 UTC 2016 : Endpoint request URI: https://lambda.us-west-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-1:598307997273:function:MicroservicePost/invocations\nThu Dec 29 08:16:05 UTC 2016 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************c8bb85, X-Amz-Date=20161229T081605Z, x-amzn-apigateway-api-id=lb2qgujjif, X-Amz-Source-Arn=arn:aws:execute-api:us-west-1:598307997273:lb2qgujjif/null/POST/books, Accept=application/json, User-Agent=AmazonAPIGateway_lb2qgujjif, Host=lambda.us-west-1.amazonaws.com, X-Amz-Content-Sha256=559d0296d96ec5647eef6381602fe5e7f55dd17065864fafb4f581d106aa92f4, X-Amzn-Trace-Id=Root=1-5864c645-8494974a41a3a16c8d2f9929, Content-Type=application/json}\nThu Dec 29 08:16:05 UTC 2016 : Endpoint request body after transformations: {\"id\": \"1\", \"bookname\": \"test book\", \"isbn\": \"123\", \"cost\": \"1.23\"}\nThu Dec 29 08:16:10 UTC 2016 : Endpoint response body before transformations: \"{\\\"cost\\\":\\\"1.23\\\",\\\"id\\\":\\\"1\\\",\\\"bookname\\\":\\\"test book\\\",\\\"isbn\\\":\\\"123\\\"}\"\nThu Dec 29 08:16:10 UTC 2016 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=0b25323b-cd9f-11e6-8bd4-292925ba63a9, Connection=keep-alive, Content-Length=78, Date=Thu, 29 Dec 2016 08:16:10 GMT, Content-Type=application/json}\nThu Dec 29 08:16:10 UTC 2016 : Method response body after transformations: Empty\nThu Dec 29 08:16:10 UTC 2016 : Method response headers: {X-Amzn-Trace-Id=Root=1-5864c645-8494974a41a3a16c8d2f9929, Content-Type=application/json}\nThu Dec 29 08:16:10 UTC 2016 : Successfully completed execution\nThu Dec 29 08:16:10 UTC 2016 : Method completed with status: 200\n",
"latency": 5091,
"headers": {
"X-Amzn-Trace-Id": "Root=1-5864c645-8494974a41a3a16c8d2f9929",
"Content-Type": "application/json"
}
}
status
属性的值为200,表示这是一次成功的调用。 log
属性的值显示CloudWatch Logs中的日志语句。 还可以使用aws logs filter-log-events --log-group /aws/lambda/MicroservicePost
获得详细日志。
- 此命令在Couchbase中存储一个JSON文档。 可以使用Couchbase CLI工具cbq轻松地验证这一点。以以下方式连接到Couchbase服务器:
cbq -u Administrator -p password -e="http://<COUCHBASE_HOST>:8091"
在default
存储桶上创建一个主索引,因为这需要使用no子句查询存储桶:
cbq> create primary index default_index on default;
{
"requestID": "13b539f9-7fff-4386-92f4-cea161a7aa08",
"signature": null,
"results": [
],
"status": "success",
"metrics": {
"elapsedTime": "1.917009047s",
"executionTime": "1.916970061s",
"resultCount": 0,
"resultSize": 0
}
}
- 编写N1QL查询以访问数据:
cbq> select * from default limit 10;
{
"requestID": "d7b1c3f9-6b4e-4952-9a1e-9faf5169926e",
"signature": {
"*": "*"
},
"results": [
{
"default": {
"bookname": "test",
"cost": "1.23",
"id": "1",
"isbn": "123"
}
}
],
"status": "success",
"metrics": {
"elapsedTime": "24.337755ms",
"executionTime": "24.289796ms",
"resultCount": 1,
"resultSize": 175
}
}
结果显示了由我们的Lambda函数存储的JSON文档。
API网关GET方法
让我们在资源上创建HTTP GET
方法:
- 创建一个
GET
方法:
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method GET \
--authorization-type NONE
- 将正确的Lambda函数设置为GET的目标:
aws apigateway put-integration \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method GET \
--type AWS \
--integration-http-method POST \
--uri arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:598307997273:function:MicroserviceGetAll/invocations
- 设置GET方法响应的
content-type
:
aws apigateway put-method-response \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method GET \
--status-code 200 \
--response-models "{\"application/json\": \"Empty\"}"
- 设置GET方法集成响应的
content-type
:
aws apigateway put-integration-response \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method GET \
--status-code 200 \
--response-templates "{\"application/json\": \"Empty\"}"
- 授予权限以允许API网关调用Lambda函数
aws lambda add-permission \
--function-name MicroserviceGetAll \
--statement-id apigateway-test-getall-1 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-1:598307997273:lb2qgujjif/*/GET/books"
- 向部署的API授予权限:
aws lambda add-permission \
--function-name MicroserviceGetAll \
--statement-id apigateway-test-getall-2 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-1:598307997273:lb2qgujjif/test/GET/books"
- 测试方法:
aws apigateway test-invoke-method \
--rest-api-id lb2qgujjif \
--resource-id vrpkod \
--http-method GET
查看输出:
{
"status": 200,
"body": "Empty",
"log": "Execution log for request test-request\nSat Dec 31 09:07:48 UTC 2016 : Starting execution for request: test-invoke-request\nSat Dec 31 09:07:48 UTC 2016 : HTTP Method: GET, Resource Path: /books\nSat Dec 31 09:07:48 UTC 2016 : Method request path: {}\nSat Dec 31 09:07:48 UTC 2016 : Method request query string: {}\nSat Dec 31 09:07:48 UTC 2016 : Method request headers: {}\nSat Dec 31 09:07:48 UTC 2016 : Method request body before transformations: \nSat Dec 31 09:07:48 UTC 2016 : Endpoint request URI: https://lambda.us-west-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-1:598307997273:function:MicroserviceGetAll/invocations\nSat Dec 31 09:07:48 UTC 2016 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=******************************************************************************************************************************************************************************************************************************************************************************************************6de147, X-Amz-Date=20161231T090748Z, x-amzn-apigateway-api-id=lb2qgujjif, X-Amz-Source-Arn=arn:aws:execute-api:us-west-1:598307997273:lb2qgujjif/null/GET/books, Accept=application/json, User-Agent=AmazonAPIGateway_lb2qgujjif, X-Amz-Security-Token=FQoDYXdzEHEaDEILpsKTo45Ys1LrFCK3A+KOe5HXOSP3GfVAaRYHe1pDUJGHL9MtkFiPjORLFT+UCKjRqE7UFaGscTVG6PZXTuSyQev4XTyROfPylCrtDomGsoZF/iwy4rlJQIJ7elBceyeKu1OVdaT1A99PVeliaCAiDL6Veo1viWOnP+7c72nAaJ5jnyF/nHl/OLhFdFv4t/hnx3JePMk5YM89/6ofxUEVDNfzXxbZHRpTrG/4TPHwjPdoR5i9dEzWMU6Eo5xD4ldQ/m5B3RmrwpaPOuEq39LhJ8k/Vzo+pAfgJTq5ssbNwYOgh0RPSGVNMcoTkCwk0EMMT5vDbmQqZ2dW1a1tmQg9N2xR+QQy+RKMFgO5YY8fMxHnRSdMuuipxl79G1pktc [TRUNCATED]\nSat Dec 31 09:07:48 UTC 2016 : Endpoint request body after transformations: \nSat Dec 31 09:07:53 UTC 2016 : Endpoint response body before transformations: \"[{\\\"default\\\":{\\\"cost\\\":\\\"1.23\\\",\\\"id\\\":\\\"1\\\",\\\"bookname\\\":\\\"test book\\\",\\\"isbn\\\":\\\"123\\\"}}]\"\nSat Dec 31 09:07:53 UTC 2016 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=99ab09b2-cf38-11e6-996f-f5f07af431af, Connection=keep-alive, Content-Length=94, Date=Sat, 31 Dec 2016 09:07:52 GMT, Content-Type=application/json}\nSat Dec 31 09:07:53 UTC 2016 : Method response body after transformations: Empty\nSat Dec 31 09:07:53 UTC 2016 : Method response headers: {X-Amzn-Trace-Id=Root=1-58677564-66f1e96642b16d2db703126e, Content-Type=application/json}\nSat Dec 31 09:07:53 UTC 2016 : Successfully completed execution\nSat Dec 31 09:07:53 UTC 2016 : Method completed with status: 200\n",
"latency": 4744,
"headers": {
"X-Amzn-Trace-Id": "Root=1-58677564-66f1e96642b16d2db703126e",
"Content-Type": "application/json"
}
}
同样,200状态代码显示调用成功。 可以使用aws logs filter-log-events --log-group /aws/lambda/MicroservicePost
获得详细的日志。
该博客仅显示了一种简单的POST和GET方法。 其他HTTP方法也可以很容易地包含在此微服务中。
API网关和Lambda参考
翻译自: https://www.javacodegeeks.com/2017/01/microservice-using-aws-api-gateway-aws-lambda-couchbase.html