Cómo configurar un API Gateway en Spring Cloud
En una arquitectura moderna basada en microservicios, tener múltiples servicios expuestos directamente al cliente genera caos y vulnerabilidades. Aquí es donde entra en juego el API Gateway, actuando como una puerta única de entrada que enruta las peticiones al microservicio correspondiente.
Spring Cloud nos ofrece una solución sencilla, aunque potente: Spring Cloud Gateway, un gateway reactivo diseñado para gestionar rutas, filtros y descubrimiento de servicios con una configuración mínima.
En el post de hoy vamos a tratar de explicar cómo crear un Gateway sencillo que enrute hacia tres microservicios distintos, paso a paso.
¿Qué es Spring Cloud Gateway?
Spring Cloud Gateway es el gateway oficial de Spring para aplicaciones construidas con Spring Bot 3 o superior (reemplazó al gateway Zuul que se utilizaba en versiones más antiguas de Spring Boot). Ofrece un modelo de programación reactivo, gracias a Spring WebFlux, y permite:
-
Gestionar rutas dinámicas.
-
Aplicar filtros (por ejemplo, autenticación o logging).
-
Integrarse con Eureka para descubrir servicios automáticamente.
-
Configurar rutas mediante parametrización (ficheros YAML o properties) o de forma programática (código Java).
A continuación, vamos a ir detallando los pasos necesarios para crear un servicio Spring Gateway que quede operativo con una configuración básica.
➕ Paso 1: Crear el proyecto y añadir dependencias
En primer lugar, hay que crear un proyecto Spring Boot. Usa Spring Initializr o tu editor favorito y asegúrate de incluir las siguientes dependencias Maven:
- Spring Reactive Web
- Spring Reactive Gateway
- Eureka Discovery Client
Las dependencias deberían quedar configuradas del siguiente modo:
Por cierto, otra cosa, no olvides añadir la gestión de versiones de Spring Cloud en tu fichero de dependencias Maven "pom.xml":
➕ Paso 2: Configuración en application.properties
➕ Paso 3: Definir rutas para los microservicios
Para este ejemplo, vamos a imaginar que nuestra aplicación está compuesta por tres microservicios (users, orders y products) que están registrados en un servidor Eureka:
-
users-service
→ puerto 8081 -
orders-service
→ puerto 8082 -
products-service
→ puerto 8083
Si añadimos la gestión de las rutas de estos microservicios, la configuración de nuestro fichero application.properties quedaría del siguiente modo:
👉 Como vemos en el fichero anterior, ahí estamos gestionando tres rutas
- Si se recibe un petición GET para la ruta "/users/**", la ejecución se redirige al balanceador del microservicio "users-service"
- Si se recibe un petición GET para la ruta "/orders/**", la ejecución se redirige al balanceador del microservicio "orders-service"
- Si se recibe un petición GET para la ruta "/products/**", la ejecución se redirige al balanceador del microservicio "products-service"
❌ Hay que puntualizar una cosa: para redigir al Balanceador de un determinado microservicio, en la URI de la ruta debemos incluir el prefijo "lb://", tal y como acabamos de ver en la configuración del application.properties anterior.
- lb://users-service
- lb://orders-service
- lb://products-service
El fichero anterior también podría ser configurado en formato YAML, con idéntico resultado. En ese caso, el fichero application.yml tendría este aspecto:
Con esto, las peticiones que comiencen por /users/
, /orders/
o /products/
serán redirigidas automáticamente al microservicio correspondiente.
➕ Paso 4 (opcional): Configuración automática de rutas
Si no queremos configurar las rutas de forma manual, Spring Gateway también dispone de la opción de enrutamiento autómatico. En ese caso, en vez de ir parametrizando las rutas una a una, simplemente tendremos que añadir los parámetros:
- spring.cloud.gateway.discovery.locator.enabled
- spring.cloud.gateway.discovery.locator.lower-case-service-id
De esta forma, eliminando las rutas manuales, el application.properties quedaría bastante simplificado. El fichero tendría este aspecto:
⛔ ¿Cómo funcionaría este enrutamiento automático?
Tomemos, por ejemplo, el microservicio "users-service". Este microservicio estará registrado en el servidor Eureka con el nombre USERS-SERVICE.
Por tanto, en función del registro anterior, la invocación automática a ese microservicio se realizará en el Spring Gateway a través del endpoint /USERS-SERVICE.
Si, por ejemplo, quisiéramos llegar hasta la ruta "/currency-conversion" del microservicio "users-service", el endpoint de invocación sería el siguiente:
/users-service/currency-conversion
Del mismo modo, si quisiéramos llegar a la ruta "/currency-exchange" del microservicio "orders-service" (registrado en Eureka como ORDERS-SERVICE), entonces el endpoint de invocación sería el siguiente:
/orders-service/currency-exchange
Como vemos, el enrutamiento automático simplifica mucho la gestión de rutas de los microservicios de nuestra aplicación. Eso sí, como contraprestación, no disponemos de la flexibilidad de configuración que ofrece el enrutamiento manual.
➕ Paso 5: Clase principal del proyecto
Asegúrate de tener la clase principal del servicio Gateway correctamente configurada. Debería quedar algo como lo siguiente.
Si usas descubrimiento de servicios con Eureka, puedes añadir @EnableDiscoveryClient
, aunque en Spring Boot 3 ya no es obligatorio.
➕ Paso 6 (opcional): Configurar rutas en Java
Si no te gusta parametrizar las rutas en el fichero de propiedades, Spring Cloud ofrece la posibilidad de configurar el enrutamiento de manera programática. Para ello, tendríamos que crearnos una clase GatewayConfig marcada con el tag @Configuration.
En dicha clase deberíamos crearnos un método (marcado con el tag @Bean) que deberá devolver un objeto de tipo RouteLocator donde estarán configurados diferentes enrutamientos.
Para cada enrutamiento que queramos realizar, nos creamos una función Lambda que redirija un determinado endpoint hacia un microservicio concreto.
Construimos el objeto RouteLocator con cada uno de los enrutamientos definidos. Una vez hecho lo anterior, el método marcado con el tag @Bean tendrá que devolver este objeto RouteLocator.
🌑 Si incluimos la configuración necesaria para cada uno de los tres microservicios que estamos tratando en el ejemplo, la clase GatewayConfig debería quedar algo así como lo siguiente:
Esta opción es útil si necesitas lógica condicional o rutas generadas dinámicamente. En cualquier caso, ya sabes que, en relación con la configuración del Spring Gateway, dispones tanto de la opción parametrizada como de la opción programática.
➕ Paso 7 (opcional): Añadir Logs al Gateway
Para mostrar los logs del API Gateway, debemos usar Log4Java. Para ello, nos podemos crear un componente de tipo “GlobalFilter” como el siguiente y de este modo se irán registrando todas las invocaciones que se vayan realizando al API Gateway.
Como vemos, esta clase está implementada con RFP (Programación Funcional Reactiva). Recordemos que el Gateway de Spring Cloud es reactivo y que, por tanto, todo el software incluido en dicho servicio debe realizarse bajo dicha directriz.
📌 Testing: Probar el Gateway
Asegúrate de tener los tres microservicios corriendo en sus respectivos puertos. Luego arranca el API Gateway y realiza pruebas para invocar a algunos endpoints de los microservicios configurados. Por ejemplo, podría ser algo así como:
Si todo está correctamente configurado, verás que cada una de las peticiones se redirigirá correctamente al microservicio definido.
Conclusión: Gateway sencillo, arquitectura limpia
Con sólo unas cuantas líneas de configuración, puedes montar un API Gateway funcional con Spring Cloud, capaz de enrutar tráfico hacia múltiples microservicios de forma eficiente y controlada. Esto no sólo reduce la complejidad en el cliente, sino que también mejora la seguridad, la observabilidad y la flexibilidad de tu sistema distribuido.
¡Nos vemos en el siguiente post!
Saludos.
Comentarios
Publicar un comentario