Hoy en día mucho se ha estudiado (y comentado) sobre lo interesante y óptimas que son las arquitecturas basadas en microservicios serverless.

De hecho, en este mismo blog, varios de mis compañeros han hablando de las distintas formas de trabajar con arquitecturas serverless, incluso de la integración de los servicios Lambda.

Sin embargo, poco se ha profundizado sobre este último, que nos provee de una serie de funcionalidades y mecanismos para desplegar gestionar APIs bastante interesantes.

¿Qué es API Gateway?

Es un servicio de Amazon Web Services (AWS), que nos permite crear, implementar y administrar una interfaz de programación de aplicaciones (API) REST para exponer los endpoints HTTP del backend, funciones AWS Lambda u otros servicios de AWS.

Su principal característica es la de servir como frontal o proxy a través del cual podemos acceder a funcionalidades y/o servicios.

¿Por qué puede ser interesante?

Múltiples versiones y simplicidad en el despliegue

Permite ejecutar varias versiones de la misma API simultáneamente, lo que facilita la iteración, puesta a prueba y publicación de nuevas versiones con rapidez. Y esto cuando hablamos de desarrollos ágiles es un gran punto a favor. Por ejemplo, es posible definir diferentes fases de publicación (o bien llamados entornos integración, preproducción y producción).

Es cierto que los servicios hay que programarlos, pero el hecho de que podamos publicarlos de forma casi inmediata es otro punto a favor y de mucho valor, teniendo en cuenta el dinamismo que está presente hoy día en el desarrollo de aplicaciones.

Sin embargo, una vez tenemos listos nuestros microservicios, el despliegue de una nueva versión de la API se consigue prácticamente con un clic. Basta solo con indicar (o definir) sobre qué fase (entorno) deseamos hacer el despliegue y poco más. ¡A correr!

Performance

Dispone de un sistema de escalado automático con el fin de administrar y gestionar la cantidad de tráfico recibido (manejo de un alto número de peticiones concurrentes).

Como un complemento al auto escalado, también provee un sistema de limitación controlada, que permite la gestión del tráfico de peticiones simultáneas. Es decir, si dicha característica está activada, todas las peticiones excedentes al umbral definido serían descartadas y así, en cierta manera, podríamos evitar que se desborde la infraestructura backend durante picos de tráfico impredecibles.

Adicionalmente es posible activar el sistema de caché, que ha sido pensado para mejorar el rendimiento evitando las llamadas innecesarias al backend. La duración de la misma se define en segundos y su tamaño en GBs.

Gestión de la seguridad

La seguridad puede gestionarse a través de un conjunto de herramientas que provee AWS, que permiten controlar la autenticación y el acceso a las diferentes operaciones de una API.

Entre las herramientas encontramos IAM (Identity Access Management) o Cognito de AWS, que permiten la identificación, definición de políticas de acceso e incluso la verificación de tokens, entre otros. Cabe destacar que la tecnología que utiliza dicho sistema de gestión de autenticación y autorización es la misma que utiliza AWS para sus propios servicios.

Otro punto importante con respecto a la seguridad, es que todos los recursos (servicios) son expuestos a través del protocolo HTTPS, es decir, API Gateway no admite comunicaciones no cifradas.

Monitorización

Provee un conjunto de métricas sobre la cantidad de llamadas, latencia, tasa de errores sobre las APIs, así como también logs para facilitar las tareas de debugging.

También es posible realizar extracción de analíticas, siendo este un punto fuerte que, personalmente, relaciono con la puesta a punto, ya que en función de los datos obtenidos es posible hacer los ajustes necesarios y, acorde a nuestras necesidades, podamos tener un mejor rendimiento.

Mocks

Por otra parte, API Gateway también ofrece la opción bastante útil para la fase de diseño y prototipado. Y es que según un modelo definido, es posible crear mocks, algo que me parece de gran utilidad para hacer pruebas de integración con el front-end.

¿Con qué podemos usar API Gateway?

Dentro de sus capacidades tenemos que destacar que es fácilmente integrable con otros servicios de AWS, siempre que los mismos pertenezcan a la misma cuenta AWS. Por ejemplo: Lambda (acciones o funciones que se ejecutan a demanda y las cuales no requieren la gestión de un servidor de aplicaciones), DynamoDB (base de datos NoSQL en AWS, la cual expone todos sus servicios a través de endpoints HTTP), entre otros.

Incluso es posible hacer una integración mixta, es decir, que cada método de la petición (POST, GET, PUT, etc.) esté asociado a distintos tipos de servicios y tecnologías.

