almessadi.
Retour à l'index

Les Reprises Nécessitent Un Backoff, Du Jitter, et Un Budget Clair_

Les reprises améliorent la résilience uniquement lorsqu'elles répartissent la charge et s'arrêtent au bon moment. Sans backoff et jitter, elles peuvent transformer un échec éphémère en une panne plus large.

Publié28 septembre 2024
Temps de lecture9 min read

Les reprises sont l'une des fonctionnalités de résilience les plus faciles à rater, car elles semblent inoffensives à petite échelle.

Un seul service répétant une requête échouée n'est pas un problème. Dix mille instances répétant selon le même calendrier le sont souvent.

C'est là que la logique de reprise se transforme d'un mécanisme de récupération en amplificateur de charge.

Le Modèle Naïf

C'est commun et dangereux :

for (let attempt = 0; attempt < 3; attempt += 1) {
  try {
    return await callPaymentApi();
  } catch (error) {
    await sleep(1000);
  }
}

Tous les appelants échouent ensemble. Tous les appelants dorment le même temps. Tous les appelants se réveillent ensemble et frappent à nouveau la dépendance.

Ce Que Comprend Une Meilleure Logique de Reprise

Un bon comportement de reprise combine généralement :

  • backoff exponentiel
  • jitter
  • un budget maximal de reprises

Par exemple :

function backoffMs(attempt: number) {
  const base = 250 * 2 ** attempt;
  const jitter = Math.random() * 0.3 * base;
  return Math.min(base + jitter, 5000);
}

L'objectif n'est pas l'élégance mathématique. L'objectif est d'empêcher des milliers de clients de reprendre en synchronisation.

Le Compromis

Les reprises n'ont de sens que pour les erreurs susceptibles d'être transitoires. Elles sont généralement incorrectes pour :

  • erreurs de validation
  • erreurs d'autorisation permanentes
  • requêtes qui ne peuvent pas être répétées sans idempotence

C'est pourquoi la politique de reprise et la politique d'idempotence vont de pair.

Lectures Complémentaires