Patrón: API Gateway (+Ejemplo con Zuul)

La descomposición en microservicios trae consigo el desarrollo de múltiples APIs que ofrecen sus endpoints, las APIs pueden estar segregadas en un ambiente distribuido con nombres de dominios o direcciones de internet diversas; esto provoca que las aplicaciones clientes tengan que conectarse a disímiles sistemas con variadas direcciones y rutas a los endpoints.

El patrón API gateway permite implementar una solución para centralizar y enrutar todas las peticiones desde el exterior hacia cada microservicio, actúa como un proxy o punto único que enruta una petición que llega hacia los microservicios correspondientes.

Existen fundamentalmente dos enfoques, (1) el API Gateway conoce donde está cada microservicio y enruta directo hacia ellos, y (2) se emplea un servicio de descubrimiento que conoce las instancia y las identifica mediante un id de servicio. Te invito a que aprendas más sobre service discovery en esta entrada.

Escenario 1: API Gateway direcciona directo a los microservicios

Un API Gateway ofrece un punto único de acceso. En la figura siguiente, se muestra uno de los posibles escenarios, usando un API Gateway que conoce las rutas hacia todos los microservicios que tiene por debajo y direcciona directamente las peticiones.

API Gateway sin configuración centralizada

El flujo contiene las siguientes etapas:

  1. Llega una petición desde internet (también puede ser usado un sistema interno), y partir de reglas de ruteo determina hacia dónde dirigirla.
  2. La petición se dirige al punto enrutado.
  3. El microservicio invocado responde al gateway.
  4. El gateway devuelve la respuesta al solicitante original.

La principal desventaja de este sistema es que cada vez se agregan nuevos microservicios o se mueven instancias entre nodos debe actualizarse la configuración del API Gateway, dificultando la gestión de la infraestructura.

Escenario 2: API Gateway usando un service discovery

En este escenario, la comunicación es como se muestra en la gráfica siguiente:

API Gateway usando un servicio de descubrimiento

Para comprender mejor este enfoque, es importante conocer que el servidor de descubrimiento, a grosso modo sabe en cada momento cuales son las instancias de microservicios que existen, sus direcciones y si están activas o no, el service discovery guarda un mapa en el que asocia un identificador de servicio y su dirección correspondiente.

Luego del resumen anterior sobre un servidor de descubrimiento, es importante conocer que en este enfoque, el API Gateway no conoce las direcciones de los microservicios, sino conoce un identificador de los servicios, y con ese identificador es suficiente para poder realizar el proceso.

Los pasos son los siguientes, acorde a los números del flujo de la figura anterior:

  1. Llega una petición desde internet (también puede ser usado un sistema interno), en las reglas de ruteo se coloca el id del microservicio.
  2. Con el id del microservicio se va al servidor de descubrimiento y se obtiene la ruta a la instancia correspondiente. (En este punto especialmente si se emplea un Load Balance como Ribbon, la ruta que se dará será acorde con la estrategia de balance de carga establecida).
  3. El service discovery entrega la ruta.
  4. Se invoca el microservicio correspondiente.
  5. El microservicio entrega la respuesta.
  6. Se responde al servicio original que invocó desde el exterior.

Capacidades que permite un API Gateway

Aunque puede variar un poco de acuerdo a la implementación de API Gateway que se elija desde el punto de vista tecnológico, con un gateway podemos implementar las siguientes funcionalidades que son beneficiosas para la arquitectura.

  • Realizar verificaciones de seguridad y control de acceso.
  • Soporte multiprotocolo, por ejemplo, HTTP REST, WebSockets, entre otros.
  • Verificar/modificar headers en las peticiones.
  • Realizar operaciones de logger sobre las peticiones/respuestas.
  • Gestionar políticas de consumo, rendimiento, fallos, etc. para asegurar acuerdos de nivel de servicio (SLAs) y sistemas de pago por uso.

¿ Cuándo usar un API Gateway ?

Un API Gateway (o varios) son siempre recomendados usarlos en una arquitectura que exponga más de un API a los dispositivos terminales (web, móvil, aplicaciones de escritorio, otras APIs externas, etc), su nivel de configuración depende del entorno y los resultados deseados del negocio.

Zuul API Gateway, un ejemplo práctico

Netflix, fue uno de los pioneros en el uso de arquitecturas de microservicios, ellos desarrollaron el ecosistema Netflix OSS, una suite de soluciones cloud para facilitar la creación de microservicios, aplicando muchos patrones y buenas prácticas del mercado. Entre estos sistemas desarrollaron el API Gateway Netflix OSS, basado en el marco de desarrollo Spring Boot.

El API Gateway será microservicio más de la infraestructura, Netflix (y luego Spring Cloud Gateway) desarrollaron una solución sencilla de poner en operación.

Para usar Spring Cloud Netflix, debemos agregar a nuestro proyecto el siguiente artefacto maven.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

Luego agregar en el programa principal del proyecto Spring Boot las siguientes anotaciones.

@Configuration
@EnableAutoConfiguration
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@EnableSwagger2
public class Run {
	public static void main(String[] args) {
		SpringApplication.run(Run.class, args);
	}
}

Especial atención a EnableZuulProxy y EnableDiscoveryClient, la primera crea el API Gateway y la segunda integra Zuul con el servidor de descubrimiento, para implementar el escenario 2 descrito en este artículo.

Zuul provee un sencillo mecanismo para especificar las configuraciones de ruteo a partir del fichero application.properties o application.yml de Spring Boot. A continuación un ejemplo:

zuul:
  ignore-security-headers: false
  ignored-headers: cookie,set-cookie
  ignoredServices: '*'
  routes:
    ms1:
        path: /api/v1/ms1/**
        serviceId: idMs1
        stripPrefix: true
        sensitive-headers: Cookie,Set-Cookie
    ms2:
        path: /api/v1/ms2/**
        serviceId: idMs2
        stripPrefix: true
        sensitive-headers: Cookie,Set-Cookie
    ms3:
        path: /api/v1/ms3/**
        serviceId: idMs3
        stripPrefix: true
        sensitive-headers: Cookie,Set-Cookie

En el ejemplo anterior, para que se comprenda mejor, cada vez que el API Gateway se le pegue un request del tipo:

http://miapigateway.com/api/v1/ms1/cualquierRuta

Entonces se preguntará al service discovery donde está el service Id que tiene como id=idMs1, y se enrutará la petición hacia ese camino.

Hasta acá esta entrada sobre API Gateway y el ejemplo con Zuul que hemos visto, espero te haya gusta este artículo. Si quieres aprender más sobre microservicios y las buenas prácticas para ponerlo en operación te invito a que veas mi ebook sobre este tema. Puedes ver su contenido acá.