En el mundo de los microservicios serverless, uno de los ámbitos más interesantes que provee API Gateway es la sencilla integración con el servicio Lambda AWS, que permite ejecutar su propio código para responder a diferentes tipos de eventos, sin la necesidad de provisionar y/o administrar servidores (las funcionalidades pueden ser desarrolladas en diferentes lenguajes de programación).

En otras palabras, nuestro backend puede estar compuesto por diversos servicios y tecnologías. Incluso pueden estar alojados en diferentes localidades y con la ayuda del API Gateway podemos hacer que esto sea totalmente transparente para quienes van a hacer uso de nuestra API.

Veamos un ejemplo

Nos planteamos el siguiente escenario:

Supongamos que tenemos una API para gestionar un club de fútbol y donde hay definido un recurso llamado /players/.

A través de su método GET retorna un listado de todos los jugadores (enlazando directamente a una tabla en una DynamoDB).

Por otro lado, el método POST del mismo recurso invoca directamente a un endpoint definido dentro de algún contenedor de AWS que se encarga de la validación y después de un conjunto de operación, de persistir los datos del nuevo jugador.

Por último, la implementación del método DELETE la delegamos a una función Lambda.

De esta manera estaríamos integrando diferentes servicios, diferentes tecnologías, e incluso hasta diferentes lenguajes de programación. Por supuesto todo dependiendo de nuestras necesidades, pero ciertamente nos ofrece flexibilidad.

Nota: es importante aclarar que el acceso a los distintos sistemas siempre se realiza por medio de endpoint y verbo.

API Gateway, integración en acción

A continuación, os voy a mostrar lo sencillo que sería hacer la integración de API Gateway con DynamoDB. En otras palabras, crearemos una capa de acceso a recursos de datos a través de una API.

Para comenzar es necesario considerar un par de premisas:

  1. Debemos disponer de una cuenta en AWS.
  2. Asumimos que tenemos una base de datos en DynamoDB con una tabla llamada player.

¡Comencemos!

Paso 1: API

Lo primero será crear una nueva API. Esto lo conseguimos directamente sobre la consola de Amazon API Gateway clicando sobre el botón Create API, asignamos un nombre y lo tenemos.

Paso 2: Recursos y métodos

Ya que se basa en RESTful, para hacer la publicación de algún servicio, tendremos que definir el recurso y los métodos por los que atenderá a las peticiones.

En el menú Actions encontramos todas las operaciones que podemos realizar sobre una API.

Primero, creamos el recurso que queremos exponer.

En este caso, crearemos un recurso llamado players/{id}.

Segundo, creamos el método HTTP al que vamos a asociar la operación.

:Nota: La relación entre el recurso y la tabla de base de datos que vamos a consultar se define dentro del apartado Policies.

En el siguiente paso debemos definir el tipo de integración que deseamos realizar. En este caso concreto, sería enlazar el recurso a la tabla en base de datos (recordemos que la misma debe ser previamente creada en DynamoDB).

Tal como mencionamos previamente, en esta pantalla pueden observarse todas las opciones que ofrece API Gateway para ser integrado.

Para continuar con el ejemplo, en este caso debemos rellenar toda la plantilla con los datos de localización y nombre del servicio con el que deseamos integrar, así como también la acción que será invocada.

En este punto hay que hacer énfasis en lo siguiente:

  1. Es importante resaltar que en la selección de HTTP method no se trata del mismo método que estamos exponiendo en la API que hemos creado previamente. Este se refiere al método que debemos utilizar para conectar con un servicio el particular al que vamos a conectar. Para el servicio DynamoDB, todas las peticiones deben ser realizadas a través del método POST, aún cuando lo que vayamos a realizar se una consulta de lectura.
  2. Action, se refiere a la acción o función que queremos invocar dentro del servicio. En este caso vamos a realizar una consulta sobre la tabla player filtrando por el id. La API DynamoDB ofrece varias funcionalidades, tanto de consulta como de modificación (GetItem, UpdateItem, DeleteItem, PutItem, etc). El detalle del servicio DynamoDB está fuera del ámbito de este post.
  3. Por razones obvias de seguridad, en AWS, para establecer la comunicación entre servicios, es estrictamente necesario definir las políticas y unos roles donde indiquemos las reglas de visibilidad entre servicios, e incluso qué funciones pueden ser invocadas entre sí. Esto se conoce dentro del ámbito de AWS como el Execution Role. Todo esto se define en la consola IAM, específicamente en los apartados de Policies y Roles***.*** En el primero definimos acceso y visibilidad (reglas del juego), y el segundo es el perfil a quién le asignamos tales políticas y reglas de acceso.

Nota: La relación entre el recurso y la tabla de base de datos que vamos a consultar se define dentro del apartado Policies.

