Patterns de Circuit Breaker pour les Gateways API Expliqués
Les circuit breakers sont des patterns de résilience critiques qui empêchent les pannes en cascade dans les systèmes distribués en bloquant temporairement les requêtes vers les backends défaillants. Dans les gateways API, ils agissent comme des interrupteurs de sécurité automatiques qui détectent les pannes, arrêtent de transférer le trafic vers les services défaillants, et laissent le temps aux systèmes de récupérer avant de reprendre les opérations normales.
Qu'est-ce qu'un Circuit Breaker ?
Un circuit breaker est un design pattern emprunté à l'électrotechnique qui protège les systèmes distribués contre les pannes en cascade. Tout comme un disjoncteur électrique coupe le courant quand un circuit est surchargé, un circuit breaker de gateway API arrête le trafic vers un service backend défaillant.
Le Problème : les Pannes en Cascade
Sans circuit breakers, un seul backend lent ou défaillant peut déclencher un effet domino :
- Le service backend ralentit à cause d'une charge élevée, de problèmes de base de données ou de pannes downstream
- Les threads du gateway s'accumulent en attendant des réponses qui n'arrivent jamais ou qui expirent lentement
- L'épuisement des ressources survient quand les pools de connexions, les threads et la mémoire se remplissent
- Les services sains souffrent car le gateway devient non réactif à tout le trafic
- Panne complète du système quand toute l'infrastructure API s'effondre
Prenons l'exemple d'une plateforme e-commerce où le service de paiement tombe en panne. Sans circuit breakers :
Client Request → Gateway (waiting...) → Payment Service (down)
↓ (300 threads blocked)
Client Request → Gateway (waiting...) → Payment Service (down)
↓ (600 threads blocked)
Client Request → Gateway (TIMEOUT) → All Services (unreachable)
Le pool de connexions du gateway est épuisé à attendre un service qui ne répondra pas. Maintenant même les services sains comme le catalogue produits ou les profils utilisateurs deviennent inaccessibles.
La Solution : Échouer Rapidement
Les circuit breakers implémentent une stratégie de "fail fast" (échec rapide). Au lieu d'attendre les timeouts sur chaque requête, le gateway détecte les patterns de panne et rejette immédiatement les requêtes vers les backends défaillants :
Client Request → Gateway (Circuit OPEN) → 503 Service Unavailable (instant)
↓ (0 threads blocked)
Client Request → Gateway (Circuit OPEN) → 503 Service Unavailable (instant)
Cela évite l'épuisement des ressources et permet au système de dégrader gracieusement. Les clients reçoivent des erreurs immédiates qu'ils peuvent gérer, plutôt que de rester suspendus indéfiniment.
Pourquoi les Gateways API ont Besoin de Circuit Breakers
Les gateways API se trouvent au point d'entrée de votre système distribué, ce qui en fait l'endroit idéal pour implémenter les circuit breakers. Voici pourquoi :
1. Détection Centralisée des Pannes
Le gateway voit tous les patterns de trafic sur tous les backends. Il peut détecter :
- La montée des taux d'erreur (réponses 5xx)
- L'augmentation de la latence (temps de réponse lents)
- Les échecs de connexion (connexions refusées, erreurs DNS)
- Les patterns de timeout (requêtes dépassant les délais)
2. Protection pour Tous les Clients
Un circuit breaker au niveau du gateway protège tous les clients downstream, quelle que soit leur implémentation. Que vous ayez des navigateurs web, des applications mobiles ou des microservices internes effectuant des appels API, ils bénéficient tous de la logique de résilience du gateway.
3. Protection du Service Backend
Quand un backend est sous charge, continuer à envoyer du trafic rend la récupération plus difficile. Les circuit breakers donnent aux services défaillants une marge de récupération en arrêtant temporairement les requêtes entrantes, leur permettant de :
- Vider les files de travail en attente
- Restaurer les connexions à la base de données
- Augmenter les ressources
- Terminer les transactions en cours
4. Frontières de Panne Observables
Les changements d'état des circuit breakers sont des événements hautement observables. Quand un circuit s'ouvre, cela signale un problème de santé du système que les équipes opérationnelles peuvent investiguer. Cela rend la réponse aux incidents plus rapide et plus ciblée.
Pour une compréhension plus approfondie de comment les circuit breakers s'intègrent dans les architectures modernes de gateways API, consultez notre Guide d'Architecture Gateway API.
Les Trois États : Fermé, Ouvert, Semi-Ouvert
Les circuit breakers fonctionnent comme des machines à états finis avec trois états distincts. Comprendre ces états est crucial pour une configuration efficace.
Diagramme d'État
┌─────────────┐
│ CLOSED │ ◄─── État initial
│ (sain) │
└──────┬──────┘
│
Seuil de panne
atteint (ex : 5
erreurs consécutives)
│
▼
┌─────────────┐
┌───────┤ OPEN │
│ │ (panne) │
│ └──────┬──────┘
│ │
Requêtes échouent Fenêtre de
immédiatement sommeil
avec 503 expire (ex :
│ 30 secondes)
│ │
│ ▼
│ ┌─────────────┐
│ │ HALF-OPEN │
│ │ (test) │
│ └──────┬──────┘
│ │
│ ┌─────┴─────┐
│ │ │
│ Seuil de Seuil de
│ succès panne
│ atteint atteint
│ │ │
└────────┴───────────┘
État Fermé (Opération Normale)
Comportement : Toutes les requêtes passent vers le backend. Le circuit breaker surveille les réponses.
Surveillance :
- Comptage des pannes consécutives
- Suivi des taux d'erreur sur des fenêtres glissantes
- Mesure des latences de réponse
Transition vers Ouvert : Quand le seuil de panne est dépassé. Déclencheurs courants :
- 5+ pannes consécutives
- Taux d'erreur de 50%+ sur 10 requêtes
- 3+ timeouts en 30 secondes
Exemple de Configuration (YAML) :
circuitBreaker:
state: closed
failureThreshold: 5
successThreshold: 2
timeout: 30s
monitoringWindow: 60s
État Ouvert (Blocage du Trafic)
Comportement : Toutes les requêtes échouent immédiatement avec 503 Service Unavailable. Aucun appel backend n'est effectué.
Objectif :
- Prévenir l'épuisement des ressources
- Donner au backend le temps de récupérer
- Échouer rapidement pour les clients
Transition vers Semi-Ouvert : Après une fenêtre de sommeil configurable (ex : 30 secondes). Cette fenêtre permet au backend de récupérer avant le début des tests.
Réponse Client :
HTTP/1.1 503 Service Unavailable
Content-Type: application/json
Retry-After: 30
{
"error": "circuit_breaker_open",
"message": "Backend service is temporarily unavailable",
"retry_after_seconds": 30
}
État Semi-Ouvert (Test de Récupération)
Comportement : Un nombre limité de requêtes de test sont autorisées pour vérifier si le backend a récupéré.
Stratégie de Test :
- Autoriser 1 à 3 requêtes sondes
- Si toutes réussissent → transition vers Fermé
- Si l'une échoue → transition vers Ouvert
Exemple de Configuration :
circuitBreaker:
halfOpen:
maxRequests: 3 # Nombre de requêtes de test
successThreshold: 2 # Succès nécessaires pour fermer
timeout: 10s # Timeout par requête de test
Pourquoi c'est Important : Le semi-ouvert évite le problème du "thundering herd". Sans lui, quand la fenêtre de sommeil expire, toutes les requêtes bloquées frapperaient simultanément le backend en cours de récupération, pouvant le faire tomber à nouveau.
Patterns d'Implémentation
Les circuit breakers peuvent être définis à différents niveaux dans votre architecture de gateway. Chacun a ses compromis.
1. Circuit Breakers par Route
Portée : Un circuit breaker par endpoint API.
Cas d'Usage : Contrôle fin quand différentes routes ont des caractéristiques de fiabilité différentes.
Configuration :
routes:
- path: /api/v1/payments
backend: http://payment-service:8080
circuitBreaker:
enabled: true
failureThreshold: 3
timeout: 20s
sleepWindow: 60s
- path: /api/v1/products
backend: http://catalog-service:8080
circuitBreaker:
enabled: true
failureThreshold: 10
timeout: 5s
sleepWindow: 30s
Avantages :
- Pannes isolées : l'ouverture du circuit
/paymentsn'affecte pas/products - Seuils ajustés : les endpoints critiques peuvent avoir des seuils plus stricts
- Surveillance granulaire : métriques par route pour les équipes opérationnelles
Inconvénients :
- Complexité de configuration : chaque route a besoin d'un ajustement
- Surcharge mémoire : un état de circuit breaker par route
2. Circuit Breakers par Backend
Portée : Un circuit breaker par service backend (partagé entre toutes les routes vers ce service).
Cas d'Usage : Quand les routes vers le même backend doivent partager la détection de panne.
Configuration :
backends:
payment-service:
url: http://payment-service:8080
circuitBreaker:
enabled: true
failureThreshold: 5
timeout: 30s
routes:
- path: /api/v1/payments/create
backend: payment-service
- path: /api/v1/payments/status
backend: payment-service
Avantages :
- Configuration simplifiée : une définition de circuit breaker par service
- État de panne partagé : si le backend est down, toutes les routes arrêtent de l'appeler
- Empreinte mémoire réduite
Inconvénients :
- Granularité faible : une route lente peut déclencher le circuit pour toutes les routes
- Moins de flexibilité : impossible d'ajuster le comportement par route
3. Circuit Breakers Globaux
Portée : Un circuit breaker protégeant l'intégralité du gateway.
Cas d'Usage : Coupure d'urgence pour protéger le gateway lui-même de la surcharge.
Configuration :
global:
circuitBreaker:
enabled: true
failureThreshold: 100 # Seuil élevé
errorRate: 0.5 # Taux d'erreur de 50%
monitoringWindow: 10s
sleepWindow: 60s
Avantages :
- Protection ultime : empêche l'effondrement total du gateway
- Simple à raisonner : un état pour l'ensemble du système
Inconvénients :
- Trop grossier : les backends sains souffrent quand d'autres tombent
- Rarement utilisé : typiquement un mécanisme de dernier recours
Approche Hybride Recommandée
Dans les systèmes de production, combinez les circuit breakers par backend et globaux :
# Circuit breakers par backend pour l'isolation au niveau service
backends:
payment-service:
circuitBreaker:
failureThreshold: 5
timeout: 30s
catalog-service:
circuitBreaker:
failureThreshold: 10
timeout: 10s
# Circuit breaker global comme coupure d'urgence
global:
circuitBreaker:
failureThreshold: 1000
errorRate: 0.8
monitoringWindow: 30s
Cela assure l'isolation au niveau service tout en protégeant contre les pannes catastrophiques.
Pour plus de patterns sur les architectures de gateways résilientes, consultez Patterns de Gateway API Natif Kubernetes.
Bonnes Pratiques de Configuration
Une configuration efficace des circuit breakers nécessite de comprendre vos patterns de trafic et vos modes de panne.
1. Définir les Seuils de Panne en Fonction du Volume de Trafic
Routes à faible trafic (< 10 requêtes/minute) :
failureThreshold: 3 # 3 pannes consécutives
timeout: 60s
Routes à fort trafic (> 100 requêtes/minute) :
failureThreshold: 10
slidingWindow: 20 # Surveiller les 20 dernières requêtes
errorRate: 0.5 # Ouvrir à 50% de taux d'erreur
timeout: 30s
Pourquoi : Les routes à faible trafic ont besoin de comptages de pannes consécutives (absolu). Les routes à fort trafic ont besoin de pourcentages de taux d'erreur (relatif) pour éviter les faux positifs dus aux pannes occasionnelles.
2. Ajuster les Fenêtres de Sommeil au Temps de Récupération du Backend
Services à récupération rapide (microservices sans état) :
sleepWindow: 10s # Réessai rapide
Services à récupération lente (bases de données, systèmes legacy) :
sleepWindow: 120s # Donner plus de temps de récupération
Pourquoi : Les fenêtres de sommeil devraient correspondre aux patterns de récupération observés de votre backend. Trop courtes et vous frapperez répétitivement un service défaillant. Trop longues et vous prolongerez les pannes.
3. Configurer les Requêtes de Test en Semi-Ouvert
Test conservateur :
halfOpen:
maxRequests: 1
successThreshold: 3 # 3 succès nécessaires pour fermer
Test agressif :
halfOpen:
maxRequests: 5
successThreshold: 3 # 3 succès sur 5 pour fermer
Pourquoi : Le test conservateur (1 requête à la fois) est plus sûr pour les backends critiques. Le test agressif (plusieurs sondes simultanées) accélère la détection de récupération.
4. Aligner les Timeouts avec la Logique du Circuit Breaker
Le timeout du circuit breaker devrait être plus court que le timeout de la requête :
request:
timeout: 10s # Délai global de la requête
circuitBreaker:
timeout: 8s # Timeout du circuit breaker (plus court)
failureThreshold: 3
Pourquoi : Si le timeout du circuit breaker est plus long que le timeout de la requête, la requête échouera à cause du timeout avant que le circuit breaker ne la compte comme une panne.
5. Utiliser des Seuils Différents pour les Différents Types d'Erreur
Certaines erreurs sont répétables, d'autres non :
circuitBreaker:
failureThreshold: 5
# Erreurs qui déclenchent le circuit
triggerOn:
- 500 # Internal Server Error
- 502 # Bad Gateway
- 503 # Service Unavailable
- 504 # Gateway Timeout
- connection_refused
- timeout
# Erreurs qui ne déclenchent pas le circuit
ignoreOn:
- 400 # Bad Request (erreur client)
- 401 # Unauthorized (erreur d'auth)
- 404 # Not Found (erreur de routage)
Pourquoi : Les erreurs client (4xx) indiquent généralement de mauvaises requêtes, pas des pannes backend. Seules les erreurs serveur (5xx) et les pannes réseau devraient compter dans les seuils du circuit breaker.
Exemple : Configuration Prête pour la Production
routes:
- path: /api/v1/payments/charge
backend: payment-service
circuitBreaker:
enabled: true
# Détection de panne
failureThreshold: 5
slidingWindow: 10
errorRate: 0.5
# Timeouts
timeout: 8s
sleepWindow: 30s
# Test semi-ouvert
halfOpen:
maxRequests: 2
successThreshold: 2
# Classification des erreurs
triggerOn:
- 500
- 502
- 503
- 504
- timeout
- connection_error
# Surveillance
metrics:
enabled: true
labels:
service: payment
criticality: high
Pour des options complètes de configuration du gateway, consultez la Référence de Configuration.
Surveillance et Alertes
Les circuit breakers ne sont efficaces que si vous surveillez leurs changements d'état et répondez aux incidents.
Métriques Clés à Suivre
Métriques d'État du Circuit :
circuit_breaker_state{route="/api/v1/payments", backend="payment-service"}
Valeurs : 0 (fermé), 1 (ouvert), 2 (semi-ouvert)
circuit_breaker_state_changes_total{route="/api/v1/payments", backend="payment-service", from="closed", to="open"}
Compteur : s'incrémente quand le circuit s'ouvre
Métriques de Panne :
circuit_breaker_failures_total{route="/api/v1/payments", backend="payment-service"}
Compteur : total des pannes détectées
circuit_breaker_consecutive_failures{route="/api/v1/payments", backend="payment-service"}
Gauge : nombre actuel de pannes consécutives
Métriques de Requête :
circuit_breaker_requests_total{route="/api/v1/payments", backend="payment-service", result="success|failure|rejected"}
Compteur : total des requêtes par résultat
circuit_breaker_request_duration_seconds{route="/api/v1/payments", backend="payment-service"}
Histogramme : distribution de latence des requêtes
Règles d'Alertes
Alerte Critique : Circuit Ouvert
- alert: CircuitBreakerOpen
expr: circuit_breaker_state{criticality="high"} == 1
for: 1m
labels:
severity: critical
annotations:
summary: "Circuit breaker ouvert pour {{ $labels.route }}"
description: "Le backend {{ $labels.backend }} est défaillant. Circuit ouvert pour protéger le système."
Alerte Avertissement : Changements d'État Fréquents
- alert: CircuitBreakerFlapping
expr: rate(circuit_breaker_state_changes_total[5m]) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "Circuit breaker instable pour {{ $labels.route }}"
description: "Circuit changeant d'état fréquemment. Le backend peut être instable."
Exemple de Tableau de Bord
Un tableau de bord circuit breaker de production devrait inclure :
- Panneau d'État Global : État actuel de tous les circuits (vert = fermé, rouge = ouvert, jaune = semi-ouvert)
- Timeline des États : Graphique montrant les changements d'état dans le temps
- Panneau de Taux d'Erreur : Taux d'erreur par backend avec ligne de seuil
- Panneau de Latence : Percentiles de temps de réponse (p50, p95, p99)
- Panneau de Volume de Requêtes : Requêtes acceptées vs rejetées
- Panneau de Durée dans l'État : Combien de temps chaque circuit est dans son état actuel
Exemple de Requête Prometheus :
# États du circuit breaker sur tous les backends
sum by (backend, state) (circuit_breaker_state)
# Taux d'erreur sur les 5 dernières minutes
rate(circuit_breaker_failures_total[5m])
/ rate(circuit_breaker_requests_total[5m])
# Taux de rejet de requêtes
rate(circuit_breaker_requests_total{result="rejected"}[1m])
Pour plus de patterns d'observabilité, consultez le Guide de Renforcement de la Sécurité Gateway API qui couvre la surveillance des événements de sécurité.
Exemple Concret : Plateforme E-Commerce
Parcourons un scénario pratique de circuit breakers en action.
Architecture du Système
Client → API Gateway → [ Payment Service ]
→ [ Inventory Service ]
→ [ Notification Service ]
Scénario : Panne de Base de Données du Service de Paiement
Chronologie :
T+0s : La base de données du service de paiement manque de connexions. Les requêtes commencent à expirer.
T+5s : Le gateway détecte 5 erreurs de timeout consécutives sur /api/v1/payments/charge. Le circuit breaker s'ouvre.
# Logs du gateway
[INFO] Circuit breaker OPENED for route=/api/v1/payments/charge backend=payment-service
[INFO] Reason: 5 consecutive timeouts exceeded threshold
T+6s : Les nouvelles requêtes de paiement reçoivent des réponses 503 immédiates :
curl -X POST https://api.example.com/api/v1/payments/charge \
-H "Content-Type: application/json" \
-d '{"amount": 100, "currency": "USD"}'
# Réponse (instantanée, sans appel backend)
HTTP/1.1 503 Service Unavailable
Retry-After: 30
{
"error": "circuit_breaker_open",
"message": "Payment service is temporarily unavailable",
"retry_after_seconds": 30
}
T+35s : La fenêtre de sommeil expire. Le circuit passe en semi-ouvert.
T+36s : Le gateway envoie une requête de test au service de paiement. Le backend a récupéré. La requête réussit.
T+37s : La deuxième requête de test réussit.
T+38s : Seuil de succès atteint (2/2 requêtes de test réussies). Le circuit se ferme.
# Logs du gateway
[INFO] Circuit breaker CLOSED for route=/api/v1/payments/charge backend=payment-service
[INFO] Reason: 2 consecutive successes in half-open state
T+39s : Les opérations normales reprennent. Toutes les requêtes de paiement passent.
Ce qui s'est Passé en Coulisses
-
Protection des Ressources : Pendant les 30 secondes d'état ouvert, le gateway n'a pas gaspillé de threads ou de connexions en essayant d'atteindre le service de paiement défaillant. Les services d'inventaire et de notification ont continué à fonctionner normalement.
-
Échec Rapide : Les clients ont reçu des erreurs immédiates qu'ils pouvaient gérer (ex : afficher un message "paiement temporairement indisponible") au lieu de rester suspendus 30+ secondes à attendre des timeouts.
-
Récupération Automatique : Le mécanisme de test semi-ouvert a détecté la récupération du service de paiement et a automatiquement rétabli les opérations normales sans intervention humaine.
-
Observabilité : L'équipe opérationnelle a reçu une alerte "Circuit Ouvert" à T+5s, a investigué la base de données du service de paiement et a résolu le problème de pool de connexions.
Pour des benchmarks de performance de la surcharge des circuit breakers, consultez STOA Gateway Performance Benchmarks.
Circuit Breakers dans les Écosystèmes Modernes de Gateways API
Les circuit breakers ne sont qu'un composant d'une architecture de gateway API résiliente. Ils fonctionnent mieux combinés avec :
- Timeouts : Empêchent les requêtes de rester suspendues indéfiniment
- Tentatives avec backoff exponentiel : Gèrent les pannes transitoires
- Rate limiting : Empêche la surcharge avant qu'elle ne cause des pannes
- Health checks : Détection proactive des problèmes de backend
- Request hedging : Envoi de requêtes dupliquées pour réduire la latence de queue
- Isolation bulkhead : Pools de threads séparés par backend
Pour une vue complète de ces patterns, consultez notre Glossaire Gateway API et Guide Gateway API Open Source.
FAQ
Comment les circuit breakers diffèrent-ils des tentatives de répétition ?
Les circuit breakers empêchent les requêtes d'atteindre les backends défaillants, tandis que les tentatives de répétition essayent les requêtes plusieurs fois. Ils servent des objectifs complémentaires :
- Les tentatives de répétition gèrent les pannes transitoires (coupures réseau temporaires, requête unique échouée). Elles sont pertinentes quand la panne est aléatoire et que la prochaine tentative peut réussir.
- Les circuit breakers gèrent les pannes persistantes (crash de service, base de données down). Quand un backend est vraiment cassé, réessayer gaspille des ressources. Les circuit breakers détectent le pattern et arrêtent d'essayer les requêtes.
En pratique, utilisez les deux : configurez des tentatives de répétition (2-3 essais avec backoff exponentiel) pour les pannes transitoires, et des circuit breakers pour détecter quand les tentatives ne sont plus utiles.
Que se passe-t-il pour les requêtes en cours quand un circuit s'ouvre ?
Les requêtes en cours (celles déjà envoyées au backend avant l'ouverture du circuit) sont autorisées à se terminer. Le circuit breaker n'affecte que les nouvelles requêtes entrantes. Cela évite d'annuler brusquement des requêtes qui pourraient réussir.
Cependant, configurez votre gateway pour respecter les timeouts de requêtes même pour les requêtes en cours. Si une requête dépasse son timeout, le gateway devrait l'annuler et retourner une erreur au client, quel que soit l'état du circuit.
Comment tester les circuit breakers dans des environnements de staging ?
Tester efficacement les circuit breakers nécessite de simuler des scénarios de panne :
-
Chaos engineering : Utilisez des outils comme Chaos Monkey pour tuer aléatoirement des pods backend ou injecter de la latence. Vérifiez que les circuits s'ouvrent comme prévu.
-
Pannes synthétiques : Créez des endpoints de test sur vos backends qui retournent des erreurs à la demande. Exemple :
GET /test/circuit-breaker?error_rate=0.5retourne 50% d'erreurs. -
Tests de charge : Utilisez des outils comme k6 ou Gatling pour envoyer des volumes élevés de requêtes en introduisant des pannes backend. Surveillez les transitions d'état du circuit.
-
Déclenchement manuel : Certains gateways supportent des APIs d'administration pour ouvrir/fermer manuellement les circuits à des fins de test :
POST /admin/circuit-breaker/payments/open.
Testez à la fois le chemin nominal (le circuit reste fermé pendant les opérations normales) et les scénarios de panne (le circuit s'ouvre, passe en semi-ouvert, puis se referme).
Prochaines Étapes
Les circuit breakers sont un pattern de résilience fondamental pour les gateways API de production. Pour continuer à apprendre :
- Plongée architecturale : Lisez notre Guide Gateway API Open Source pour une couverture complète des patterns de gateway
- Détails d'implémentation : Consultez STOA Gateway Performance Benchmarks pour voir les mesures de surcharge des circuit breakers
- Pratique : Déployez un gateway natif Kubernetes avec des circuit breakers en utilisant les patterns de Patterns de Gateway API Natif Kubernetes
- Intégration sécurité : Apprenez comment les circuit breakers s'intègrent aux contrôles de sécurité dans Guide de Renforcement de la Sécurité Gateway API
Les circuit breakers n'empêcheront pas toutes les pannes, mais ils garantiront que votre système échoue gracieusement, récupère automatiquement, et offre une meilleure expérience à vos utilisateurs pendant les incidents.