Día 26 de 30 Fase 7: API Gateway, API-First, Arquitectura Hexagonal Enterprise y Sagas

API Gateway, API-First Design y Contratos OpenAPI 3.1

Spring Cloud Gateway, Enrutamiento Declarativo, Generación de Código con OpenAPI Generator

Visión de conjunto. Sales entendiendo cómo funciona y cuándo usarlo; dominarlo pide más práctica en un proyecto real.

  • 4h de estudio
  • 5 conceptos
  • 3 preguntas
  • 1 katas
API GatewayAPI-FirstOpenAPI 3.1Spring Cloud GatewaySwaggerContract-First
Al terminar este día sabrás 4
  • Situar un API Gateway en la arquitectura y decidir qué responsabilidades le corresponden.
  • Trabajar con un contrato OpenAPI como fuente de verdad y generar código a partir de él.
  • Configurar rutas, predicados y filtros en Spring Cloud Gateway.
  • Evolucionar una API sin romper a sus clientes.

API Gateway: Punto de Entrada Único para Microservicios

Un API Gateway es un servicio que actúa como puerta de entrada centralizada para todas las peticiones de clientes externos. Recibe las llamadas HTTP, las enruta al microservicio correcto según la URL o cabeceras, y aplica preocupaciones transversales como autenticación, rate limiting, logging, transformación de headers y balanceo de carga.

En una línea spring.cloud.gateway.routes[0].uri=http://servicio-pedidos:8080 spring.cloud.gateway.routes[0].predicates[0]=Path=/api/v1/pedidos/**

