Netflix Zuul

API Gateway pour microservices (Déprécié - Documentation Historique)

Introduction à Netflix Zuul

Qu'est-ce que Netflix Zuul ?

⚠️ ATTENTION - PRODUIT DÉPRÉCIÉ

Zuul 1 est officiellement déprécié. Cette documentation est fournie à titre historique et éducatif. Pour les nouveaux projets, utilisez Spring Cloud Gateway à la place.

Netflix Zuul était un service de routage et de filtrage d'API Gateway développé par Netflix. Il agissait comme un point d'entrée unique pour toutes les requêtes clientes vers les microservices, fournissant des fonctionnalités de routage dynamique, de surveillance, de résilience et de sécurité.

graph LR A[Client] --> B[Zuul
API Gateway] B --> C[Service A] B --> D[Service B] B --> E[Service C] style A fill:#FF9800,stroke:#E65100 style B fill:#4CAF50,stroke:#388E3C style C fill:#2196F3,stroke:#0D47A1 style D fill:#9C27B0,stroke:#4A148C style E fill:#FF5722,stroke:#E64A19

Fonctionnalités principales de Zuul :

  • Routage dynamique : Redirection des requêtes vers les services appropriés
  • Filtrage : Pré-filtres, filtres de routage, post-filtres
  • Sécurité : Authentification, autorisation, validation
  • Monitoring : Tracing des requêtes, métriques
  • Résilience : Gestion des erreurs, fallbacks
  • Load Balancing : Distribution de charge intégrée

Architecture avec Zuul

Structure de l'application

graph TD A[Client
Navigateur/App] --> B[Zuul Gateway
Port: 8762] B --> C[Eureka Server
Port: 8761] C --> D[Service A
Port: 8080] C --> E[Service B
Port: 8081] C --> F[Service C
Port: 8082] style A fill:#FF9800,stroke:#E65100 style B fill:#4CAF50,stroke:#388E3C style C fill:#2196F3,stroke:#0D47A1 style D fill:#9C27B0,stroke:#4A148C style E fill:#FF5722,stroke:#E64A19 style F fill:#8BC34A,stroke:#33691E

Rôles des composants :

  • Zuul Gateway : Point d'entrée unique pour toutes les requêtes
  • Eureka Server : Serveur de découverte de services
  • Services A, B, C : Microservices backend
  • Client : Applications clientes (navigateurs, mobiles, etc.)

Services Backend

1 Service A - Utilisateurs

Structure du projet :

serviceA/
├── pom.xml
└── src/main/
    ├── java/com/example/users/
    │   ├── UsersMicroserviceApplication.java
    │   ├── controller/
    │   │   └── UserController.java
    │   ├── model/
    │   │   └── User.java
    └── resources/
        └── application.properties
serviceA/pom.xml
<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Eureka Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>
serviceA/src/main/resources/application.properties
# === CONFIGURATION SERVEUR ===
server.port=8080
spring.application.name=service-a

# === CONFIGURATION EUREKA ===
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.prefer-ip-address=true
serviceA/src/main/java/com/example/users/model/User.java
package com.example.users.model;

public class User {
    private Long id;
    private String name;
    private String email;
    private String department;
    
 //construtors
    
    // Getters et Setters
   
serviceA/src/main/java/com/example/users/controller/UserController.java
package com.example.users.controller;

import com.example.users.model.User;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "*")
public class UserController {
    
    @GetMapping
    public List<User> getAllUsers() {
        return Arrays.asList(
            new User(1L, "John Doe", "john@example.com", "IT"),
            new User(2L, "Jane Smith", "jane@example.com", "HR")
        );
    }
    
    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return new User(id, "User " + id, "user" + id + "@example.com", "Department " + id);
    }
    
    @PostMapping
    public User createUser(@RequestBody User user) {
        user.setId(System.currentTimeMillis());
        return user;
    }
}
serviceA/src/main/java/com/example/users/UsersMicroserviceApplication.java
package com.example.users;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class UsersMicroserviceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UsersMicroserviceApplication.class, args);
    }
}

2 Service B - Produits

serviceB/src/main/resources/application.properties
# === CONFIGURATION SERVEUR ===
server.port=8081
spring.application.name=service-b

