
Passerelle d'API (API Gateway) avec Spring Cloud Gateway
Découvrez le pattern API Gateway et apprenez à implémenter une passerelle réactive, robuste et flexible avec Spring Cloud Gateway pour vos microservices Spring Boot.
Introduction au pattern API Gateway
Dans une architecture microservices, les clients (applications web frontend, applications mobiles, autres services) doivent interagir avec de multiples services backend. Exposer directement tous ces microservices aux clients présente plusieurs inconvénients : couplage fort, multiplication des points d'entrée à gérer, complexité pour le client qui doit connaître l'adresse de chaque service, et difficulté à gérer des préoccupations transversales comme l'authentification, la limitation de débit (rate limiting) ou la journalisation de manière centralisée.
Le pattern API Gateway (Passerelle d'API) résout ces problèmes en introduisant une couche intermédiaire unique qui agit comme le point d'entrée unique pour toutes les requêtes externes vers les microservices backend. C'est une façade qui simplifie l'interaction avec l'écosystème de microservices.
Les responsabilités typiques d'une API Gateway incluent :
- Routage des requêtes : Diriger les requêtes entrantes vers le microservice approprié en fonction du chemin, de l'hôte, des en-têtes, etc.
- Composition/Agrégation d'API : Parfois, agréger les réponses de plusieurs microservices pour fournir une réponse unique au client.
- Découplage : Masquer la structure interne des microservices aux clients externes.
- Gestion des préoccupations transversales (Cross-Cutting Concerns) :
- Authentification et Autorisation
- Terminaison SSL/TLS
- Limitation de débit (Rate Limiting)
- Mise en cache des réponses
- Journalisation (Logging) et Monitoring
- Transformation des requêtes/réponses
- Gestion des Circuit Breakers
- Traduction de protocoles : Exposer une API REST standard même si les services internes utilisent d'autres protocoles (ex: gRPC, AMQP).
En centralisant ces aspects, l'API Gateway simplifie grandement les microservices backend (qui peuvent se concentrer sur leur logique métier) et les clients (qui n'interagissent qu'avec un seul point d'entrée).
Présentation de Spring Cloud Gateway
Spring Cloud Gateway est le projet de l'écosystème Spring Cloud dédié à la création d'API Gateways. C'est une solution moderne, construite sur une pile technologique entièrement réactive et non bloquante :
- Project Reactor
- Spring Framework 5+
- Spring Boot 2+
- Spring WebFlux
Il s'exécute sur des serveurs non bloquants comme Netty. Cette nature réactive le rend particulièrement bien adapté pour gérer un grand nombre de connexions concurrentes avec une utilisation efficace des ressources, ce qui est crucial pour un composant critique comme une passerelle qui gère tout le trafic entrant.
Spring Cloud Gateway est conçu pour remplacer l'ancien projet Spring Cloud Netflix Zuul 1, qui était basé sur une architecture bloquante (basée sur les Servlets). Spring Cloud Gateway offre de meilleures performances, une meilleure scalabilité et un modèle de programmation plus cohérent avec les applications réactives modernes.
Concepts fondamentaux de Spring Cloud Gateway
Le fonctionnement de Spring Cloud Gateway repose sur trois concepts principaux :
- Route : L'élément de base de la passerelle. Une route est définie par un identifiant unique (ID), une URI de destination (vers où router la requête), une collection de Predicates (conditions pour que la route corresponde à une requête), et une collection de Filters (modifications à appliquer à la requête ou à la réponse). Si les prédicats d'une route correspondent à la requête entrante, la requête est routée vers l'URI de destination après application des filtres.
- Predicate (Prédicat) : C'est une condition qui permet de faire correspondre une requête HTTP entrante à une route spécifique. Spring Cloud Gateway fournit de nombreux prédicats intégrés basés sur divers attributs de la requête : chemin (Path), méthode HTTP (Method), en-têtes (Header), paramètres de requête (Query Param), hôte (Host), cookie, adresse IP distante (RemoteAddr), etc. Plusieurs prédicats peuvent être combinés avec des opérateurs logiques (ET). Une requête doit satisfaire tous les prédicats d'une route pour être traitée par celle-ci.
- Filter (Filtre) : Ce sont des composants qui permettent de modifier la requête HTTP entrante avant qu'elle ne soit envoyée à la destination, ou de modifier la réponse HTTP sortante avant qu'elle ne soit renvoyée au client. Les filtres peuvent être appliqués globalement (à toutes les routes) ou spécifiquement à une route donnée (GatewayFilter). Exemples de filtres intégrés : ajout/suppression d'en-têtes, réécriture de chemin (RewritePath), ajout de paramètres, limitation de débit (RateLimiter), intégration de circuit breaker (CircuitBreaker), etc. Vous pouvez également créer vos propres filtres personnalisés.
Le flux d'une requête est donc : Requête entrante -> Evaluation des Prédicats des Routes -> Application des Filtres de la Route correspondante -> Routage vers l'URI de destination -> Réception de la réponse -> Application des Filtres sur la réponse -> Réponse renvoyée au client.
Mise en place et configuration
Pour utiliser Spring Cloud Gateway, ajoutez la dépendance `spring-cloud-starter-gateway` à votre projet Spring Boot (notez qu'il ne faut pas inclure `spring-boot-starter-web` ou `spring-boot-starter-webflux` en même temps, car Gateway fournit sa propre runtime) :
Maven :
org.springframework.cloud
spring-cloud-starter-gateway
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
Les routes peuvent être configurées de deux manières principales :
1. Via `application.yml` ou `application.properties` (Configuration simple) :
# application.yml
spring:
application:
name: api-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # Active le routage basé sur la découverte de service (si discovery client est présent)
lower-case-service-id: true # Route /user-service/** vers le service "user-service"
routes:
- id: product_route # ID unique de la route
uri: lb://product-service # URI de destination (lb:// pour load-balanced via service discovery)
predicates:
- Path=/products/** # Prédicat: correspond si le chemin commence par /products/
# filters:
# - RewritePath=/products/(?.*), /${segment} # Filtre: réécrit le chemin avant de router
- id: user_route
uri: lb://user-service
predicates:
- Path=/users/**
# Exemple avec un service externe
- id: httpbin_route
uri: https://httpbin.org:443 # URI directe
predicates:
- Path=/httpbin/**
filters:
- RewritePath=/httpbin/(?.*), /${segment}
- AddRequestHeader=X-Gateway-Source, SpringCloudGateway
2. Via la configuration Java (`RouteLocatorBuilder`) (Plus flexible) :
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("product_route_java", r -> r.path("/products-java/**") // Prédicat Path
.filters(f -> f.rewritePath("/products-java/(?.*)", "/${segment}") // Filtre RewritePath
.addRequestHeader("X-Source", "JavaConfig"))
.uri("lb://product-service")) // Destination
.route("user_route_java", r -> r.path("/users-java/**")
.and().method("GET", "POST") // Prédicat combiné (Path ET Method)
.uri("lb://user-service"))
.route("httpbin_route_java", r -> r.host("*.myhost.org") // Prédicat Host
.and().path("/httpbin-java/**")
.filters(f -> f.rewritePath("/httpbin-java/(?.*)", "/${segment}"))
.uri("https://httpbin.org"))
.build();
}
}
Fonctionnalités clés et intégrations
Au-delà du routage de base, Spring Cloud Gateway excelle dans l'application des préoccupations transversales via ses filtres :
- Intégration avec la Découverte de Services : Comme vu dans les exemples, en utilisant le préfixe `lb://` dans l'URI (ex: `lb://product-service`), Gateway s'intègre avec le client de découverte (Eureka, Consul) pour trouver dynamiquement les instances du service `product-service` et répartir la charge entre elles.
- Sécurité : S'intègre avec Spring Security pour sécuriser les endpoints exposés par la passerelle (authentification OAuth2/OIDC, JWT, etc.). Des filtres peuvent valider les tokens, ajouter des en-têtes d'authentification pour les services backend, etc.
- Limitation de Débit (Rate Limiting) : Fournit un filtre `RequestRateLimiter` (souvent utilisé avec Redis) pour limiter le nombre de requêtes par utilisateur, IP ou autre critère.
- Tolérance aux Pannes (Circuit Breaking) : Intégration avec des bibliothèques comme Resilience4j via un filtre `CircuitBreaker`. La passerelle peut ainsi éviter d'appeler des services backend défaillants et retourner une réponse de secours.
- Modification des Requêtes/Réponses : Filtres pour ajouter/supprimer/modifier des en-têtes, des paramètres, ou même le corps des requêtes/réponses.
Conclusion : La porte d'entrée de votre écosystème
Spring Cloud Gateway est une solution moderne, performante et flexible pour implémenter le pattern API Gateway dans un écosystème microservices basé sur Spring Boot. Sa nature réactive le rend adapté aux charges de travail exigeantes, et son système de routes, prédicats et filtres offre un contrôle fin sur le trafic entrant.
Bien qu'une API Gateway introduise un composant supplémentaire dans l'architecture (qui doit être géré, sécurisé et mis à l'échelle), les bénéfices en termes de simplification, de sécurité et de gestion centralisée des préoccupations transversales en font un élément quasi indispensable pour toute architecture microservices sérieuse. Spring Cloud Gateway fournit les outils nécessaires pour construire cette porte d'entrée essentielle de manière robuste et efficace.