Este blog explicou os seguintes conceitos para aplicativos sem servidor até o momento:
O terceiro blog da série sem servidor explicará como criar um microsserviço simples usando o Amazon API Gateway, o AWS Lambda e o Couchbase. Leia blogs anteriores para obter mais contexto sobre o AWS Lambda. Gateway de API da Amazon é um serviço totalmente gerenciado que facilita aos desenvolvedores a criação, publicação, manutenção, monitoramento e segurança de APIs em qualquer escala. O Amazon API Gateway lida com todas as tarefas envolvidas na aceitação e no processamento de até centenas de milhares de chamadas de API simultâneas, incluindo gerenciamento de tráfego, autorização e controle de acesso, monitoramento e gerenciamento de versões de API. Veja a seguir os principais componentes dessa arquitetura:

- O cliente pode ser curl, AWS CLI, cliente Postman ou qualquer outra ferramenta/API que possa invocar um ponto de extremidade REST.
- O API Gateway é usado para provisionar APIs. O recurso de nível superior está disponível no caminho
/livros. HTTPOBTERePOSTsão publicados para o recurso. - Cada API aciona uma função Lambda. Duas funções Lambda são criadas,
lista de livrospara listar todos os livros disponíveis ecriar livropara criar um novo livro. - O Couchbase é usado como um armazenamento de persistência no EC2. Todos os documentos JSON são armazenados e recuperados desse banco de dados.
Vamos começar!
Criar função de IAM
As funções do IAM terão políticas e relações de confiança que permitirão que essa função seja usada no API Gateway e execute a função Lambda. Vamos criar uma nova função de IAM:
|
1 2 3 |
aws iam create-role --role-name microserviceRole --assume-role-policy-document file://./trust.json |
--assume-role-policy-document define o documento de política de relacionamento de confiança que concede permissão a uma entidade para assumir a função. trust.json está em github.com/arun-gupta/serverless/blob/master/aws/microservice/trust.json e se parece com isso:
|
1 2 3 4 5 6 7 8 9 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" } ] } |
Essa relação de confiança permite que as funções Lambda e o API Gateway assumam essa função durante a execução. Associe políticas a essa função como:
|
1 2 3 4 |
aws iam put-role-policy --role-name microserviceRole --policy-name microPolicy --policy-document file://./policy.json |
policy.json está em github.com/arun-gupta/serverless/blob/master/aws/microservice/policy.json e se parece com isso:
|
1 2 3 4 5 6 7 8 9 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": "*" } ] } |
Essa política generosa permite quaisquer permissões sobre os registros gerados no CloudWatch para todos os recursos. Além disso, ela permite todas as permissões do Lambda e do API Gateway para todos os recursos. Em geral, somente a política necessária seria fornecida a recursos específicos.
Criar funções Lambda
As etapas detalhadas para criar funções Lambda são explicadas em FaaS sem servidor com AWS Lambda e Java. Vamos criar as duas funções Lambda conforme exigido em nosso caso:
|
1 2 3 4 5 6 7 8 9 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 |
Alguns dos principais itens a serem observados nessa função são:
- Função de IAM
microserviceRolecriado na etapa anterior é explicitamente especificado aqui - O manipulador é
org.sample.serverless.aws.couchbase.BucketGetAllclasse. Essa classe consulta o banco de dados do Couchbase definido usando o parâmetroCOUCHBASE_HOSTvariável de ambiente.
Crie a segunda função Lambda:
|
1 2 3 4 5 6 7 8 9 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 |
O manipulador para essa função é org.sample.serverless.aws.couchbase.BucketPost classe. Essa classe cria um novo documento JSON no banco de dados do Couchbase identificado por COUCHBASE_HOST variável de ambiente. O código-fonte completo dessas classes está em github.com/arun-gupta/serverless/tree/master/aws/microservice/microservice-http-endpoint.
Recurso do gateway de API
Crie uma API usando o Amazon API Gateway e teste-a e Criar uma API para expor uma função Lambda fornecem etapas e explicações detalhadas sobre como usar o API Gateway e as funções Lambda para criar sistemas de back-end avançados. Este blog fará uma rápida descrição das etapas, caso você queira ir direto ao ponto. Vamos criar recursos do API Gateway.
- A primeira etapa é criar uma API:
123aws apigatewaycreate-rest-api--name Book
Isso mostra a saída como:
12345{"name": "Book","id": "lb2qgujjif","createdDate": 1482998945}
O valor deidé o ID da API. No nosso caso, élb2qgujjif. - Encontre o ROOT ID da API criada, pois ele é necessário para a próxima invocação da CLI do AWS:
1aws apigateway get-resources --rest-api-id lb2qgujjif
Isso mostra o resultado:
12345678{"items": [{"path": "/","id": "hgxogdkheg"}]}
Valor deidé a ID ROOT. Essa também é a ID PARENT do recurso de nível superior. - Criar um recurso
1234aws apigateway create-resource--rest-api-id lb2qgujjif--parent-id hgxogdkheg--path-part books
Isso mostra o resultado:
123456{"path": "/books","pathPart": "books","id": "vrpkod","parentId": "hgxogdkheg"}
Valor deidé RESOURCE ID (ID do recurso).
A API ID e a RESOURCE ID são usadas para invocações subsequentes da AWS CLI.
Método POST do gateway de API
Agora que o recurso foi criado, vamos criar o HTTP POST nesse recurso.
- Criar um
POSTmétodo
12345aws apigateway put-method--rest-api-id lb2qgujjif--resource-id vrpkod--http-method POST--authorization-type NONE
para ver a resposta:
12345{"apiKeyRequired": false,"httpMethod": "POST","authorizationType": "NONE"} - Defina a função Lambda como destino do método POST:
1234567aws 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::function:MicroservicePost/invocations
Certifique-se de substituircom o ID de sua conta do AWS. O ID da API e o ID do recurso da seção anterior também são usados aqui.--urié usado para especificar o URI da entrada de integração. O formato do URI é fixo. Essa CLI mostrará o resultado como:
12345678{"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::function:MicroservicePost/invocations","cacheNamespace": "vrpkod"} - Conjunto
tipo de conteúdoda resposta do método POST:
123456aws apigateway put-method-response--rest-api-id lb2qgujjif--resource-id vrpkod--http-method POST--status-code 200--response-models "{"application/json": "Empty"}"
para ver a resposta:
123456{"responseModels": {"application/json": "Empty"},"statusCode": "200"} - Conjunto
tipo de conteúdoda resposta de integração do método POST:
123456aws apigateway put-integration-response--rest-api-id lb2qgujjif--resource-id vrpkod--http-method POST--status-code 200--response-templates "{"application/json": "Empty"}"
para ver a resposta:
123456{"statusCode": "200","responseTemplates": {"application/json": "Empty"}} - Implantar a API
123aws apigateway create-deployment--rest-api-id lb2qgujjif--stage-name test
para ver a resposta
1234{"id": "9wi991","createdDate": 1482999187} - Conceder permissão para que o API Gateway invoque a função Lambda:
123456aws 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::lb2qgujjif/*/POST/books"
Além disso, conceda permissão à API implantada:
123456aws 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::lb2qgujjif/test/GET/books" - Teste o método da API:
123456aws 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"}"
para ver a resposta:
12345678910{"status": 200,"body": "Empty","log": "Execution log for request test-requestnThu Dec 29 08:16:05 UTC 2016 : Starting execution for request: test-invoke-requestnThu Dec 29 08:16:05 UTC 2016 : HTTP Method: POST, Resource Path: /booksnThu 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/invocationsnThu 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: EmptynThu 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 executionnThu Dec 29 08:16:10 UTC 2016 : Method completed with status: 200n","latency": 5091,"headers": {"X-Amzn-Trace-Id": "Root=1-5864c645-8494974a41a3a16c8d2f9929","Content-Type": "application/json"}}
Valor destatusé 200 e indica que a invocação foi bem-sucedida. Valor deregistromostra a declaração de registro do CloudWatch Logs. Os registros detalhados também podem ser obtidos usandoaws logs filter-log-events --log-group /aws/lambda/MicroservicePost. - Esse comando armazena um único documento JSON no Couchbase. Isso pode ser facilmente verificado usando o comando Ferramenta CLI do Couchbase cbqConecte-se ao servidor Couchbase como:
1cbq -u Administrator -p password -e="https://:8091"
Criar um índice primário empadrãopois isso é necessário para consultar o bucket sem cláusulas:
1234567891011121314cbq> 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}} - Escreva um N1QL para acessar os dados:
123456789101112131415161718192021222324cbq> 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}}
Os resultados mostram o documento JSON que foi armazenado por nossa função Lambda.
Método GET do gateway de API
Vamos criar o HTTP OBTER no recurso:
- Criar um
OBTERmétodo:
12345aws apigateway put-method--rest-api-id lb2qgujjif--resource-id vrpkod--http-method GET--authorization-type NONE - Defina a função Lambda correta como destino do GET:
1234567aws 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 - Conjunto
tipo de conteúdoda resposta do método GET:
123456aws apigateway put-method-response--rest-api-id lb2qgujjif--resource-id vrpkod--http-method GET--status-code 200--response-models "{"application/json": "Empty"}" - Conjunto
tipo de conteúdoda resposta de integração do método GET:
123456aws apigateway put-integration-response--rest-api-id lb2qgujjif--resource-id vrpkod--http-method GET--status-code 200--response-templates "{"application/json": "Empty"}" - Conceder permissão para que o API Gateway invoque a função Lambda
123456aws 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" - Conceder permissão à API implantada:
123456aws 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" - Teste o método:
1234aws apigateway test-invoke-method--rest-api-id lb2qgujjif--resource-id vrpkod--http-method GET
para ver a saída:
12345678910{"status": 200,"body": "Empty","log": "Execution log for request test-requestnSat Dec 31 09:07:48 UTC 2016 : Starting execution for request: test-invoke-requestnSat Dec 31 09:07:48 UTC 2016 : HTTP Method: GET, Resource Path: /booksnSat 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/invocationsnSat 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: EmptynSat 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 executionnSat Dec 31 09:07:53 UTC 2016 : Method completed with status: 200n","latency": 4744,"headers": {"X-Amzn-Trace-Id": "Root=1-58677564-66f1e96642b16d2db703126e","Content-Type": "application/json"}}
Mais uma vez, o código de status 200 mostra uma invocação bem-sucedida. Os registros detalhados podem ser obtidos usandoaws logs filter-log-events --log-group /aws/lambda/MicroservicePost.
Este blog mostra apenas um método simples de POST e GET. Outros métodos HTTP também podem ser facilmente incluídos nesse microsserviço.
Oi @Arun,
Podemos usar o SDK do Couchbase NodeJs V2.6.3 com o lamda?
Estamos recebendo o seguinte erro quando tentamos usar o SDK mais recente.
"errorMessage": "/var/lang/lib/libstdc++.so.6: a versão `CXXABI_1.3.9′ não foi encontrada (exigida por /var/task/node_modules/couchbase/build/Release/couchbase_impl.node)",