En una arquitectura basada en microservicios para un sistema de nivel empresarial como Clumio, no resulta práctico disponer de un punto de acceso público por cada microservicio. Uno de los principales problemas es el estrecho acoplamiento que esto genera entre el cliente y el servidor. Además, cada microservicio debe implementar y mantener los componentes comunes, como el registro de eventos, el rastreo y la seguridad (autenticación, autorización y limitación de tasa).
Una API Gateway actúa como intermediario entre un cliente y un servidor para gestionar las solicitudes y respuestas entre ambos.
Contar con una API Gateway proporciona un punto de entrada unificado para todos los clientes externos y un marco que se encarga de todos los elementos comunes mencionados anteriormente. Esto también permite que cada microservicio implemente su propio protocolo de comunicación que mejor se adapte a sus requisitos, independientemente de la API Gateway.
AWS API Gateway
Además de las ventajas mencionadas anteriormente que ofrecen las API Gateway, también teníamos otros requisitos que influyeron en la elección de una de ellas:
- Disponer de un mecanismo que permita la integración con API Gateway de tal forma que la incorporación de nuevas API y el mantenimiento de las existentes se realicen sin dificultades o con las mínimas posibles, de modo que los desarrolladores puedan centrarse principalmente en su lógica de negocio.
- Dado que una API Gateway podría constituir un punto único de fallo, debería tratarse de una solución totalmente gestionada, resistente y altamente escalable.
- Compatibilidad con WebSockets
AWS API Gateway cumple todos estos requisitos y ofrece una buena integración con otros servicios de AWS para desarrollar soluciones basadas en él.

Aprovechar las ventajas de AWS API Gateway
Especificación de Swagger
Swagger ofrece una potente representación de las API RESTful.
Hemos utilizado la herramienta go-swagger, que permite generar una especificación Swagger a partir de código Go anotado.
Por lo tanto, los desarrolladores solo tienen que anotar su API REST según la especificación anterior y dejar que nuestro marco de trabajo (que se menciona más adelante) se encargue de integrarla con AWS API Gateway.
Integración con AWS API Gateway
En Clumio, toda nuestra infraestructura de AWS se gestiona como código a través de Terraform. AWS API Gateway se puede configurar utilizando los recursos de Terraform que ofrece.
Utilizamos el recurso `aws_api_gateway_rest_api`, que nos permite incorporar la especificación completa de Swagger a AWS API Gateway. Sin embargo, AWS API Gateway no puede procesar una especificación Swagger sin formato. Requiere varias extensiones (como x-amazon-apigateway-integration) que formen parte de la especificación Swagger para poder configurar una API sin problemas. ¡Aquí es donde hemos implementado un marco que inyecta las extensiones necesarias en una especificación Swagger sin procesar para que funcione con AWS API Gateway!
Tipo de integración de enlace VPC
AWS API Gateway ofrece diversas integraciones con tus servidores de backend para actuar como proxy de las solicitudes de API entrantes.

Dado que todos nuestros microservicios están vinculados a una VPC para garantizar una mayor seguridad, utilizamos la VPC Link integración. Esto permite que AWS API Gateway acceda de forma segura a los puntos finales privados de la API dentro de la VPC.
Nombres de dominio personalizados y asignaciones de API
De forma predeterminada, AWS API Gateway genera un nombre de dominio único para la API, algo así como aabbccdd12.execute-api.us-west-2.amazonaws.com. En el caso de una empresa, obviamente nos gustaría personalizar el nombre de dominio público de las API para nuestros usuarios. AWS API Gateway nos permite hacerlo mediante los nombres de dominio personalizados.
Además, también creamos API independientes en API Gateway que se corresponden con algunas de nuestras rutas base de API más transitadas. Posteriormente, todas estas API se integran mediante asignaciones de API, tal y como se muestra a continuación. Esto nos permite escalar horizontalmente nuestras API y, al mismo tiempo, disponer de un único nombre de dominio público para ellas.

Lambda Authorizer, planes de uso y claves de API
Como se ha mencionado anteriormente, uno de los principales casos de uso de una API Gateway es aplicar la autenticación y la autorización justo al inicio del ciclo de vida de la solicitud de la API, de modo que solo el tráfico relevante llegue a los servidores backend.
Utilizamos Lambda Authorizer para la autenticación y la autorización, mientras que los planes de uso y las claves de API se emplean para aplicar la limitación de tasa en nuestras API.

Hemos implementado un autorizador Lambda basado en tokens que espera la siguiente entrada:
El authorizationToken (en forma de JWT) se puede utilizar para implementar la lógica de autenticación/autorización necesaria dentro del autorizador de Lambda, con el fin de devolver el resultado que se muestra a continuación:
La decisión de autenticación/autorización viene determinada por el valor de Effect (Allow|Deny) y la decisión sobre la limitación de tráfico se rige por el identificador de la clave API que figura en usageIdentifierKey. La clave API debe estar asociada a un plan de uso que determine el límite de solicitudes que se debe aplicar (en términos de solicitudes por segundo). Emitimos una clave API para cada cliente y, por lo tanto, podemos aplicar la limitación de solicitudes por cliente.
Otro aspecto interesante de la salida es context que puede contener cualquier par clave-valor según lo requiera la aplicación. Lo utilizamos ampliamente para recopilar la información del cliente, que luego transmitimos a lo largo de todo el ciclo de vida de la solicitud de la API. Esto elimina la necesidad de buscar los datos del cliente mientras la solicitud recorre varios microservicios en el backend.
Conclusión
Esperamos que te hayas hecho una idea de cómo aprovechamos AWS API Gateway en Clumio y que también hayas podido echar un vistazo a las iniciativas de ingeniería más amplias que llevamos a cabo. Prestamos la máxima atención a la seguridad, la escalabilidad y, lo más importante, a la adopción de procesos que faciliten el trabajo de los desarrolladores. Esto facilita el mantenimiento de los productos a medida que maduramos y crecemos, al tiempo que nos permite ser lo suficientemente flexibles como para incorporar nuevas funcionalidades.