# === CONFIGURATION EUREKA ===
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.prefer-ip-address=true
serviceB/src/main/java/com/example/products/model/Product.java
package com.example.products.model;

public class Product {
    private Long id;
    private String name;
    private String description;
    private Double price;
    
//construtors
    
    // Getters et Setters
serviceB/src/main/java/com/example/products/controller/ProductController.java
package com.example.products.controller;

import com.example.products.model.Product;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/products")
@CrossOrigin(origins = "*")
public class ProductController {
    
    @GetMapping
    public List<Product> getAllProducts() {
        return Arrays.asList(
            new Product(1L, "Laptop", "High-performance laptop", 999.99),
            new Product(2L, "Smartphone", "Latest smartphone model", 699.99)
        );
    }
    
    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return new Product(id, "Product " + id, "Description " + id, 99.99 + id);
    }
    
    @PostMapping
    public Product createProduct(@RequestBody Product product) {
        product.setId(System.currentTimeMillis());
        return product;
    }
}

3 Service C - Commandes

serviceC/src/main/resources/application.properties
# === CONFIGURATION SERVEUR ===
server.port=8082
spring.application.name=service-c

# === CONFIGURATION EUREKA ===
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.prefer-ip-address=true
serviceC/src/main/java/com/example/orders/model/Order.java
package com.example.orders.model;

public class Order {
    private Long id;
    private Long userId;
    private Long productId;
    private Integer quantity;
    private Double totalAmount;
    
//constructors
    
    // Getters et Setters
   
serviceC/src/main/java/com/example/orders/controller/OrderController.java
package com.example.orders.controller;

import com.example.orders.model.Order;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/orders")
@CrossOrigin(origins = "*")
public class OrderController {
    
    @GetMapping
    public List<Order> getAllOrders() {
        return Arrays.asList(
            new Order(1L, 1L, 1L, 2, 1999.98),
            new Order(2L, 2L, 2L, 1, 699.99)
        );
    }
    
    @GetMapping("/{id}")
    public Order getOrderById(@PathVariable Long id) {
        return new Order(id, 1L, 1L, 1, 999.99);
    }
    
    @PostMapping
    public Order createOrder(@RequestBody Order order) {
        order.setId(System.currentTimeMillis());
        return order;
    }
}

Zuul Gateway

1 Configuration de Base de Zuul

⚠️ RAPPEL - Zuul est déprécié

Pour les nouveaux projets, utilisez Spring Cloud Gateway à la place.

Dépendances Maven :

zuul-gateway/pom.xml
<dependencies>
    <!-- Zuul -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    
    <!-- Eureka Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
    <!-- Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

Application principale :

zuul-gateway/src/main/java/com/example/gateway/ZuulGatewayApplication.java
package com.example.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 * Application Zuul Gateway
 * 
 * @EnableZuulProxy - Active Zuul comme proxy API Gateway
 * @EnableDiscoveryClient - Active la découverte de services via Eureka
 */
@SpringBootApplication
@EnableZuulProxy  // Active Zuul Proxy
@EnableDiscoveryClient  // Active Eureka Client
public class ZuulGatewayApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ZuulGatewayApplication.class, args);
    }
}

2 Configuration de Routage

Configuration application.properties :

zuul-gateway/src/main/resources/application.properties
# === CONFIGURATION SERVEUR ===
server.port=8762
spring.application.name=zuul-gateway

# === CONFIGURATION EUREKA ===
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.prefer-ip-address=true

# === CONFIGURATION ZUUL - ROUTAGE DE BASE ===

# Routage par service name (discovery-based routing)
zuul.routes.service-a.path=/api/users/**
zuul.routes.service-a.serviceId=service-a

zuul.routes.service-b.path=/api/products/**
zuul.routes.service-b.serviceId=service-b

zuul.routes.service-c.path=/api/orders/**
zuul.routes.service-c.serviceId=service-c

# === CONFIGURATION ZUUL - OPTIONS AVANCÉES ===

# Désactiver les routes automatiques
zuul.ignored-services=*

# Timeout configuration
zuul.host.connect-timeout-millis=5000
zuul.host.socket-timeout-millis=10000

# Buffer configuration
zuul.host.max-total-connections=200
zuul.host.max-per-route-connections=20

# === CONFIGURATION DES FILTRES ===

# Désactiver les headers sensibles par défaut
zuul.sensitive-headers=

# === CONFIGURATION ACTUATOR ===
management.endpoints.web.exposure.include=routes,filters,health,info
management.endpoint.routes.enabled=true
management.endpoint.filters.enabled=true

3 Filtres Zuul

Filtres personnalisés :

zuul-gateway/src/main/java/com/example/gateway/filter/PreLoggingFilter.java
package com.example.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * Filtre pré-routage pour le logging des requêtes
 * 
 * Type: pre - Exécuté avant le routage
 * Order: 1 - Ordre d'exécution
 */
