Résilience de l’application et de l’infrastructure

Effectué

La résilience est la capacité à récupérer suite à des défaillances temporaires. La stratégie de récupération de l’application restaure la fonction normale avec un impact minimal sur l’utilisateur. Des défaillances peuvent se produire dans des environnements cloud et votre application doit répondre de manière à réduire les temps d’arrêt et les pertes de données. Idéalement, votre application gère correctement les défaillances sans que l’utilisateur ait connaissance du problème.

Étant donné que les environnements de microservices peuvent être volatiles, concevez vos applications de manière à ce qu’elles s’attendent et à ce qu’elles gèrent les défaillances partielles. Une défaillance partielle peut inclure, par exemple, des exceptions de code, des pannes du réseau,des processus de serveur sans réponse et des défaillances matérielles. Même des activités planifiées, telles que le déplacement de conteneurs vers un nœud différent au sein d’un cluster Kubernetes, peuvent entraîner une défaillance temporaire.

Approches de la résilience

Lors de la conception d’applications résilientes, vous devez souvent choisir entre la stratégie Fail-fast et la dégradation progressive. La stratégie Fail-fast signifie que l’application lève immédiatement une erreur ou une exception lorsqu’un problème se produit au lieu d’essayer de récupérer ou de contourner le problème. Cela permet d’identifier et de résoudre des problèmes rapidement. La dégradation progressive signifie que l’application tente de continuer à fonctionner dans une capacité limitée même en cas d’échec de certains composants.

Dans les applications natives cloud, il est important que les services gèrent progressivement les défaillances plutôt que d’échouer rapidement. Étant donné que les microservices sont décentralisés et déployables de manière indépendante, les défaillances partielles sont attendues. La stratégie Fail-fast autorisera la défaillance d’un service pour retirer rapidement les services dépendants, ce qui réduit la résilience globale du système. Les microservices doivent plutôt être codés pour anticiper et tolérer des défaillances de service internes et externes. Cette dégradation progressive permet au système global de continuer à fonctionner même en cas d’interruption de certains services. Les fonctions critiques pour les utilisateurs finaux peuvent être maintenues, ce qui évite une panne complète. Une défaillance progressive permet également aux services perturbés de récupérer ou de se réparer automatiquement avant d’affecter le reste du système. Pour les applications basées sur les microservices, la dégradation progressive est ainsi mieux alignée sur les meilleures pratiques de résilience, telles que l’isolation des erreurs et la récupération rapide. Elle empêche aux incidents locaux de se répercuter en cascade sur le système.

Il existe deux approches fondamentales pour prendre en charge une dégradation progressive avec résilience : l’application et l’infrastructure. Chaque approche présente des avantages et des inconvénients. Les deux approches peuvent être appropriées en fonction de la situation. Ce module explique comment implémenter la résilience basée sur le code et basée sur l’infrastructure.

Résilience basée sur le code

Pour implémenter la résilience basée sur le code,.NET dispose d’une bibliothèque d’extensions pour la résilience et la gestion des défaillances temporaires, Microsoft.Extensions.Http.Resilience.

Elle utilise une syntaxe fluide et facile à comprendre afin de générer du code de gestion des défaillances de manière thread-safe. Il existe plusieurs stratégies de résilience qui définissent le comportement de la gestion des défaillances. Dans ce module, vous allez appliquer les stratégies de nouvelles tentatives et de disjoncteur aux opérations du client HTTP.

Stratégie de nouvelle tentative

Une stratégie de nouvelle tentative correspond exactement à ce que le nom implique. La requête est retentée après une brève attente en cas de réception d’une réponse d’erreur. Le temps d’attente augmente avec chaque nouvelle tentative. L’augmentation peut être linéaire ou exponentielle.

Une fois le nombre maximal de nouvelles tentatives atteint, la stratégie abandonne et lève une exception. Du point de vue de l’utilisateur, l’application prend généralement plus de temps pour effectuer certaines opérations. L’application peut également prendre un certain temps avant d’informer l’utilisateur qu’elle n’a pas pu terminer l’opération.

Stratégie de disjoncteur

Une stratégie de disjoncteur offre un temps d’arrêt au service cible après un nombre répété de défaillances en interrompant la tentative de communication avec celui-ci. Le service peut rencontrer un problème grave et être temporairement incapable de répondre. Après un nombre défini de défaillances consécutives, les tentatives de connexion sont suspendues, ouvrant le circuit. Pendant cette attente, les opérations supplémentaires sur le service cible échouent immédiatement sans tenter de se connecter au le service. Une fois le délai d’attente écoulé, l’opération est de nouveau tentée. Si le service répond correctement, le circuit est fermé et le système revient à la normale.

Résilience basée sur l’infrastructure

Pour implémenter la résilience basée sur l’infrastructure, vous pouvez utiliser un maillage de services. Outre la résilience sans modification du code, un maillage de services fournit la gestion du trafic, la stratégie, la sécurité, l’identité forte et l’observabilité. Votre application est dissociée de ces fonctionnalités opérationnelles, qui sont déplacées vers la couche d’infrastructure.

Comparaison avec les approches basées sur le code

Une approche de résilience basée sur l’infrastructure peut utiliser une vue basée en fonction des métriques qui lui permet de s’adapter dynamiquement aux conditions du cluster en temps réel. Cette approche ajoute une autre dimension à la gestion du cluster, mais n’ajoute pas de code.

Une approche basée sur le code vous permet :

  • deviner les paramètres de nouvelles tentatives et de délai d’attente appropriés
  • vous concentrer sur une requête HTTP spécifique.

Il n’existe aucun moyen raisonnable de répondre à une défaillance de l’infrastructure dans le code de votre application. Tenez compte des centaines ou des milliers de requêtes qui sont traitées simultanément. Même une nouvelle tentative avec une interruption exponentielle (nombre de requêtes) peut inonder un service.

Par contre, les approches basées sur l’infrastructure ne connaissent pas le fonctionnement interne des applications. Par exemple, les transactions de base de données complexes sont invisibles pour les maillages de service. Ces transactions ne peuvent être protégées en cas de défaillance qu’avec une approche basée sur le code.

Dans les prochaines unités, vous allez implémenter la résilience pour une application basée sur un microservice en utilisant la résilience HTTP .NET dans le code et un maillage de service Linkerd.