Este blog ha explicado hasta ahora los siguientes conceptos para las aplicaciones sin servidor:
El tercer blog de la serie serverless explicará cómo crear un microservicio sencillo utilizando Amazon API Gateway, AWS Lambda y Couchbase. Leer blogs anteriores para obtener más información sobre AWS Lambda. Puerta de enlace API de Amazon es un servicio totalmente administrado que facilita a los desarrolladores la creación, publicación, mantenimiento, monitorización y protección de API a cualquier escala. Amazon API Gateway se encarga de todas las tareas relacionadas con la aceptación y el procesamiento de hasta cientos de miles de llamadas a API simultáneas, incluida la administración del tráfico, la autorización y el control del acceso, la monitorización y la administración de versiones de API. Estos son los componentes clave de esta arquitectura:

- El cliente puede ser curl, AWS CLI, cliente Postman o cualquier otra herramienta/API que pueda invocar un endpoint REST.
- API Gateway se utiliza para aprovisionar APIs. El recurso de nivel superior está disponible en la ruta
/libros. HTTPGETyPOSTpara el recurso. - Cada API activa una función Lambda. Se crean dos funciones Lambda,
lista de librospara listar todos los libros disponibles ylibro-crearpara crear un nuevo libro. - Couchbase se utiliza como almacén de persistencia en EC2. Todos los documentos JSON se almacenan y recuperan de esta base de datos.
Empecemos.
Crear rol IAM
Los roles IAM tendrán políticas y relaciones de confianza que permitirán utilizar este rol en API Gateway y ejecutar la función Lambda. Vamos a crear un nuevo rol IAM:
|
1 2 3 |
aws iam create-role --role-name microserviceRole --assume-role-policy-document file://./trust.json |
--documento de política de funciones define el documento de política de relación de confianza que concede a una entidad permiso para asumir el rol. confianza.json está en github.com/arun-gupta/serverless/blob/master/aws/microservice/trust.json y parece:
|
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" } ] } |
Esta relación de confianza permite que las funciones Lambda y API Gateway asuman este rol durante la ejecución. Asocie políticas con este rol como:
|
1 2 3 4 |
aws iam put-role-policy --role-name microserviceRole --policy-name microPolicy --policy-document file://./policy.json |
política.json está en github.com/arun-gupta/serverless/blob/master/aws/microservice/policy.json y parece:
|
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": "*" } ] } |
Esta generosa política permite cualquier permiso sobre los registros generados en CloudWatch para todos los recursos. Además, permite todos los permisos de Lambda y API Gateway para todos los recursos. En general, solo se daría la política requerida a recursos específicos.
Crear funciones lambda
Los pasos detallados para crear funciones Lambda se explican en FaaS sin servidor con AWS Lambda y Java. Vamos a crear las dos funciones Lambda necesarias en nuestro 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 |
Un par de elementos clave a tener en cuenta en esta función son:
- Función IAM
microservicioRolecreado en el paso anterior se especifica explícitamente aquí - El manipulador es
org.sample.serverless.aws.couchbase.BucketGetAllclase. Esta clase consulta la base de datos Couchbase definida mediante la claseCOUCHBASE_HOSTvariable de entorno.
Crea la segunda función 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 |
El controlador de esta función es org.sample.serverless.aws.couchbase.BucketPost clase. Esta clase crea un nuevo documento JSON en la base de datos Couchbase identificado por COUCHBASE_HOST variable de entorno. El código fuente completo de estas clases se encuentra en github.com/arun-gupta/serverless/tree/master/aws/microservice/microservice-http-endpoint.
Recurso de la pasarela API
Crear una API con Amazon API Gateway y probarla y Crear una API para exponer una función Lambda proporcionan pasos detallados y explicaciones sobre cómo utilizar API Gateway y Lambda Functions para crear potentes sistemas backend. Este blog hará un rápido repaso de los pasos en caso de que desee cortar la persecución. Vamos a crear recursos de API Gateway.
- El primer paso es crear una API:
123aws apigatewaycreate-rest-api--name Book
Esto muestra la salida como:
12345{"name": "Book","id": "lb2qgujjif","createdDate": 1482998945}
El valor deides el ID de la API. En nuestro caso, eslb2qgujjif. - Busca el ROOT ID de la API creada, ya que es necesario para la siguiente invocación a la CLI de AWS:
1aws apigateway get-resources --rest-api-id lb2qgujjif
Esto muestra la salida:
12345678{"items": [{"path": "/","id": "hgxogdkheg"}]}
Valor deides el ID RAÍZ. También es el ID PARENT del recurso de nivel superior. - Crear un recurso
1234aws apigateway create-resource--rest-api-id lb2qgujjif--parent-id hgxogdkheg--path-part books
Esto muestra la salida:
123456{"path": "/books","pathPart": "books","id": "vrpkod","parentId": "hgxogdkheg"}
Valor deides RESOURCE ID.
El ID de API y el ID de RECURSO se utilizan para las invocaciones posteriores de la CLI de AWS.
API Gateway Método POST
Ahora que el recurso está creado, vamos a crear HTTP POST en este recurso.
- Crear un
POSTmétodo
12345aws apigateway put-method--rest-api-id lb2qgujjif--resource-id vrpkod--http-method POST--authorization-type NONE
para ver la respuesta:
12345{"apiKeyRequired": false,"httpMethod": "POST","authorizationType": "NONE"} - Establece la función Lambda como destino del 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
Asegúrese de sustituircon el ID de su cuenta AWS. El ID de API y el ID de RECURSO de la sección anterior también se utilizan aquí.--urise utiliza para especificar el URI de la entrada de integración. El formato del URI es fijo. Esta CLI mostrará el 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"} - Establecer
tipo de contenidode la respuesta del 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 la respuesta:
123456{"responseModels": {"application/json": "Empty"},"statusCode": "200"} - Establecer
tipo de contenidode la respuesta de integración del 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 la respuesta:
123456{"statusCode": "200","responseTemplates": {"application/json": "Empty"}} - Despliegue de la API
123aws apigateway create-deployment--rest-api-id lb2qgujjif--stage-name test
para ver la respuesta
1234{"id": "9wi991","createdDate": 1482999187} - Conceder permiso para permitir que API Gateway invoque Lambda Function:
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"
Además, conceda permiso a la API desplegada:
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" - Prueba el método 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 la respuesta:
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 deestadoes 200 e indica que la invocación se ha realizado correctamente. El valor deregistromuestra la declaración de registro de CloudWatch Logs. También se pueden obtener registros detallados utilizandoaws logs filter-log-events --log-group /aws/lambda/MicroservicePost. - Este comando almacena un único documento JSON en Couchbase. Esto puede verificarse fácilmente utilizando el comando Herramienta CLI de Couchbase cbqConéctese al servidor Couchbase como:
1cbq -u Administrator -p password -e="https://:8091"
Crear un índice primario enpor defectoya que es necesario para consultar el bucket sin 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}} - Escriba un N1QL para acceder a los datos:
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}}
Los resultados muestran el documento JSON que fue almacenado por nuestra función Lambda.
API Gateway Método GET
Vamos a crear HTTP GET en el recurso:
- Crear un
GETmétodo:
12345aws apigateway put-method--rest-api-id lb2qgujjif--resource-id vrpkod--http-method GET--authorization-type NONE - Establezca la función Lambda correcta como destino de 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 - Establecer
tipo de contenidode respuesta del 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"}" - Establecer
tipo de contenidode la respuesta de integración del 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 permiso para permitir que API Gateway invoque Lambda Function
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 permiso a la API desplegada:
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" - Prueba el método:
1234aws apigateway test-invoke-method--rest-api-id lb2qgujjif--resource-id vrpkod--http-method GET
para ver la salida:
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"}}
Una vez más, el código de estado 200 muestra una invocación correcta. Se pueden obtener registros detallados utilizandoaws logs filter-log-events --log-group /aws/lambda/MicroservicePost.
Este blog sólo muestra un simple POST y GET métodos. Otros métodos HTTP se pueden incluir muy fácilmente en este microservicio también.
Hola @Arun,
¿Podemos usar Couchbase NodeJs V2.6.3 SDK con lamda?
Estamos recibiendo el siguiente error cuando intentamos con la última SDK.
"errorMessage": "/var/lang/lib/libstdc++.so.6: versión `CXXABI_1.3.9′ no encontrada (requerida por /var/task/node_modules/couchbase/build/Release/couchbase_impl.node)",