@Component
public class PreLoggingFilter extends ZuulFilter {
    
    private static final Logger logger = LoggerFactory.getLogger(PreLoggingFilter.class);
    
    /**
     * Type de filtre :
     * - pre : Exécuté avant le routage
     * - route : Exécuté pendant le routage
     * - post : Exécuté après le routage
     * - error : Exécuté en cas d'erreur
     */
    @Override
    public String filterType() {
        return "pre";
    }
    
    /**
     * Ordre d'exécution du filtre
     * Plus le chiffre est petit, plus le filtre est exécuté tôt
     */
    @Override
    public int filterOrder() {
        return 1;
    }
    
    /**
     * Condition d'exécution du filtre
     * true = toujours exécuté
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    /**
     * Logique du filtre
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        
        logger.info("Pre Filter: {} request to {}", 
                   request.getMethod(), 
                   request.getRequestURL().toString());
        
        // Ajout d'un header personnalisé
        ctx.addZuulRequestHeader("X-Request-Time", String.valueOf(System.currentTimeMillis()));
        
        return null;
    }
}
zuul-gateway/src/main/java/com/example/gateway/filter/PostLoggingFilter.java
package com.example.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;

/**
 * Filtre post-routage pour le logging des réponses
 */
@Component
public class PostLoggingFilter extends ZuulFilter {
    
    private static final Logger logger = LoggerFactory.getLogger(PostLoggingFilter.class);
    
    @Override
    public String filterType() {
        return "post";
    }
    
    @Override
    public int filterOrder() {
        return 1;
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletResponse response = ctx.getResponse();
        
        long startTime = (Long) ctx.get("startTime");
        long duration = System.currentTimeMillis() - startTime;
        
        logger.info("Post Filter: Response status {} in {}ms", 
                   response.getStatus(), 
                   duration);
        
        return null;
    }
}
zuul-gateway/src/main/java/com/example/gateway/filter/PreTimeFilter.java
package com.example.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

/**
 * Filtre pour mesurer le temps de traitement
 */
@Component
public class PreTimeFilter extends ZuulFilter {
    
    @Override
    public String filterType() {
        return "pre";
    }
    
    @Override
    public int filterOrder() {
        return 0; // Exécuté en premier
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.set("startTime", System.currentTimeMillis());
        return null;
    }
}
zuul-gateway/src/main/java/com/example/gateway/filter/ErrorFilter.java
package com.example.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * Filtre pour la gestion des erreurs
 */
@Component
public class ErrorFilter extends ZuulFilter {
    
    private static final Logger logger = LoggerFactory.getLogger(ErrorFilter.class);
    
    @Override
    public String filterType() {
        return "error";
    }
    
    @Override
    public int filterOrder() {
        return 1;
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        Throwable throwable = ctx.getThrowable();
        
        logger.error("Error Filter: {}", throwable.getMessage(), throwable);
        
        return null;
    }
}

4 Filtres de Sécurité

Filtres d'authentification :

zuul-gateway/src/main/java/com/example/gateway/filter/AuthFilter.java
package com.example.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Filtre d'authentification basique
 */
@Component
public class AuthFilter extends ZuulFilter {
    
    private static final Logger logger = LoggerFactory.getLogger(AuthFilter.class);
    
    @Override
    public String filterType() {
        return "pre";
    }
    
    @Override
    public int filterOrder() {
        return 2; // Exécuté après PreTimeFilter
    }
    
