Этот блог объяснил следующие концепции для безсерверных приложений:
В третьем блоге, посвященном бессерверной серии, будет рассказано, как создать простой микросервис с использованием 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… . |