Rutas declarativas en Spring Cloud Gateway yaml
spring:
  cloud:
    gateway:
      default-filters:
        - AddResponseHeader=X-Content-Type-Options, nosniff
      routes:
        - id: tareas
          uri: http://tareas-service:8080
          predicates:
            - Path=/api/tareas/**
          filters:
            - name: CircuitBreaker
              args:
                name: tareas
                fallbackUri: forward:/fallback/tareas

        - id: usuarios-v2
          uri: http://usuarios-service-v2:8080
          predicates:
            - Path=/api/v2/usuarios/**
          filters:
            - StripPrefix=2                    # /api/v2/usuarios/7 -> /usuarios/7
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 20
                redis-rate-limiter.burstCapacity: 40
Cómo funciona por dentro

Un API Gateway es el único punto de entrada de los clientes externos a un conjunto de servicios. Recibe todas las peticiones y las encamina al servicio adecuado según la ruta, el método o las cabeceras. Así los clientes no conocen la topología interna, que puede cambiar sin afectarles.

Además del enrutamiento, concentra preocupaciones transversales que no conviene repetir en cada servicio: terminación TLS, validación de tokens, limitación de peticiones (rate limiting), CORS, cabeceras de seguridad, registro de accesos, propagación del id de correlación y, a veces, agregación de respuestas para un cliente concreto (patrón Backend for Frontend).

Como todo el tráfico pasa por él, debe desplegarse con alta disponibilidad (varias instancias tras un balanceador) y mantenerse ligero. Si se convierte en un lugar donde cada equipo añade lógica, pasa a ser un cuello de botella organizativo y técnico.

Evita que los clientes (frontends, apps móviles) deban conocer las IPs y puertos internos de cada microservicio. Centraliza seguridad y monitorización.

Se conecta con Spring Cloud GatewayKongEnvoyIngress de Kubernetes

Cuatro bloques cronometrados. No pases al siguiente sin tener el resultado esperado.

  1. Bloque 1: Diseño API-First con OpenAPI 3.1 (0 - 25 min)

    Qué estudiar. Estructura de un fichero openapi.yaml: info, paths, schemas, responses.

    Pregunta a responder. ¿Cómo definir un endpoint POST que devuelve 201 Created con un DTO en el body?

    Resultado esperado. Fichero api-spec.yaml con 3 endpoints documentados.

  2. Bloque 2: Spring Cloud Gateway y Enrutamiento (25 - 50 min)

    Qué estudiar. Configuración de rutas con predicados de Path y filtros de headers.

    Pregunta a responder. ¿Cómo enrutar /api/v1/pedidos/ al servicio de pedidos y /api/v1/usuarios/ al servicio de usuarios?

    Resultado esperado. application.yml con 3 rutas de gateway funcionales.

  3. Bloque 3: SpringDoc y Swagger UI (50 - 80 min)

    Qué estudiar. Integración de springdoc-openapi en Spring Boot 3 y anotaciones @Operation, @Schema.

    Pregunta a responder. ¿Cómo documentar errores de validación (400) y not found (404)?

    Resultado esperado. Swagger UI accesible en /swagger-ui.html con documentación interactiva.

  4. Cierre y Consolidación (80 - 90 min)

    Qué estudiar. Versionado de APIs y criterios de decisión API-First vs Code-First.

    Pregunta a responder. ¿Cuándo es más práctico Code-First?

    Resultado esperado. Notas de decisión en la app.

Tres formas de comprobar si lo has entendido, de menos a más exigente: explicarlo con tus palabras, responder preguntas trampa y resolver el reto del tutor.

Explícalo desde cero

Lee cada ficha y explícala en voz alta antes de seguir: si puedes contárselo a alguien que empieza, lo has entendido.

Por qué API-First ahorra semanas de trabajo en equipos frontend-backend

Lo que debes entender

Si el equipo frontend tiene que esperar a que el backend termine para saber la forma de los datos, todo el proyecto se ralentiza. Con API-First, el contrato YAML se firma antes de escribir código. El frontend genera mocks automáticos del YAML y construye su UI completa. El backend implementa contra las interfaces generadas. Cuando ambos terminan, se integran y funcionan a la primera.

Analogía para contarlo

Construir una casa: el plano del arquitecto (contrato OpenAPI) se firma antes de que el fontanero (backend) y el electricista (frontend) empiecen a trabajar. Si cada uno trabaja sin plano, las tuberías y los cables no coincidirán.

Lo que suele explicarse mal

Pensar que API-First es "documentar la API con Swagger". Documentar a posteriori es Code-First; API-First significa que el YAML es el artefacto maestro que se diseña PRIMERO.

Señal de que aún no lo dominas

Si los endpoints de tu API devuelven campos que solo existen porque tu tabla de base de datos los tiene, en vez de devolver lo que el consumidor necesita.

Preguntas trampa

Responde de memoria, en voz alta o por escrito, y después abre la respuesta razonada: lo importante es el porqué, no la palabra exacta.

Nivel 1 (Básico) ¿Por qué un API Gateway NO debe contener lógica de negocio? Ver respuesta

Respuesta razonada

Porque el gateway es compartido por todos los servicios y equipos. Si contiene lógica de negocio, cada cambio de negocio exige modificar y desplegar el gateway, que se convierte en un cuello de botella para todos los equipos y en un punto donde un error afecta a todo el sistema. Además, la lógica queda repartida entre el gateway y los servicios, rompiendo la autonomía y el encapsulamiento de cada uno: es el camino hacia un monolito distribuido.

Su responsabilidad son las preocupaciones transversales y técnicas: enrutar, autenticar, limitar, observar y proteger. Si un cliente concreto necesita agregar datos de varios servicios, la opción es un Backend for Frontend propio de ese cliente, no meter esa lógica en el gateway común.

Qué está evaluando la pregunta

El gateway debe ser un enrutador ligero sin estado. Si metes lógica de negocio, conviertes el gateway en un monolito centralizado, un punto único de fallo, difícil de escalar y de testear independientemente.

Nivel 2 (Intermedio) ¿Cuál es la diferencia entre API-First (Contract-First) y Code-First para generar documentación OpenAPI? Ver respuesta

Respuesta razonada

En API-First se escribe primero el contrato OpenAPI, se acuerda con los consumidores y se genera el código del servidor (interfaces, DTOs) y de los clientes a partir de él. El contrato es la fuente de verdad: los cambios se discuten antes de implementarse y los equipos pueden trabajar en paralelo con mocks.

En Code-First se escribe el código y la documentación OpenAPI se genera a partir de él (por ejemplo con SpringDoc). Es más rápido para empezar y no hay ficheros que mantener sincronizados, pero el contrato es una consecuencia de la implementación y los cambios incompatibles pueden colarse sin que nadie los revise. API-First compensa en APIs públicas o consumidas por varios equipos; Code-First, en APIs internas de un solo equipo.

Qué está evaluando la pregunta

En API-First el contrato YAML/JSON se diseña y aprueba primero; el código se genera o implementa después contra ese contrato. En Code-First el desarrollador escribe el controlador Java y la documentación OpenAPI se genera automáticamente a partir de las anotaciones. API-First garantiza que la API está diseñada para el consumidor; Code-First suele reflejar la estructura interna del backend.

Nivel 3 (Entrevista Senior) Spring Cloud Gateway se ejecuta sobre WebFlux/Netty. ¿Por qué no se puede usar Spring Data JPA (JDBC bloqueante) directamente dentro de un filtro del gateway? Ver respuesta

Respuesta razonada

Spring Cloud Gateway clásico se ejecuta sobre Netty con un número pequeño de hilos de event loop, que atienden todas las conexiones. JDBC y JPA son bloqueantes: mientras esperan a la base de datos, el hilo queda parado. Unas pocas peticiones lentas a la base de datos dentro de un filtro bastan para dejar todos los hilos bloqueados, y el gateway, por el que pasa todo el tráfico, deja de responder.

Si un filtro necesita datos (por ejemplo, permisos o límites por cliente), se usan clientes reactivos (R2DBC, Redis reactivo, WebClient), se cachean los datos en memoria o, como último recurso, se aísla la llamada en Schedulers.boundedElastic(). Y, sobre todo, se cuestiona si ese acceso a datos pertenece realmente al gateway.

Qué está evaluando la pregunta

Spring Cloud Gateway ejecuta sobre el Event Loop de Netty con pocos hilos. Una llamada JDBC bloqueante dentro de un filtro congelaría uno de esos escasos hilos del Event Loop, pudiendo bloquear todo el gateway. Si se necesita consultar una BD, se debe usar un cliente reactivo (R2DBC) o delegar a un microservicio downstream.

Reto del tutor

Tu empresa tiene 12 microservicios. Un equipo propone que cada microservicio exponga su propia documentación Swagger UI en su propio puerto. El equipo de frontend se queja porque debe consultar 12 URLs distintas. ¿Cómo centralizarías la documentación?

Lo que una respuesta suele tener bien

Propone agregar la documentación en un punto central.

Lo que suele quedarse en la superficie

Decir "poner un Swagger UI en el gateway".

El concepto de fondo que suele faltar

No saber que Spring Cloud Gateway puede agregar los spec JSON de cada microservicio usando la configuración de springdoc.swagger-ui.urls o un servicio de agregación de contratos.

Cómo lo respondería alguien senior en una entrevista

La solución es configurar el API Gateway con springdoc-openapi-starter-webflux-ui y usar la propiedad springdoc.swagger-ui.urls para agregar los esquemas /v3/api-docs de cada microservicio en un Swagger UI centralizado accesible desde una URL única del gateway. Adicionalmente, en producción se desactiva el acceso público a /swagger-ui.html con un filtro de seguridad o restricción de red.

Proyecto «Pedidos» · paso 26 de 30

Contrato OpenAPI y gateway

Definir la API antes de implementarla y poner una única puerta de entrada delante.

De qué va el proyecto

El backend de una tienda online: clientes, catálogo de productos y pedidos con sus líneas, pagos y envíos. Empieza como un proyecto Maven con records y termina como un sistema con API REST, seguridad, mensajería, contenedores y observabilidad. Cada paso construye sobre el anterior, así que trabaja siempre en el mismo repositorio.

Qué hacer

  1. Escribe el contrato OpenAPI 3.1 de la API de pedidos y genera las interfaces de los controladores.
  2. Pon Spring Cloud Gateway delante de pedidos y notificaciones con rutas por prefijo.
  3. Añade limitación de peticiones por cliente en el gateway.

Está listo cuando

  • Un cambio incompatible en el contrato rompe la compilación de los controladores.
  • Superar el límite de peticiones devuelve 429 desde el gateway.

Katas: ejercicios cortos

Reglas de oro

  • Diseña el contrato OpenAPI YAML antes de escribir código Java (API-First).
  • El API Gateway es un enrutador sin estado; jamás pongas lógica de negocio allí.
  • Versiona tus APIs desde el día 1 con /api/v1/ en la URL.
  • Usa springdoc-openapi en Spring Boot 3, no springfox (abandonado).
  • En producción, desactiva el acceso público a Swagger UI con restricciones de red o seguridad.
Se guarda automáticamente

Fuentes oficiales

Revisado el . Este día en Markdown