Recommandations relatives à la gestion des erreurs temporaires
S’applique à cette recommandation de liste de contrôle de fiabilité d’Azure Well-Architected Framework :
RE :07 | Renforcez la résilience et la récupération de votre charge de travail en implémentant des mesures d’auto-préservation et d’auto-réparation. Générez des fonctionnalités dans la solution à l’aide de modèles de fiabilité basés sur l’infrastructure et de modèles de conception basés sur le logiciel pour gérer les défaillances des composants et les erreurs temporaires. Générez des fonctionnalités dans le système pour détecter les défaillances des composants de solution et lancer automatiquement une action corrective pendant que la charge de travail continue à fonctionner à pleine ou réduite. |
---|
Guides connexes : Travaux | en arrière-plan auto-préservation
Ce guide décrit les recommandations relatives à la gestion des erreurs temporaires dans vos applications cloud. Toutes les applications qui communiquent avec des services à distance ou des ressources distantes doivent être sensibles aux erreurs temporaires. Cela est particulièrement vrai pour les applications exécutées dans le cloud, où la nature de l’environnement et la connectivité sur Internet augmentent le risque de rencontrer ce type d’erreurs. Les défaillances temporaires peuvent être une perte momentanée de la connectivité réseau des composants et des services, l’indisponibilité passagère d’un service ou l’expiration des délais d’attente quand un service est occupé. Comme ces erreurs se corrigent souvent d’elles-mêmes, si l’action est répétée après un délai approprié, elle a de fortes chances d’aboutir.
Cet article fournit des conseils généraux pour traiter les erreurs temporaires. Pour plus d’informations sur la gestion des erreurs temporaires, consultez le modèle de nouvelle tentative et, lorsque vous utilisez des services Azure, consultez les instructions de nouvelle tentative pour les services Azure.
Stratégies de conception
Les erreurs temporaires peuvent se produire dans n’importe quel environnement, sur n’importe quel système d’exploitation ou plateforme et dans n’importe quel type d’application. Pour les solutions exécutées sur une infrastructure locale, les performances et la disponibilité de l’application et de ses composants sont généralement garanties au moyen d’une redondance matérielle coûteuse et souvent sous-exploitée, et les ressources et les composants sont situés à proximité les uns des autres. Cette approche rend l’échec moins probable, mais les erreurs temporaires peuvent toujours se produire, car les pannes provoquées par des événements imprévus tels que l’alimentation externe ou les problèmes réseau, ou par les scénarios d’urgence.
L’hébergement cloud, y compris les systèmes de cloud privé, peut offrir une disponibilité globale supérieure en s’appuyant sur des ressources partagées, la redondance, le basculement automatique et l’allocation dynamique des ressources entre de nombreux nœuds de calcul de base. Toutefois, en raison de la nature des environnements cloud, les erreurs temporaires sont plus susceptibles de se produire. Il existe plusieurs raisons à cela :
Dans un environnement cloud, de nombreuses ressources sont partagées et leur accès peut être limité afin de les protéger. Certains services refusent les connexions quand la charge s’élève à un niveau spécifique ou qu’un débit maximal est atteint, afin d’autoriser le traitement des demandes existantes et de maintenir les performances du service pour tous les utilisateurs. Cette limitation permet de maintenir la qualité de service pour les voisins et les autres locataires qui utilisent la ressource partagée.
Les environnements cloud utilisent un grand nombre d’unités matérielles de base. Ils assurent de bonnes performances en distribuant dynamiquement la charge sur plusieurs unités de calcul et composants d’infrastructure. Ils assurent également une certaine fiabilité en recyclant ou en remplaçant automatiquement les unités défaillantes. En raison de cette nature dynamique, des échecs de connexion et erreurs temporaires peuvent parfois se produire.
Il y a souvent plus de composants matériels, notamment des composants d’infrastructure réseau comme des routeurs et des équilibreurs de charge, entre l’application et les ressources et services qu’elle utilise. Cette infrastructure en plus peut parfois introduire une latence et des erreurs de connexion temporaires supplémentaires.
Les conditions réseau entre le client et le serveur peuvent être variables, tout particulièrement quand les communications utilisent Internet. Même dans des emplacements locaux, les charges de trafic élevées peuvent ralentir les communications et entraîner des échecs de connexion intermittents.
Les erreurs temporaires peuvent avoir un effet significatif sur la disponibilité perçue d’une application, même si elle a été soigneusement testée dans toutes les circonstances prévisibles. Pour assurer un fonctionnement fiable des applications hébergées dans le cloud, vous devez vérifier qu’elles sont capables de répondre aux défis suivants :
L’application doit pouvoir détecter les erreurs quand elles se produisent et déterminer si ces erreurs sont temporaires, de longue durée ou irréversibles. Différentes ressources retournent généralement différentes réponses en cas d’erreur, et ces réponses peuvent également varier selon le contexte de l’opération. Par exemple, la réponse à une erreur quand l’application lit dans le stockage peut différer de la réponse à une erreur quand elle écrit dans le stockage. De nombreux services et ressources ont des contrats bien documentés concernant les erreurs temporaires. Toutefois, quand ce n’est pas le cas, il peut être difficile de découvrir la nature de l’erreur et si elle est temporaire.
L’application doit pouvoir réessayer l’opération si elle détermine que l’erreur est temporaire. Elle doit aussi faire un suivi du nombre des nouvelles tentatives de l’opération.
L’application doit utiliser une stratégie appropriée pour les nouvelles tentatives. Cette stratégie spécifie le nombre de nouvelles tentatives nécessaires, le délai entre chaque tentative et les mesures à prendre après une tentative infructueuse. Le nombre approprié de tentatives et le délai entre chacune d’elles sont souvent difficiles à déterminer. La stratégie varie en fonction du type de ressource et des conditions d’exploitation actuelles de la ressource et de l’application.
Le guide suivant vous aide à concevoir un mécanisme de gestion des erreurs temporaires adapté à vos applications.
Déterminer s’il y a un mécanisme de nouvelle tentative intégré
De nombreux services fournissent un kit de développement logiciel (SDK) ou une bibliothèque cliente contenant un mécanisme de gestion des erreurs temporaires intégré. La politique de nouvelle tentative utilisée est généralement adaptée à la nature et aux exigences du service cible. Les interfaces REST pour les services peuvent également renvoyer des informations utiles pour déterminer si une nouvelle tentative est appropriée et évaluer la durée d’attente avant la tentative suivante.
Vous devez utiliser le mécanisme de nouvelle tentative intégré s’il existe, sauf si vous avez des besoins spécifiques et bien définis nécessitant un comportement de nouvelle tentative différent plus approprié.
Déterminer si l’opération est adaptée aux nouvelles tentatives
Réessayez les opérations uniquement quand les erreurs sont temporaires (généralement indiqué par la nature de l’erreur) et si l’opération a des chances d’aboutir en cas de nouvelle tentative. Il est inutile de faire une nouvelle tentative pour une opération non valide, comme une mise à jour de base de données sur un élément inexistant, ou une demande envoyée à un service ou une ressource qui a subi une erreur irrécupérable.
En général, implémentez les nouvelles tentatives uniquement quand vous pouvez en déterminer l’effet complet, et quand les conditions sont bien comprises et peuvent être validées. Sinon, laissez le code appelant implémenter les nouvelles tentatives. N’oubliez pas que les erreurs renvoyées par des ressources et des services que vous ne contrôlez pas peuvent évoluer au fil du temps, et que vous devez peut-être revoir votre logique de détection des erreurs temporaires.
Quand vous créez des services ou des composants, implémentez des codes d’erreur et des messages qui aident les clients à déterminer s’ils doivent réessayer les opérations ayant échoué. Plus particulièrement, indiquez si le client doit réessayer l’opération (par exemple, en renvoyant une valeur isTransient) et suggérez un délai approprié avant la tentative suivante. Si vous créez un service web, renvoyez des erreurs personnalisées définies dans vos contrats de service. Même si les clients génériques peuvent ne pas pouvoir lire ces erreurs, elles sont utiles pour la création de clients personnalisés.
Déterminer un nombre de nouvelles tentatives et un intervalle appropriés
Optimisez le nombre de nouvelles tentatives et l’intervalle par rapport au type de cas d’usage. Si vous n’effectuez pas suffisamment de tentatives, l’application ne peut pas terminer l’opération et échoue probablement. Si vous effectuez trop de nouvelles tentatives ou que l’intervalle entre elles est trop court, l’application peut bloquer des ressources comme les threads, les connexions et la mémoire pendant de longues périodes, ce qui affecte l’intégrité de l’application.
Adaptez les valeurs de l’intervalle de temps et du nombre de nouvelles tentatives en fonction du type de l’opération. Par exemple, si l’opération fait partie d’une interaction utilisateur, l’intervalle doit être court et le nombre de nouvelles tentatives faible. En utilisant cette approche, vous évitez que les utilisateurs attendent une réponse, ce qui implique des connexions ouvertes et peut réduire la disponibilité pour les autres utilisateurs. Si l’opération fait partie d’un workflow long ou critique, où l’annulation et le redémarrage du processus implique des frais et du temps, il vaut mieux attendre plus longtemps entre les tentatives et les renouveler plus souvent.
N’oubliez pas que l’étape la plus difficile dans la conception de la stratégie est de déterminer l’intervalle approprié entre les nouvelles tentatives. Les stratégies classiques utilisent les types suivants d’intervalles avant nouvelle tentative :
Temporisation exponentielle. L’application attend peu de temps avant la première nouvelle tentative, puis augmente l’intervalle de façon exponentielle entre les tentatives suivantes. Par exemple, elle peut réessayer l’opération au bout de 3 secondes, 12 secondes, 30 secondes, etc.
Intervalles incrémentiels. L’application attend peu de temps avant la première nouvelle tentative, puis augmente l’intervalle de façon incrémentielle entre les tentatives suivantes. Par exemple, elle peut réessayer l’opération au bout de 3 secondes, 7 secondes, 13 secondes, etc.
Intervalles réguliers. L’application attend le même laps de temps entre chaque tentative. Par exemple, elle peut réessayer l’opération toutes les 3 secondes.
Nouvelle tentative immédiate. Une erreur temporaire peut parfois être courte, par exemple, quand elle est liée à un événement comme une collision de paquets réseau ou un pic dans un composant matériel. Dans ce cas, il faut réessayer l’opération immédiatement, car elle peut aboutir si l’erreur disparaît pendant que l’application assemble et envoie la demande suivante. Toutefois, il ne doit jamais y avoir plusieurs nouvelles tentatives immédiates. Vous devez utiliser des stratégies alternatives, comme des actions de secours ou de temporisation exponentielle, si la nouvelle tentative échoue.
Répartition aléatoire. Toutes les stratégies de nouvelle tentative listées précédemment peuvent inclure une randomisation pour éviter que plusieurs instances du client tentent des tentatives successives en même temps. Par exemple, une instance peut réessayer l’opération au bout de 3 secondes, 11 secondes, 28 secondes, etc., tandis qu’une autre instance peut réessayer l’opération au bout de 4 secondes, 12 secondes, 26 secondes, etc. La randomisation est une technique utile qui peut être associée à d’autres stratégies.
En règle générale, utilisez une stratégie de temporisation exponentielle pour les opérations d’arrière-plan et des stratégies de nouvelle tentative immédiate ou à intervalles réguliers pour les opérations interactives. Dans les deux cas, vous devez choisir le délai et le nombre de nouvelles tentatives de sorte que la latence maximale pour toutes les nouvelles tentatives soit comprise dans la plage de latence de bout en bout requise.
Prenez en compte la combinaison de tous les facteurs qui contribuent au délai d’expiration maximal général pour une opération réessayée. Ces facteurs sont le temps de réponse d’une connexion ayant échoué (généralement défini par une valeur de délai d’expiration dans le client), le délai entre les nouvelles tentatives et le nombre maximal de nouvelles tentatives. La somme de tous ces délais peut entraîner une grande durée d’opération générale, en particulier quand vous utilisez une stratégie de délai exponentiel où l’intervalle entre les nouvelles tentatives augmente rapidement après chaque échec. Si un processus doit satisfaire un contrat de niveau de service (SLA) spécifique, la durée d’opération globale, y compris tous les délais d’expiration et autres, doit être comprise dans les limites définies dans le contrat SLA.
N’implémentez pas de stratégies de nouvelle tentative trop agressives. Ce sont des stratégies qui ont des intervalles trop courts ou des nouvelles tentatives trop fréquentes. Elles peuvent avoir l’effet inverse sur la ressource ou le service cible. Ces stratégies peuvent empêcher la ressource ou le service de sortir de son état de surcharge, l’obligeant ainsi à continuer de bloquer ou refuser les demandes. Ce scénario entraîne un cercle vicieux, où de plus en plus de demandes sont envoyées à la ressource ou au service. Par conséquent, sa capacité de récupération est encore plus réduite.
Prenez en compte le délai d’expiration des opérations quand vous choisissez les intervalles des nouvelles tentatives, pour éviter de lancer une nouvelle tentative immédiatement (par exemple, si le délai d’expiration est similaire à l’intervalle entre les nouvelles tentatives). Demandez-vous également si vous devez maintenir la durée totale possible (délai d’expiration plus intervalles entre les nouvelles tentatives) en dessous d’une durée totale spécifique. Si une opération a un délai d’attente anormalement court ou long, ce délai d’attente peut influencer l’intervalle entre les nouvelles tentatives et leur fréquence.
Utilisez le type de l’exception et les données qu’elle contient, ou les codes d’erreur et les messages renvoyés par le service afin d’optimiser le nombre de nouvelles tentatives et l’intervalle entre elles. Par exemple, certaines exceptions ou certains codes d’erreur (comme le code HTTP 503 Service indisponible avec un en-tête Retry-After dans la réponse) peuvent indiquer la durée potentielle de l’erreur, ou que le service a échoué et ne répondra pas aux nouvelles tentatives.
Envisagez d’utiliser une approche de file d’attente de lettres mortes pour vous assurer que toutes les informations de l’appel entrant ne sont pas perdues une fois que toutes les tentatives de nouvelle tentative ont été épuisées.
Éviter les anti-modèles
Dans la plupart des cas, évitez des implémentations qui comprennent des couches dupliquées de code de nouvelle tentative. Évitez les conceptions comprenant des mécanismes de nouvelle tentative en cascade ou qui implémentent une nouvelle tentative à chaque étape d’une opération impliquant une hiérarchie de demandes, sauf si vous avez des besoins spécifiques qui l’exigent. Dans ces circonstances exceptionnelles, utilisez des politiques qui empêchent un nombre de nouvelles tentatives et des délais excessifs, et assurez-vous que vous comprenez les répercussions. Par exemple, supposons qu’un composant envoie une demande à un autre, lequel accède ensuite au service cible. Si vous implémentez trois nouvelles tentatives sur chaque appel, vous obtenez neuf nouvelles tentatives au total sur le service. De nombreux services et ressources implémentent un mécanisme de nouvelle tentative intégré. Vous devez investiguer comment désactiver ou modifier ces mécanismes si vous devez implémenter des nouvelles tentatives à un niveau supérieur.
N’implémentez jamais de mécanisme de nouvelle tentative infini. En effet, vous risquez d’empêcher la ressource ou le service de sortir des situations de surcharge, et donc de prolonger la limitation et le refus des connexions. Utilisez un nombre fini de nouvelles tentatives ou implémentez un modèle de type Disjoncteur pour permettre au service de récupérer.
N’effectuez jamais plus d’une nouvelle tentative immédiate.
Évitez d’utiliser un intervalle de nouvelle tentative régulier quand vous accédez aux services et aux ressources sur Azure, en particulier si vous avez un grand nombre de nouvelles tentatives. La meilleure approche dans ce scénario est d’utiliser une stratégie de temporisation exponentielle avec une capacité de disjoncteur.
Empêchez plusieurs instances du même client ou plusieurs instances de clients différents d’envoyer simultanément des nouvelles tentatives. Si ce scénario risque de se produire, introduisez la randomisation dans les intervalles de nouvelle tentative.
Tester les stratégies et l’implémentation de nouvelles tentatives
Testez entièrement votre stratégie de nouvelle tentative dans toutes les circonstances possibles, en particulier quand l’application et les ressources ou services cibles qu’elle utilise sont soumis à une charge extrême. Pour vérifier le comportement pendant le test, vous pouvez :
Injecter des erreurs temporaires et non temporaires dans le service. Par exemple, envoyez des demandes non valides ou ajoutez du code qui détecte les requêtes test et répond avec différents types d’erreurs.
Créer une ressource ou un service fictifs renvoyant une plage d’erreurs que le service réel est susceptible de renvoyer. Couvrez tous les types d’erreurs que votre stratégie de nouvelle tentative peut détecter.
Pour les services personnalisés que vous créez et déployez, forcez des erreurs temporaires en désactivant ou en surchargeant temporairement le service. (N’essayez pas de surcharger des ressources partagées ou des services partagés dans Azure.)
Utilisez des bibliothèques ou des solutions qui interceptent et modifient le trafic réseau pour répliquer des scénarios défavorables à partir de vos tests automatisés. Par exemple, les tests peuvent ajouter des heures d’aller-retour supplémentaires, supprimer des paquets, modifier des en-têtes ou même modifier le corps de la requête elle-même. Cela permet de tester de manière déterministe un sous-ensemble des conditions d’échec, qu’il s’agisse d’erreurs temporaires ou d’autres types d’échecs.
Lors du test de la résilience d’une application web cliente aux erreurs temporaires, utilisez les outils de développement du navigateur ou la capacité de votre framework de test à simuler ou bloquer les demandes réseau.
Effectuez des tests simultanés et de charge élevée pour vérifier que le mécanisme et la stratégie de nouvelle tentative fonctionnent correctement dans ces conditions. Ces tests permettent également de s’assurer que la nouvelle tentative n’a pas d’effet négatif sur le fonctionnement du client ou provoque une contamination croisée entre les requêtes.
Gérer les configurations de stratégie de nouvelle tentative
Une stratégie de nouvelle tentative associe tous les éléments de votre logique de nouvelle tentative. Elle définit le mécanisme de détection qui détermine si une erreur est temporaire, le type d’intervalle à utiliser (régulier, temporisation exponentielle et randomisation), les valeurs d’intervalle réelles et le nombre de nouvelles tentatives à effectuer.
Implémentez les nouvelles tentatives à de nombreux endroits, même dans la plus simple des applications, et dans toutes les couches des applications plus complexes. Au lieu de coder en dur les éléments de chaque stratégie à plusieurs emplacements, utilisez un point central pour stocker l’ensemble des stratégies. Par exemple, stockez les valeurs comme l’intervalle et le nombre de nouvelles tentatives dans les fichiers de configuration de l’application, lisez-les au moment de l’exécution et créez programmatiquement les stratégies de nouvelle tentative. Cela facilite la gestion des paramètres, ainsi que la modification et l’ajustement des valeurs afin de répondre à l’évolution des besoins et des scénarios. Toutefois, concevez le système pour qu’il stocke les valeurs plutôt qu’il relise chaque fois un fichier de configuration, et utilisez des valeurs par défaut appropriées si les valeurs ne peuvent pas être obtenues à partir de la configuration.
Stockez les valeurs utilisées pour générer les stratégies de nouvelle tentative au moment de l’exécution dans le système de configuration de l’application afin de pouvoir les modifier sans avoir à redémarrer l’application.
Tirez parti des stratégies de nouvelle tentative intégrées ou par défaut qui sont disponibles dans les API de client que vous utilisez, mais uniquement quand elles sont adaptées à votre scénario. Ces stratégies sont généralement génériques. Dans certains scénarios, elles peuvent répondre entièrement à vos besoins, mais dans d’autres scénarios, elles n’offrent pas toutes les options nécessaires pour répondre à vos besoins spécifiques. Pour déterminer les valeurs les plus appropriées, vous devez faire des tests afin de comprendre comment les paramètres affectent votre application.
Journaliser et suivre les erreurs temporaires et non temporaires
Dans le cadre de votre stratégie de nouvelle tentative, ajoutez la gestion des exceptions et d’autres instrumentations qui journalisent les nouvelles tentatives. Une erreur temporaire occasionnelle et une nouvelle tentative sont des événements attendus qui n’indiquent pas un problème. Toutefois, un nombre régulier et croissant de nouvelles tentatives est souvent indicateur d’un problème susceptible de provoquer un échec, ou de dégrader les performances et la disponibilité de l’application.
Journalisez les erreurs temporaires comme des avertissements et non des erreurs pour que les systèmes de monitoring ne les détectent pas comme des erreurs d’application susceptibles de déclencher de fausses alertes.
Stockez dans vos entrées de journal une valeur qui indique si les nouvelles tentatives ont été provoquées par une limitation dans le service ou par d’autres types d’erreurs, comme des échecs de connexion, afin de pouvoir les différencier pendant l’analyse des données. Une augmentation du nombre d’erreurs de limitation est souvent révélatrice d’un défaut de conception de l’application ou de la nécessité de passer à un service Premium qui offre du matériel dédié.
Mesurez et journalisez le temps total nécessaire aux opérations qui utilisent un mécanisme de nouvelle tentative. Cette métrique est un bon indicateur de l’effet général des erreurs temporaires sur les temps de réponse pour l’utilisateur, la latence des processus et l’efficacité des cas d’usage de l’application. Journalisez également le nombre réel de nouvelles tentatives pour comprendre les facteurs qui contribuent au temps de réponse.
Implémentez un système de télémétrie et de monitoring capable de déclencher des alertes quand le nombre et le taux d’échecs, le nombre moyen de nouvelles tentatives ou le temps total que mettent les opérations pour aboutir augmentent.
Gérer les opérations qui échouent continuellement
Réfléchissez à la façon de gérer les opérations qui continuent d’échouer à chaque tentative. Les situations de ce type sont inévitables.
Bien qu’une stratégie de nouvelle tentative définisse le nombre maximal de fois qu’une opération doit être réessayée, elle n’empêche pas l’application de répéter l’opération avec le même nombre de nouvelles tentatives. Par exemple, si un service de traitement de commandes échoue avec une erreur irrécupérable qui le met définitivement en défaut, la stratégie de nouvelle tentative peut détecter une expiration du délai de connexion et considérer cet événement comme une erreur temporaire. Le code réessaie l’opération un nombre spécifié de fois avant d’abandonner. Toutefois, quand un autre client passe une commande, l’opération est réessayée, même si elle est échoue chaque fois.
Pour empêcher les nouvelles tentatives des opérations qui échouent continuellement, implémentez le modèle Disjoncteur. Quand vous utilisez ce modèle, si le nombre d’échecs dans une période spécifiée dépasse un seuil, les demandes retournent immédiatement à l’appelant comme des erreurs, sans tentative d’accès à la ressource ou au service qui a échoué.
L’application peut tester régulièrement le service, par intermittence et avec de longs intervalles entre les demandes, pour détecter le moment où il redevient disponible. Un intervalle approprié dépend de facteurs comme la criticité de l’opération et la nature du service. Il peut s’étendre de quelques minutes à plusieurs heures. Quand le test réussit, l’application peut reprendre un fonctionnement normal et passer des demandes au service qui vient d’être restauré.
En attendant, vous pouvez avoir recours à une autre instance du service (par exemple, dans un autre centre de données ou une autre application), utiliser un service similaire qui offre des fonctionnalités compatibles (peut-être plus simples) ou effectuer d’autres opérations en espérant que le service sera de nouveau disponible bientôt. Par exemple, vous pouvez peut-être stocker les demandes destinées au service dans une file d’attente ou un magasin de données, et les réessayer plus tard. Sinon, vous pouvez peut-être rediriger l’utilisateur vers une autre instance de l’application, dégrader les performances de l’application tout en continuant à offrir des fonctionnalités acceptables ou renvoyer simplement un message à l’utilisateur indiquant que l’application est actuellement indisponible.
Optimiser l’implémentation de nouvelle tentative
Quand vous choisissez les valeurs du nombre de nouvelles tentatives et des intervalles des nouvelles tentatives d’une stratégie, demandez-vous si l’opération à effectuer sur le service ou la ressource fait partie d’une opération longue ou multi-étape. Quand une étape opérationnelle échoue, il peut être difficile ou coûteux de compenser toutes les autres étapes ayant déjà abouti. Dans ce cas, un intervalle très long et un grand nombre de nouvelles tentatives peuvent être acceptables à condition que la stratégie ne bloque pas les autres opérations en retenant ou en verrouillant des ressources rares.
Demandez-vous si une nouvelle tentative pour la même opération peut donner lieu à des incohérences dans les données. Si certaines parties d’un processus multi-étape sont répétées et que les opérations ne sont pas idempotentes, des incohérences peuvent se produire. Par exemple, si une opération qui incrémente une valeur est répétée, elle produit un résultat non valide. La répétition d’une opération qui envoie un message à une file d’attente peut entraîner une incohérence dans le consommateur de message s’il ne détecte pas les messages en double. Pour éviter ces scénarios, concevez chaque étape comme une opération idempotente. Pour plus d’informations, consultez Modèles d’idempotence.
Réfléchissez à l’étendue des opérations réessayées. Par exemple, ce peut être plus simple d’implémenter du code de nouvelle tentative à un niveau qui englobe plusieurs opérations et de toutes les réessayer si l’une d’elles échoue. Toutefois, cela peut donner lieu à des problèmes d’idempotence ou à des opérations de restauration inutiles.
Si vous choisissez une étendue de nouvelle tentative qui englobe plusieurs opérations, prenez en compte la latence totale de toutes ces opérations pour déterminer les intervalles des nouvelles tentatives et monitorer le temps nécessaire, et avant de déclencher des alertes de défaillance.
Réfléchissez à l’impact que votre stratégie de nouvelle tentative peut avoir sur les voisins et les autres locataires d’une application partagée, ou quand vous utilisez des ressources et des services partagés. Les politiques de nouvelle tentative agressives peuvent augmenter le nombre d’erreurs temporaires pour ces autres utilisateurs et pour les applications qui partagent les ressources et les services. De même, votre application peut être affectée par les stratégies de nouvelle tentative implémentées par les autres utilisateurs des ressources et des services. Pour les applications critiques pour l’entreprise, vous pouvez utiliser des services Premium qui ne sont pas partagés. Cela vous permet de mieux contrôler la charge et la limitation de ces ressources et services, ce qui peut vous aider à justifier le coût supplémentaire.
Remarque
Consultez les problèmes et les considérations de l’article sur le modèle Nouvelle tentative pour obtenir des conseils supplémentaires sur les compromis et les risques.
Facilitation Azure
La plupart des services Azure et des kits SDK clients fournissent un mécanisme de nouvelle tentative. Toutefois, ces mécanismes diffèrent, car chaque service a des caractéristiques et des exigences différentes, et chaque mécanisme de nouvelle tentative est paramétré sur le service spécifique. Cette section récapitule les fonctionnalités du mécanisme de nouvelle tentative pour certains services Azure couramment utilisés.
Service | Fonctionnalités de nouvelle tentative | Configuration de la stratégie | Étendue | Fonctionnalités de télémétrie |
---|---|---|---|---|
Microsoft Entra ID | Native dans la bibliothèque d’authentification Microsoft (MSAL) | Incorporé dans la bibliothèque MSAL | Interne | None |
Azure Cosmos DB | Native dans le service | Non configurable | Global | TraceSource |
Azure Data Lake Storage | Native dans le client | Non configurable | Opérations individuelles | Aucune |
Azure Event Hubs | Native dans le client | Par programme | Client | Aucune |
Azure IoT Hub | Native dans le Kit de développement logiciel (SDK) client | Par programme | Client | None |
Azure Cache pour Redis | Native dans le client | Par programme | Client | TextWriter |
Recherche cognitive Azure | Native dans le client | Par programme | Client | ETW ou personnalisé |
Azure Service Bus | Native dans le client | Par programme | NamespaceManager, MessagingFactory et client | ETW |
Azure Service Fabric | Native dans le client | Par programme | Client | Aucune |
Azure SQL Database avec ADO.NET | Polly | Déclarative et par programme | Instructions uniques ou blocs de code | Custom |
Base de données SQL avec Entity Framework | Native dans le client | Par programme | Globale par domaine d’application | None |
SQL Database avec Entity Framework Core | Native dans le client | Par programme | Globale par domaine d’application | Aucune |
Stockage Azure | Native dans le client | Par programme | Opérations individuelles et du client | TraceSource |
Remarque
Pour la plupart des mécanismes de nouvelle tentative intégrés Azure, il n’existe actuellement aucun moyen d’appliquer une stratégie de nouvelle tentative différente pour différents types d’erreurs ou d’exceptions. Vous devez configurer une stratégie qui fournit les performances et la disponibilité moyennes optimales. Une façon d’affiner votre stratégie consiste à analyser les fichiers journaux pour déterminer le type d’erreurs temporaires qui se produisent.
Exemple
Consultez le modèle d’application web fiable pour .NET pour obtenir un exemple qui utilise un grand nombre des modèles abordés dans cet article. Il existe également une implémentation de référence sur GitHub.
Liens connexes
- Modèle Disjoncteur
- Modèle Nouvelle tentative
- Modèle de limitation
- Modèle de transaction de compensation
- Billet de blog sur les modèles d’idempotency
- Résilience de connexion
- Injecter des services fictifs
- Modèle de file d’attente de lettres mortes
Liste de contrôle de fiabilité
Reportez-vous à l’ensemble complet de recommandations.