Dégradation gracieuse
1) L'essence de l'approche
La dégradation gracieuse est une transition gérée du système vers un mode plus simple mais utile en cas de pénurie de ressources, de défaillance des dépendances ou de pics de charge. L'objectif est de préserver le noyau de la valeur pour l'utilisateur et la durabilité de la plate-forme en sacrifiant les capacités et la qualité secondaires.
Propriétés clés :- Prévisibilité : scénarios prédéfinis et « escaliers » de dégradation.
- Limitation du rayon de lésion : isolation des fiches et des dépendances.
- Observabilité : métriques, logs et tracés « quel niveau de dégradation est actif et pourquoi ».
- Réversibilité : retour rapide à la normale.
2) Principes et limites
1. Enregistrer l'essentiel : son SLA/SLO principal (par exemple, « achat », « login », « recherche ») est une priorité au-dessus des secondaires (avatars, recommandations, animations).
2. Fail-open vs fail-closed:- Sécurité, paiements, droits - fail-closed (mieux vaut refuser qu'enfreindre).
- Contenu, indices, avatars - fail-open avec folback.
- 3. Budgets temporaires : Temporisation descendante (client
- 4. Contrôle des coûts : la dégradation devrait réduire la consommation de CPU/IO/réseau, pas simplement « cacher » les erreurs.
3) Niveaux de dégradation
3. 1 Client/UX
Skeletons/playscholders et le sous-chargement « paresseux » des widgets secondaires.
UI partial : les blocs critiques sont chargés, les blocs secondaires sont cachés/simplifiés.
Cache côté client : last-known-good (LKG) marqué « les données pourraient être obsolètes ».
Mode hors ligne : file de commandes répétées plus tard (idempotence !).
3. 2 passerelle Edge/CDN/WAF/API
stale-while-revalidate : nous donnons le cache, le fond est mis à jour.
Rate limiting & load shedding : en cas de surcharge, nous réinitialisons le trafic de fond/anonyme.
Géofence/itinéraire pondéré : le trafic est détourné vers la région saine la plus proche.
3. 3 Couche de service
Réponse partielle : nous retournons une partie des données + 'warnings'.
Mode de lecture : interdiction temporaire des mutations (drapeaux).
Brownout : Désactivation temporaire des fiches à forte intensité de ressources (recommandations, enrichissement).
Concurrence adaptative : nous réduisons dynamiquement le parallélisme.
3. 4 Données/streaming
Cache comme source de vérité avec TTL (temporairement) : « Mieux qu'à peu près ».
Précision réduite des modèles/algorithmes (fast path vs accurate path).
Defer/queue : transfère des tâches lourdes à l'arrière-plan (outbox/job queue).
Files d'attente prioritaires : événements critiques - dans une classe distincte.
4) « Escaliers » de dégradation (playbooks)
Exemple pour l'API de recherche :- L0 (La norme) → L1 : cacher la personnalisation et les bannières → L2 : déconnecter les synonymes/fazzi-recherches → L3 : limiter le montant de la réponse et таймаут jusqu'à 300 мс → L4 : rendre les résultats de кеша 5 mines → L5 : "read-only et cached only" + le tour des demandes sur la recalculation.
- Déclencheurs : surcharge CPU> 85 % p95> cible, erreurs> seuil, lag Kafka> seuil, flap de dépendances.
- Actions : activer l'indicateur X, réduire la concurrence à N, changer la source Y en cache.
- Critères de sortie : 10 minutes de mesures vertes, stock de ressources.
5) Politiques décisionnelles
5. 1 Budget erroné et SLO
Utilisez error-budget burn rate comme déclencheur brownout/shedding.
Politique : « Si burn-rate> 4 × pendant 15 min - activer la dégradation L2 ».
5. 2 Admission control
Nous limitons le RPS entrant sur les chemins critiques pour garantir la p99 et empêcher l'effondrement des files d'attente.
5. 3 Priorité
Classes : interactive> system> background.
Priorités per tenant (Gold/Silver/Bronze) et équité (fair share).
6) Modèles et implémentations
6. 1 Load shedding (serveur)
Réinitialisez les requêtes avant qu'elles n'occupent toutes les ressources.
Retournez '429 '/' 503' avec 'Retry-After' et une explication de politique (pour les clients).
Envoy (adaptive concurrency + circuit breaking)
yaml typed_extension_protocol_options:
envoy. filters. http. adaptive_concurrency:
"@type": type. googleapis. com/envoy. extensions. filters. http. adaptive_concurrency. v3. AdaptiveConcurrency gradient_controller_config:
sample_aggregate_percentile: 90 circuit_breakers:
thresholds:
- max_requests: 2000 max_pending_requests: 500 max_connections: 1000
6. 2 Brownout (simplification temporaire)
L'idée est de réduire la « luminosité » (coût) quand les ressources sont à la sortie.
kotlin class Brownout(val level: Int) { // 0..3 fun recommendationsEnabled() = level < 2 fun imagesQuality() = if (level >= 2) "low" else "high"
fun timeoutMs() = if (level >= 1) 150 else 300
}
6. 3 Responsabilité et avertissements partiels
Champ 'warnings '/' degradation' dans la réponse :json
{
"items": [...],
"degradation": {
"level": 2,
"applied": ["cache_only", "no_personalization"],
"expiresAt": "2025-10-31T14:20:00Z"
}
}
6. 4 Stale-while-revalidate sur le bord (Nginx)
nginx proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout http_500 http_502 http_504 updating;
proxy_cache_background_update on;
6. 5 Read-only commutateur (Kubernetes + drapeau)
yaml apiVersion: v1 kind: ConfigMap data:
MODE: "read_only"
The code should check MODE and block mutations with a friendly message.
6. 6 Kafka : backpressure et files d'attente
Passez les heavy consumers à un plus petit 'max. poll. records ', limitez les batch-e. de production
Diviser les événements « critiques » et « bulk » en points de repère/quotas.
6. 7 UI: graceful fallback
Cachez les widgets « lourds », montrez le cache/squelette et marquez clairement les données obsolètes.
7) Exemples de configuration
7. 1 Istio : outlier + pools de priorité
yaml outlierDetection:
consecutive5xx: 5 interval: 10s baseEjectionTime: 30s maxEjectionPercent: 50
7. 2 Nginx : trafic de fond sous le couteau d'abord
nginx map $http_x_priority $bucket { default low; high high; }
limit_req_zone $binary_remote_addr zone=perip:10m rate=20r/s;
limit_req_status 429;
server {
location /api/critical/ { limit_req zone=perip burst=40 nodelay; }
location /api/background/ {
limit_req zone = perip burst = 5 nodelay; # stricter
}
}
7. 3 Feature flags / kill-switches
Stockez dans une configuration dynamique (BouMap/Consul), mise à jour sans version.
Séparez les drapeaux per-fich et globaux, logiez les activations.
8) Observabilité
8. 1 Métriques
« degradation _ level {service} » est le niveau actuel.
'shed _ requests _ total {route, reason}' - combien est réinitialisé et pourquoi.
'stale _ responses _ total' : Combien de cache a été émis.
`read_only_mode_seconds_total`.
`brownout_activations_total{feature}`.
Budget erroné : burn-rate, proportion de violations de SLO.
8. 2 Tracing
Attributs span : 'degraded = true', 'level = 2', 'reason = upstream _ timeout'.
Links entre les retraits/demandes hedged pour voir la contribution à la queue.
8. 3 Logs/alertes
Événements de changement de niveau de dégradation avec les causes et le propriétaire de la modification.
Alert sur le niveau « bouillant » (la dégradation dure trop longtemps).
9) Gestion des risques et sécurité
Ne dégénérez pas l'aoutentifikatsiju/avtorizatsiju/intégrité des données : mieux refus.
Le masquage PII est conservé dans tous les modes.
Finances/paiements : uniquement les opérations d'idempotent, les délais stricts et les remboursements ; en cas de doute - read-only/hold.
10) Anti-modèles
Dégradation silencieuse sans conseil à l'utilisateur et sans télémétrie.
Des tempêtes rétrospectives au lieu de load shedding et de brefs timouts.
Les « coupeurs » mondiaux sans segmentation sont un énorme radius blast.
Mélange des chemins prod et « léger » dans un seul cache/file d'attente.
Dégradation perpétuelle : brownout comme « nouvelle norme », critères de sortie oubliés.
Stale-write : tentatives d'écriture basées sur des données obsolètes.
11) Chèque de mise en œuvre
- Le noyau de la valeur et les scénarios critiques de l'utilisateur sont définis.
- Les escaliers de dégradation par les services/maisons avec les déclencheurs et les sorties sont composés.
- Les délais/restrictions et le serveur-side load shedding sont entrés.
- Les limites de taux et les classes de trafic prioritaires sont configurées.
- Mise en œuvre de la réponse partielle, read-only, stale-while-revalidate.
- Fonctionnalité flags/kill-switches intégrée avec audit.
- Métriques/tracés/alertes pour les niveaux de dégradation et les causes.
- Exercice de jeu régulier avec simulation de surcharge/défaillance.
- Documenté par SLO et la politique error-budget → la dégradation.
12) FAQ
Q : Quand choisir brownout et quand - shedding ?
R : Si l'objectif est de réduire le coût des demandes sans refus - brownout. Si le but est de protéger le système, quand même la simplification n'aide pas - shedding login.
Q : Signaler la dégradation à l'utilisateur ?
R : Pour les scénarios critiques, oui (badge « mode limité »). La transparence réduit le soutien et le mécontentement.
Q : Le cache peut-il être une source de vérité ?
R : Temporairement - oui, avec des SLA explicites et des étiquettes d'obsolescence. C'est interdit pour les mutations.
Q : Comment ne pas « casser » faire des retraits ?
A : Temps courts, backoff exponentiel avec jitter, idempotence et limite de tentative ; seules les opérations de sécurité sont rétractées.
13) Résultats
La dégradation gracieuse est un contrat architectural et un ensemble de modes de fonctionnement gérés qui sont activés par des signaux de métriques et de budget erroné. Escaliers bien conçus, Timeouts et Shedding rigoureux, Kesh Folbacks et brownout, plus une forte observabilité - et votre plate-forme reste utile et économique même en période de tempête.