Circuit Breaker et dégradation
Circuit Breaker (CB) est un modèle de protection qui interrompt les appels à une dépendance dégradée pour localiser la défaillance et protéger les services d'apstream et l'utilisateur. La dégradation (graceful degradation) est une simplification délibérée de la fonctionnalité en cas de manque de ressources ou de défaillances (par exemple, retour des données cachées/incomplètes, désactivation des fiches « chères ») sans un downtime complet.
L'objectif principal est de préserver l'expérience SLO et utilisateur grâce à des pannes contrôlées, au lieu de chutes en cascade.
1) Quand appliquer
La dépendance est instable : croissance p95/p99, délais, réponses erronées.
API externes avec limites strictes/penalti.
Backends « lourds » (recherches, recommandations, rapports) où les retraits amplifient la tempête.
Zones fortement chargées avec risque d'épuisement des bassins (composés, trèdes).
2) États CB et transitions
Les trois classiques :1. Closed - le trafic est en cours, les métriques d'erreur/latence sont comptées.
2. Ouvert - les appels sont instantanément rejetés (fail-fast) et/ou traduits en fallback.
3. Half-Open - Un nombre limité de requêtes « d'essai » détermine si l'interrupteur doit être fermé.
Déclencheurs d'ouverture
Seuil d'erreur/temporisation par fenêtre (par example ≥ 50 % des N derniers).
Seuil de latence (par exemple, p95> valeur cible).
Stratégies combinées (erreurs ∧ dépassement du délai).
Temps de rétention (cool-down)
Fixe (par exemple, 10-60 secondes) ou adaptative (augmentation exponentielle lors des réactifs).
3) Timouts, Retrai et Jitter
Les temporisations sont toujours plus courtes que les SLOs d'aptrime et sont alignées sur la chaîne (déadline propagation).
Retraits uniquement pour les opérations idempotentes ; 1-2 tentatives sont suffisantes dans la plupart des cas.
Backoff + jitter (full jitter) empêche les ondes synchrones de répétition.
Hedging (demandes de rechange) - économique et seulement pour les lectures très critiques.
4) Isolation Bulkhead et « fusibles »
Séparez les pools de connexion/workers/files d'attente par domaine et type de trafic (VIP, tâches d'arrière-plan, API publiques).
Caps sur la concurrence pour les opérations « coûteuses ».
Contrôle d'admission : une défaillance facile avant l'exécution lorsque la file d'attente est dépassée.
5) Fallback et scénarios de dégradation
Options
Cache/Stale Reponses : 'stale-while-revalidate', retour des données du cache L2/L3.
Read-only : bloc d'écriture/commandes, permettre des lectures sécurisées.
Réponses de substitution : données incomplètes (p. ex. sans avis/avatars).
Désactivation fonctionnelle : masquer temporairement les widgets/fiches non critiques.
Feature flags : changement rapide de comportement sans sortie.
Règles
Fallback doit être déterministe, rapide et sûr sur les données.
Marquez clairement le chemin dégradé dans les logs/trails/métriques.
6) Priorité et trafic-shaping
VIP/plans payants - priorité/quotas plus élevés en cas de déficit.
Les limites de taux et le throttling réduisent la charge de dépendance dégradée.
Shed load : légère diminution de la qualité (par exemple moins de résultats, images coupées) avant stabilisation.
7) Observation et signalisation
Métriques CB
État (fermé/ouvert/half-ouvert) et durée dans l'état.
Taux d'échec pour des raisons : CB-open, timeout, 5xx, retry-exhausted.
p95/p99 latence « avant » et « après » de l'interrupteur.
Colv/proportion de demandes via fallback.
Tracing
Annotations de span : 'circuit = opened', 'fallback = cache', 'admission = denied'.
Corrélation avec les limites (429/RateLimit-), les files d'attente et les balles de connexion.
Logi/audit
Raison d'ouverture/fermeture, seuils, identifiants de dépendance.
8) Contrats et protocoles
HTTP
Fail-fast : '503 Service Unavailable' avec 'Retry-After' (ou '429' aux limites).
Contenu partial/steel : '200 '/' 206' avec des métadonnées de dégradation (par exemple, 'X-Degraded : true').
Stratégies de cache : 'Cache-Control : stale-if-error, stale-while-revalidate'.
gRPC
'UNAVAILABLE ',' DEADLINE _ EXCEEDED ', la sémantique des retraits par polices client/proxy.
Deadline/timeout dans le contexte de la demande ; propagation de la debline le long de la chaîne.
Idempotence
Idempotency-Key pour les opérations POST, déduplication à la frontière.
9) Implémentation type (pseudo-code)
pseudo onRequest(req):
if circuit. isOpen(dep):
return fallbackOrFail(req)
with timeout(T):
try:
resp = call(dep, req)
circuit. recordSuccess(dep, latency=resp. latency)
return resp except TimeoutError or 5xx as e:
circuit. recordFailure(dep)
if circuit. shouldOpen(dep):
circuit. open(dep, coolDown=adaptive())
return fallbackOrFail(req)
Échantillon Half-Open
pseudo onTimer():
if circuit. state(dep) == OPEN and coolDownExpired():
circuit. toHalfOpen(dep)
onRequestHalfOpen(req):
if circuit. allowTrial (dep): # e.g. 1 try: call -> success => close catch: reopen with longer coolDown else:
return fallbackOrFail(req)
10) Ajuster les seuils
Fenêtre d'observation : glissant N secondes/requêtes.
Seuil d'erreur : 20-50 % dans la fenêtre (dépend du profil).
Seuil de latence : p95 ≤ SLO cible (par example 300-500 ms) ; le dépassement est comptabilisé comme « erreur » pour CB.
Cool-down adaptatif : 10s → 30s → 60s lors de déclenchements répétés.
11) Tests et pratiques de chaos
Chaos : injection de latence/erreurs en fonction, panne DNS, drop paquets.
Jours de jeu : lancement de « l'ouverture » de l'interrupteur sur un environnement de type boo, vérification de fallback.
Canary : incluez d'abord les SV/politiques de dégradation pour 1 à 5 % du trafic.
Budget SLO : permettre des expériences jusqu'à épuisement du budget error.
12) Intégration avec multi-ténacité
L'état CB peut être stocké per-dependency per-tenant (pour les locataires bruyants) ou globalement - en fonction du profil de charge.
Segmentez les données fallback et les caches par 'tenant _ id'.
Priorités/quotas - selon les plans (les VIP ne doivent pas souffrir du comportement de Starter).
13) Chèque-liste avant la vente
- Les délais et les délais sont de bout en bout et cohérents.
- Les retraits sont limités, uniquement pour les opérations idempotentes, avec backoff + gitter.
- Les seuils CB sont justifiés par les données du test de charge.
- Les chemins de chute existent, rapides et sûrs ; le cache de stratégie est défini.
- Bulkhead-isolation : pools/files d'attente/limites séparés.
- Les métriques/tracés/logs marquent les dégradations et les états de CB.
- Documentation des contrats de réponse (HTTP/gRPC) avec exemples de titres/codes.
- Les scénarios de chaos et les journées de jeu se déroulent régulièrement ; il y a un runbook.
14) Erreurs typiques
Il n'y a pas de temporuts → de retraits « à bout portant » et de chutes en cascade.
Une CB mondiale unique au lieu d'une CB sélective (par endpoint/méthode) est un refus superflu.
L'interrupteur ouvert sans fallback → les écrans « vides » au lieu de l'UX dégradé.
Les retraits sans jitter → des tempêtes de requêtes synchrones.
Long cool-down en cas de défaillance à court terme ou trop court en cas d'état stable - « flip-flop ».
L'absence de bulkhead est l'épuisement des pools communs et le « head-of-line blocking ».
15) Sélection rapide de la stratégie
Lectures de haute importance : CB + cache des réponses de steel + hedging (économique).
Entrées/paiements : délais stricts, minimum de retraits, clés d'identité, pas de « sale » fallback.
API externes : CB avec seuils agressifs, cool-down adaptatif, throttling strict.
Microservices avec charge pulsative : bulkheads, caps sur la concurrence, priorité VIP.
Conclusion
Le Circuit Breaker et la dégradation gérée sont les « assurances » de l'architecture : elles traduisent des refus chaotiques en comportements prévisibles. Des délais clairs, des retraits restreints avec jitter, des pools isolés, des voies de chute réfléchies et la télémétrie rendent le système résistant aux défaillances de dépendance et maintiennent le SLO même pendant les périodes de pointe et d'urgence.