¡Ya casi lo tenemos! Ya hemos creado tanto el recurso como el método (/players/{id} - GET). Ahora solo quedaría definir de qué manera deberán ser mapeados los parámetros de la API con respecto a los argumentos que espera el servicio a ser invocado (siempre que esto aplique, obviamente).

Paso 4: parámetros y transformación de datos

Dado que estamos hablando de peticiones HTTP y que los parámetros pueden viajar bien sea a través de la URL (path/querystring), en el cuerpo o en la cabecera de la misma (body y header respectivamente), la configuración de los mismos vendrá condicionada al servicio que se desee invocar.

Ahora bien, para el ejemplo que hemos propuesto, para invocar la acción Query dentro del servicio DynamoDB, es necesario proporcionar nombre de la tabla y los campos por los que que realizará el filtro (requisitos mínimos de la acción).

En todo caso, el mapeo y transformación tanto de los argumentos de entrada como los de salida, los podemos configurar dentro de la sección Method Execution.

Donde:

Con respecto al ejemplo:

El cuerpo de la petición lo establecemos desde la opción Body Mapping Templates del Integration Request. En este punto podemos capturar los datos que viajan desde la entrada hasta el método, parsearlos (si es necesario) y luego inyectarlos a la llamada del servicio con el que estamos enlazando.

El cuerpo de la petición se expresa en formato JSON, por lo que el Content-Type será application/json. Siempre podemos partir de una plantilla que exista o una en blanco.

En la instrucción #set($inputRoot = $input.path(‘$’)) obtendremos todos los datos con la que se ha realizado la petición. De allí podremos extraer: parámetros, cabeceras, cuerpo y contexto; bien para añadir algún tipo de lógica o transformación, o bien para redirigirlos como entrada del siguiente punto de enlace que no es más que la invocación al servicio.

El JSON definido establece lo siguiente:

  1. TableName nombre de la tabla a consultar.
  2. PrimaryKey campo primario dentro de la tabla.
  3. KeyConditionExpression condición de filtrado (campo id).
  4. ExpressionAttributeValues es aquí donde hacemos la magia, es decir, aquí indicamos de dónde provienen los datos de entrada ($input.params(‘id’)) y dónde los inyectamos.

Con esto último nuestra API está preparada para consultar el registro de la tabla player a través del método GET del recurso /players/{id}. Lo podemos comprobar ejecutando el test que nos provee la consola.

De forma similar que ocurre en el Integration Request en el Integration Response podemos configurar el apartado Body Mapping Templates. Pero en este caso, para hacer una proyección de los datos obtenidos, es decir, podemos aplicar alguna transformación a la respuesta, y de esta manera presentar la salida como sea más conveniente.

Como podemos observar, aquí preparamos la salida para que tenga una estructura más manejable. ¡Ojo! Esto es siempre que lo necesitemos, ya que este punto no es imprescindible para llevar a cabo la integración de la API con un servicio.

Si ejecutamos nuevamente el test veremos claramente la diferencia:

Paso 5: Despliegue y publicación

El despliegue de una API es más sencillo de lo que podríamos imaginar, solo es necesario ejecutar la acción Deploy API.

Seguidamente mostrará un popup donde indicaremos la fase o entorno, acompañado por un nombre y una breve descripción.

Con este paso ya hemos conseguido publicar los servicios a través de nuestra API.

Cada Stage que creamos nos suministrará una URL a través de la cual podremos atracar un servicio utilizando el método adecuado.

Paso 6: Ajustes y puesta a punto

Una vez realizado el despliegue podemos realizar una serie de configuraciones con respecto al rendimiento, seguridad y monitorización de la API. Esto lo podemos conseguir editando el apartado Stages.

Aquí podemos activar el uso de la caché para mejorar los tiempos de respuesta. También podemos ajustar el umbral de peticiones por segundo y ráfagas de peticiones concurrentes.

Y en caso de que la integración así lo requiera, también podemos habilitar la opción de envío de certificado digital. Los certificados podemos añadirlos directamente en el apartado Client Certificates.

Finalmente, cada Stage proporciona una URL con el que podemos consumir la API.

Conclusión

Para la mayoría de las aplicaciones basadas en microservicios tiene sentido implementar una API Gateway que actúe como un único punto de entrada en un sistema, asumiendo la responsabilidad del enrutamiento de solicitudes, la composición y la traducción de protocolos.

Adicionalmente es una herramienta de fácil gestión, con la que podemos acortar los tiempos de despliegue y puesta en producción. Algo sumamente importante si queremos que nuestros desarrollos sean dinámicos y donde los deadlines están a la orden del día.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.