Этот блог объяснил следующие концепции для безсерверных приложений:
В третьем блоге, посвященном бессерверной серии, будет рассказано, как создать простой микросервис с использованием Amazon API Gateway, AWS Lambda и Couchbase .
Прочитайте предыдущие блоги, чтобы узнать больше о AWS Lambda.
Amazon API Gateway — это полностью управляемый сервис, который позволяет разработчикам легко создавать, публиковать, поддерживать, отслеживать и защищать API-интерфейсы в любом масштабе. Amazon API Gateway выполняет все задачи, связанные с приемом и обработкой до сотен тысяч одновременных вызовов API, включая управление трафиком, авторизацию и контроль доступа, мониторинг и управление версиями API.
Вот ключевые компоненты этой архитектуры:
- Клиент может быть curl, AWS CLI, клиентом Postman или любым другим инструментом / API, который может вызывать конечную точку REST.
- API Gateway используется для предоставления API. Ресурс верхнего уровня доступен в path
/books. Методы HTTPGETиPOSTпубликуются для ресурса. - Каждый API запускает лямбда-функцию. Созданы две лямбда-функции: функция списка книг для перечисления всех доступных книг и функция создания книги для создания новой книги.
- Couchbase используется в качестве постоянного хранилища в EC2. Все документы JSON хранятся и извлекаются из этой базы данных.
Давайте начнем!
Создать роль IAM
Роли IAM будут иметь политики и доверительные отношения, которые позволят использовать эту роль в API Gateway и выполнять функцию Lambda.
Давайте создадим новую роль IAM:
|
1
2
3
|
aws iam create-role \--role-name microserviceRole \--assume-role-policy-document file://./trust.json |
--assume-role-policy-document определяет --assume-role-policy-document доверительных отношений, который предоставляет объекту разрешение на принятие роли. trust.json находится на github.com/arun-gupta/serverless/blob/master/aws/microservice/trust.json и выглядит так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com", "apigateway.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ]} |
Эти доверительные отношения позволяют функциям Lambda и API-шлюзу выполнять эту роль во время выполнения.
Связать политики с этой ролью как:
|
1
2
3
4
|
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 и выглядит следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
{ "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 Gateway для всех ресурсов. В целом, только требуемая политика будет предоставлена конкретным ресурсам.
Создать лямбда-функции
Подробные шаги по созданию лямбда-функций описаны в разделе «Бессерверный FaaS с AWS Lambda и Java» . Давайте создадим две лямбда-функции, как требуется в нашем случае:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
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, определенную с помощью переменной средыCOUCHBASE_HOST.
Создайте вторую лямбда-функцию:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
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 . Этот класс создает новый документ JSON в базе данных Couchbase, идентифицируемый переменной среды COUCHBASE_HOST .
Полный исходный код для этих классов находится по адресу github.com/arun-gupta/serverless/tree/master/aws/microservice/microservice-http-endpoint .
Ресурс шлюза API
Создайте API с помощью Amazon API Gateway, протестируйте его и создайте API для предоставления лямбда-функции, предоставьте подробные шаги и объяснение того, как использовать API-шлюз и лямбда-функции для создания мощных внутренних систем. Этот блог поможет вам быстро выполнить все шаги на случай, если вы захотите сократить погоню.
Давайте создадим ресурсы API Gateway.
- Первым шагом является создание API:
|
1
2
3
|
aws apigateway \create-rest-api \--name Book |
Это показывает вывод как:
|
1
2
3
4
5
|
{ "name": "Book", "id": "lb2qgujjif", "createdDate": 1482998945} |
Значением атрибута id является API ID. В нашем случае это lb2qgujjif .
- Найдите ROOT ID созданного API, поскольку это требуется для следующего вызова интерфейса командной строки AWS:
|
1
|
aws apigateway get-resources --rest-api-id lb2qgujjif |
Это показывает вывод:
|
1
2
3
4
5
6
7
8
|
{ "items": [ { "path": "/", "id": "hgxogdkheg" } ]} |
Значением атрибута id является ROOT ID. Это также идентификатор PARENT для ресурса верхнего уровня.
- Создать ресурс
|
1
2
3
4
|
aws apigateway create-resource \--rest-api-id lb2qgujjif \--parent-id hgxogdkheg \--path-part books |
Это показывает вывод:
|
1
2
3
4
5
6
|
{ "path": "/books", "pathPart": "books", "id": "vrpkod", "parentId": "hgxogdkheg"} |
Значением атрибута id является RESOURCE ID.
Идентификатор API и идентификатор RESOURCE используются для последующих вызовов интерфейса командной строки AWS.
Метод POST для шлюза API
Теперь, когда ресурс создан, давайте создадим метод HTTP POST для этого ресурса.
- Создать метод
POST
|
1
2
3
4
5
|
aws apigateway put-method \--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method POST \--authorization-type NONE |
чтобы увидеть ответ:
|
1
2
3
4
5
|
{ "apiKeyRequired": false, "httpMethod": "POST", "authorizationType": "NONE"} |
- Установите лямбда-функцию в качестве пункта назначения метода POST:
|
1
2
3
4
5
6
7
|
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. Здесь также используются API ID и RESOURCE ID из предыдущего раздела. --uri используется для указания URI входных данных интеграции. Формат URI фиксированный. Этот CLI покажет результат как:
|
1
2
3
4
5
6
7
8
|
{ "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"} |
- Установите
content-typeответа метода POST:
|
1
2
3
4
5
6
|
aws apigateway put-method-response \--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method POST \--status-code 200 \--response-models "{\"application/json\": \"Empty\"}" |
чтобы увидеть ответ:
|
1
2
3
4
5
6
|
{ "responseModels": { "application/json": "Empty" }, "statusCode": "200"} |
- Установите
content-typeответа интеграции метода POST:
|
1
2
3
4
5
6
|
aws apigateway put-integration-response \--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method POST \--status-code 200 \--response-templates "{\"application/json\": \"Empty\"}" |
чтобы увидеть ответ:
|
1
2
3
4
5
6
|
{ "statusCode": "200", "responseTemplates": { "application/json": "Empty" }} |
- Разверните API
|
1
2
3
|
aws apigateway create-deployment \--rest-api-id lb2qgujjif \--stage-name test |
чтобы увидеть ответ
|
1
2
3
4
|
{ "id": "9wi991", "createdDate": 1482999187} |
- Предоставьте разрешение API-шлюзу на вызов лямбда-функции:
|
1
2
3
4
5
6
|
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:
|
1
2
3
4
5
6
|
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:
|
1
2
3
4
5
6
|
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\"}" |
чтобы увидеть ответ:
|
01
02
03
04
05
06
07
08
09
10
|
{ "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 .
- Эта команда сохраняет один документ JSON в Couchbase. Это можно легко проверить с помощью Couch Casebase CLI Tool. Подключитесь к серверу Couchbase следующим образом:
|
1
|
cbq -u Administrator -p password -e="http://<COUCHBASE_HOST>:8091" |
Создайте первичный индекс в default по default поскольку это необходимо для запроса блока без разделов:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
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 для доступа к данным:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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 }} |
Результаты показывают документ JSON, который был сохранен нашей функцией Lambda.
API GET Метод GET
Давайте создадим метод HTTP GET для ресурса:
- Создайте метод
GET:
|
1
2
3
4
|
--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method GET \--authorization-type NONE |
- Установите правильную лямбда-функцию в качестве пункта назначения GET:
|
1
2
3
4
5
6
7
|
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 |
- Установите
content-typeответа метода GET:
|
1
2
3
4
5
6
|
aws apigateway put-method-response \--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method GET \--status-code 200 \--response-models "{\"application/json\": \"Empty\"}" |
- Установите
content-typeответа интеграции метода GET:
|
1
2
3
4
5
6
|
aws apigateway put-integration-response \--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method GET \--status-code 200 \--response-templates "{\"application/json\": \"Empty\"}" |
- Предоставьте разрешение API-шлюзу на вызов лямбда-функции
|
1
2
3
4
5
6
|
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:
|
1
2
3
4
5
6
|
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" |
- Проверьте метод:
|
1
2
3
4
|
aws apigateway test-invoke-method \--rest-api-id lb2qgujjif \--resource-id vrpkod \--http-method GET |
чтобы увидеть результат:
|
01
02
03
04
05
06
07
08
09
10
|
{ "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 Gateway и лямбда-ссылки
- Безсерверные архитектуры
- AWS API Gateway
- Создание простого микросервиса с использованием Lambda и API Gateway
- Документы Couchbase Server
- Форумы Couchbase
- Следуйте за нами на @couchbasedev
| Ссылка: | Микросервис с использованием AWS API Gateway, AWS Lambda и Couchbase от нашего партнера по JCG Аруна Гупта из блога Miles to go 3.0… . |