    @Override
    public boolean shouldFilter() {
        // Appliquer le filtre à toutes les requêtes sauf /api/public/**
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        return !request.getRequestURI().startsWith("/api/public/");
    }
    
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        
        // Vérification du header d'authentification
        String authorizationHeader = request.getHeader("Authorization");
        
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            logger.warn("Unauthorized access to {}", request.getRequestURI());
            
            // Bloquer la requête
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            
            try {
                HttpServletResponse response = ctx.getResponse();
                response.getWriter().write("{\"error\": \"Unauthorized\"}");
                response.setContentType("application/json");
            } catch (Exception e) {
                throw new ZuulException(e, 401, "Unauthorized");
            }
            
            return null;
        }
        
        logger.info("Authorized access to {}", request.getRequestURI());
        return null;
    }
}

5 Configuration Avancée

Configuration étendue :

zuul-gateway/src/main/resources/application-advanced.properties
# === CONFIGURATION ZUUL AVANCÉE ===

# === ROUTAGE PERSONNALISÉ ===

# Routage avec préfixe
zuul.routes.users.path=/api/v1/users/**
zuul.routes.users.serviceId=service-a
zuul.routes.users.strip-prefix=false

# Routage avec URL statique
zuul.routes.external.path=/api/external/**
zuul.routes.external.url=http://external-api.example.com

# Routage avec load balancing personnalisé
zuul.routes.loadbalanced.path=/api/balanced/**
zuul.routes.loadbalanced.serviceId=service-a

# === CONFIGURATION DES TIMEOUTS ===

# Timeout pour les connexions
zuul.host.connect-timeout-millis=10000
zuul.host.socket-timeout-millis=20000

# Timeout pour les routes spécifiques
zuul.routes.service-a.sensitive-headers=Cookie,Set-Cookie
zuul.routes.service-a.custom-sensitive-headers=true

# === CONFIGURATION DES HEADERS ===

# Headers à ignorer
zuul.ignored-headers=Access-Control-Allow-Credentials,Access-Control-Allow-Origin

# Headers sensibles (par défaut: Cookie,Set-Cookie,Authorization)
zuul.sensitive-headers=Cookie,Set-Cookie

# === CONFIGURATION DE LA SÉCURITÉ ===

# Désactiver les routes non sécurisées
zuul.ignored-patterns=/**/admin/**

# === CONFIGURATION DES FILTRES ===

# Désactiver les filtres par défaut
zuul.PreDecorationFilter.pre.disable=true

# === CONFIGURATION DES MÉTRIQUES ===

# Activer les métriques Hystrix
zuul.ribbon-isolation-strategy=THREAD

# === CONFIGURATION DU BUFFER ===

# Taille maximale du buffer
zuul.buffer-size=8192

# === CONFIGURATION DES CORS ===

# Activer CORS
zuul.allow-credentials=true
zuul.allowed-origins=*
zuul.allowed-methods=GET,POST,PUT,DELETE
zuul.allowed-headers=*
zuul.exposed-headers=Authorization,X-Total-Count

Utilisation et Tests

1 Exemples d'Utilisation

Requêtes via Zuul :

Accès aux services via Zuul :

# === REQUÊTES DIRECTES AUX SERVICES ===

# Service A - Utilisateurs
GET http://localhost:8080/api/users
GET http://localhost:8080/api/users/1

# Service B - Produits
GET http://localhost:8081/api/products
GET http://localhost:8081/api/products/1

# Service C - Commandes
GET http://localhost:8082/api/orders
GET http://localhost:8082/api/orders/1

# === REQUÊTES VIA ZUUL GATEWAY ===

# Mêmes requêtes via Zuul
GET http://localhost:8762/api/users
GET http://localhost:8762/api/users/1

GET http://localhost:8762/api/products
GET http://localhost:8762/api/products/1

GET http://localhost:8762/api/orders
GET http://localhost:8762/api/orders/1

# === REQUÊTES AVEC AUTHENTIFICATION ===
GET http://localhost:8762/api/users
Authorization: Bearer your-token-here

POST http://localhost:8762/api/users
Content-Type: application/json
Authorization: Bearer your-token-here

{
    "name": "New User",
    "email": "newuser@example.com",
    "department": "IT"
}

2 Tests et Validation

Tests Postman/Curl :

# === TESTS AVEC CURL ===

# Test de routage basique
curl -X GET http://localhost:8762/api/users

# Test avec authentification
curl -X GET http://localhost:8762/api/users \
  -H "Authorization: Bearer test-token"

# Test de création
curl -X POST http://localhost:8762/api/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer test-token" \
  -d '{"name":"Test User","email":"test@example.com","department":"TEST"}'

# Test de routage vers différents services
curl -X GET http://localhost:8762/api/products
curl -X GET http://localhost:8762/api/orders

# === TESTS DES ENDPOINTS ACTUATOR ===

# Liste des routes
curl -X GET http://localhost:8762/actuator/routes

# Liste des filtres
curl -X GET http://localhost:8762/actuator/filters

# Health check
curl -X GET http://localhost:8762/actuator/health

Tableau Récapitulatif des Fonctionnalités

Fonctionnalité Zuul Spring Cloud Gateway État
Routage Basé sur Servlet Reactive (WebFlux) ⚠️ Zuul / ✅ Gateway
Filtres ZuulFilter GatewayFilter ⚠️ Legacy / ✅ Moderne
Load Balancing Ribbon intégré LoadBalancer réactif ⚠️ Zuul / ✅ Gateway
Performance Bloquant Non-bloquant ⚠️ Limité / ✅ Supérieur
Maintenance Déprécié Actif ⚠️ Arrêté / ✅ Actif
Écosystème Netflix OSS Spring Cloud ⚠️ Legacy / ✅ Intégré

Bonnes Pratiques et Conseils

1 Configuration Optimale

Configuration recommandée pour Zuul :

# === CONFIGURATION ZUUL OPTIMALE ===

# Timeout raisonnable
zuul.host.connect-timeout-millis=5000
zuul.host.socket-timeout-millis=10000

# Buffer adapté
zuul.buffer-size=8192

# Connexions
zuul.host.max-total-connections=200
zuul.host.max-per-route-connections=20

# === CONFIGURATION DES ROUTES ===

# Routage sécurisé
zuul.routes.secure.path=/api/secure/**
zuul.routes.secure.serviceId=secure-service
zuul.routes.secure.sensitive-headers=Cookie,Set-Cookie,Authorization

# Routage public
zuul.routes.public.path=/api/public/**
zuul.routes.public.serviceId=public-service
zuul.routes.public.sensitive-headers=

# === CONFIGURATION DES HEADERS ===

# Headers à ignorer pour la sécurité
zuul.ignored-headers=Access-Control-Allow-Origin,Access-Control-Allow-Credentials

# Headers sensibles par défaut
zuul.sensitive-headers=Cookie,Set-Cookie,Authorization

Conclusion

Points Clés à Retenir

⚠️ Zuul est DÉPRÉCIÉ

Utilisez Spring Cloud Gateway pour les nouveaux projets !

graph TB A[Zuul] --> B[Fonctionnalités] A --> C[Architecture] A --> D[Configuration] A --> E[Filtres] A --> F[Migration] B --> B1[Routage] B --> B2[Filtrage] B --> B3[Sécurité] B --> B4[Load Balancing] C --> C1[Eureka] C --> C2[Services] C --> C3[Gateway] D --> D1[Properties] D2[Routes] D3[Timeouts] E --> E1[Pre-filtres] E2[Post-filtres] E3[Error-filtres] F --> F1[Spring Cloud Gateway] F2[Configuration] F3[Filtres] style A fill:#f44336,stroke:#d32f2f style B fill:#2196F3,stroke:#0D47A1 style C fill:#FF9800,stroke:#E65100 style D fill:#9C27B0,stroke:#4A148C style E fill:#4CAF50,stroke:#388E3C style F fill:#FF5722,stroke:#E64A19

Résumé historique :

  • Zuul était l'API Gateway Netflix pour les microservices
  • Utilisait des ZuulFilter pour le pré/post-traitement
  • Fournissait du routage dynamique via Eureka
  • Incluait des fonctionnalités de sécurité et de monitoring
  • Déprécié au profit de Spring Cloud Gateway

⚠️ Points d'attention :

  • Ne pas utiliser pour les nouveaux projets
  • Migrer les projets existants vers Spring Cloud Gateway
  • Maintenir les projets Zuul existants avec prudence
  • Surveiller les vulnérabilités de sécurité