Introduction
En développement logiciel, une logique de réessai fiable est essentielle pour gérer les échecs intermittents, tels que les problèmes de réseau ou les interruptions temporaires. Récemment, j’ai rencontré une base de code où un développeur utilisait une boucle for
avec un intervalle de temps fixe pour réessayer les opérations en échec. Bien que cette approche puisse sembler simple, elle manque de la résilience nécessaire pour les applications du monde réel. C’est là qu’intervient l’Exponential Backoff – une stratégie conçue pour rendre les réessais plus intelligents et efficaces.
Dans cet article, nous examinerons comment fonctionne l’Exponential Backoff, ses avantages par rapport à une simple boucle de réessai, et comment vous pouvez l’implémenter pour améliorer la fiabilité de votre système. Je vous guiderai également à travers un exemple pratique utilisant un module d’envoi d’e-mails, vous montrant comment utiliser l’Exponential Backoff pour garantir une gestion d’erreurs plus résiliente.
Qu’est-ce que l’Exponential Backoff?
L’Exponential Backoff est une stratégie de réessai où le temps d’attente entre les tentatives de réessai augmente de manière exponentielle après chaque échec. Au lieu de réessayer à intervalles fixes, chaque tentative ultérieure attend plus longtemps que la précédente – en doublant généralement le délai à chaque fois. Par exemple, si le délai initial est de 1 seconde, les réessais suivants se produiront à 2, 4, 8 secondes, et ainsi de suite. Cette approche aide à réduire la charge du système et à minimiser le risque de surcharger les services externes pendant les périodes de forte demande.
En permettant plus de temps entre les réessais, l’Exponential Backoff donne aux problèmes temporaires une chance de se résoudre, ce qui conduit à une gestion d’erreurs plus efficace et à une meilleure stabilité de l’application.
Avantages et inconvénients de l’Exponential Backoff
Avantages:
-
Charge Système Réduite: En espaçant les réessais, l’Exponential Backoff minimise les chances de surcharger les serveurs, ce qui est particulièrement utile pour gérer les limites de débit ou les pannes transitoires.
-
Gestion Efficace des Erreurs: Le délai croissant permet aux problèmes transitoires d’avoir plus de temps pour se résoudre naturellement, améliorant ainsi la probabilité d’un réessai réussi.
-
Stabilité Améliorée: Surtout pour les systèmes à fort trafic, cela prévient une inondation de tentatives de réessai, maintenant les applications en fonctionnement fluide sans consommation excessive de ressources.
Inconvénients:
- Latence Accrue: Avec chaque réessai prenant de plus en plus de temps, l’Exponential Backoff peut entraîner des délais, surtout si de nombreux réessais sont nécessaires avant le succès.
Cas d’Utilisation Clés pour l’Exponential Backoff
L’Exponential Backoff est particulièrement utile dans des scénarios où les systèmes interagissent avec des services externes ou gèrent de grands volumes de trafic. Voici quelques autres cas d’utilisation courants :
-
APIs à limitation de débit : Certaines APIs ont des limites de débit, restreignant les requêtes dans un certain laps de temps. Le retour exponnentiel permet d’éviter des reprises immédiates qui pourraient dépasser la limite, en laissant le temps à celle-ci de se réinitialiser.
-
Instabilité du réseau : En cas de pannes temporaires du réseau ou de délais dépassés, le retour exponnentiel aide en attendant plus longtemps entre les tentatives, permettant au réseau de se stabiliser.
-
Connexions à la base de données : Lors de la connexion à des bases de données soumises à une charge importante, le retour exponnentiel aide à prévenir une surcharge supplémentaire en retardant les reprises, laissant le temps à la base de données de récupérer.
-
Systèmes de files d’attente : Dans les systèmes de files d’attente de messages, si un message échoue en raison d’une erreur, l’utilisation du retour exponnentiel pour les reprises peut éviter un retraitement rapide et laisser le temps de résoudre les problèmes temporaires.
Créer un Service d’Envoi d’Emails de Base avec Exponential Backoff
Pour démontrer l’Exponential Backoff, nous allons construire un service d’envoi d’emails de base qui tente de renvoyer les emails en cas d’erreur. Cet exemple montre comment l’Exponential Backoff améliore le processus de nouvelle tentative par rapport à une simple boucle for.
import nodemailer from "nodemailer";
import { config } from "../common/config";
import SMTPTransport from "nodemailer/lib/smtp-transport";
const emailSender = async (
subject: string,
recipient: string,
body: string
): Promise<boolean> => {
const transport = nodemailer.createTransport({
host: config.EMAIL_HOST,
port: config.EMAIL_PORT,
secure: true,
auth: { user: config.EMAIL_SENDER, pass: config.EMAIL_PASSWORD },
} as SMTPTransport.Options);
const mailOptions: any = {
from: config.EMAIL_SENDER,
to: recipient,
subject: subject,
};
const maxRetries = 5; // maximum number of retries before giving up
let retryCount = 0;
let delay = 1000; // initial delay of 1 second
while (retryCount < maxRetries) {
try {
// send email
await transport.sendMail(mailOptions);
return true;
} catch (error) {
// Exponential backoff strategy
retryCount++;
if (retryCount < maxRetries) {
const jitter = Math.random() * 1000; // random jitter(in seconds) to prevent thundering herd problem
const delayMultiplier = 2
const backOffDelay = delay * delayMultiplier ** retryCount + jitter;
await new Promise((resolve) => setTimeout(resolve, backOffDelay));
} else {
// Log error
console.log(error)
return false; // maximum number of retries reached
}
}
}
return false;
};
Ajustement des Paramètres de l’Exponential Backoff
La mise en œuvre de l’Exponential Backoff implique l’ajustement de certains paramètres pour s’assurer que la stratégie de nouvelle tentative fonctionne bien pour les besoins de votre application. Les paramètres clés suivants affectent le comportement et les performances de l’Exponential Backoff dans un mécanisme de nouvelle tentative :
- Délai Initial
-
Objectif : Définit le temps d’attente avant la première nouvelle tentative. Il doit être suffisamment long pour éviter les nouvelles tentatives immédiates mais assez court pour éviter des délais notables.
-
Paramètre Recommandé : Commencez avec un délai compris entre 500 ms et 1000 ms. Pour les systèmes critiques, utilisez un délai plus court, tandis que les opérations moins urgentes peuvent avoir un délai plus long.
- Multiplicateur de délai
-
Objectif : Contrôle la rapidité avec laquelle le délai augmente après chaque nouvelle tentative. Un multiplicateur de 2 double le délai (par exemple, 1s, 2s, 4s).
-
Paramètre recommandé : En général, un multiplicateur compris entre 1.5 et 2 équilibre réactivité et stabilité. Des multiplicateurs plus élevés (par exemple, 3) peuvent être appropriés si le système peut gérer des délais plus longs entre les nouvelles tentatives.
- Nombre maximum de tentatives
-
Objectif : Limite les tentatives de réessai pour éviter des réessais excessifs qui pourraient épuiser les ressources ou augmenter la charge du système.
-
Paramètre recommandé : Une plage de 3 à 5 tentatives est généralement suffisante pour la plupart des applications. Au-delà de cela, l’opération pourrait devoir être enregistrée comme échouée ou gérée différemment, comme notifier l’utilisateur ou déclencher une alerte.
- Jitter (Randomisation)
-
Objectif: Ajoute un élément aléatoire à chaque délai pour éviter que les tentatives de réessai ne se regroupent et ne provoquent un effet d’emballement.
-
Paramètre recommandé: Ajouter un délai aléatoire entre 0 et 500 ms à chaque intervalle de réessai. Ce jitter permet de répartir de manière plus uniforme les tentatives de réessai dans le temps.
Conclusion
En utilisant le Backoff Exponentiel, vous ajoutez de la résilience à votre application, la préparant à gérer des problèmes inattendus. C’est un petit changement avec un grand impact, surtout lorsque votre application se développe.
Et c’est tout pour le moment. N’hésitez pas à laisser un commentaire et à poser des questions si vous en avez. Cheers pour la création d’applications plus fiables et résilientes.
Bon codage! 👨💻❤️
Source:
https://timothy.hashnode.dev/implementing-exponential-backoff-for-reliable-systems