Partager via


Présentation du développement d’applications résilientes

La résilience est la capacité d’une application à récupérer à partir d’échecs temporaires et à continuer à fonctionner. Dans le contexte de la programmation .NET, la résilience est obtenue en concevant des applications qui peuvent gérer les défaillances correctement et récupérer rapidement. Pour aider à créer des applications résilientes dans .NET, les deux packages suivants sont disponibles sur NuGet :

Paquet NuGet Descriptif
📦 Microsoft.Extensions.Resilience Ce package NuGet fournit des mécanismes permettant de renforcer les applications contre les défaillances temporaires.
📦 Microsoft.Extensions.Http.Resilience Ce package NuGet fournit des mécanismes de résilience spécifiquement pour la HttpClient classe.

Ces deux packages NuGet sont basés sur Polly, qui est un projet open source populaire. Polly est une bibliothèque .NET de résilience et de gestion des erreurs transitoires qui permet aux développeurs d'exprimer des stratégies telles que la réessai, le disjoncteur, le délai d'expiration, l'isolation par cloisonnement, la limitation de débit, la repli et la couverture de manière fluide et thread-safe.

Importante

Le package NuGet Microsoft.Extensions.Http.Polly est déconseillé. Utilisez l’un des packages mentionnés à la place.

Commencez

Pour bien démarrer avec la résilience dans .NET, installez le package NuGet Microsoft.Extensions.Resilience .

dotnet add package Microsoft.Extensions.Resilience

Pour plus d’informations, consultez dotnet package add ou gérer les dépendances des packages dans les applications .NET.

Créer un pipeline de résilience

Pour utiliser la résilience, vous devez d’abord créer un pipeline de stratégies basées sur la résilience. Chaque stratégie configurée s’exécute dans l’ordre de configuration. En d’autres termes, l’ordre est important. Le point d’entrée est une méthode d’extension sur le IServiceCollection type, nommé AddResiliencePipeline. Cette méthode accepte un identificateur du pipeline et un délégué qui configure le pipeline. Le délégué reçoit une instance de ResiliencePipelineBuilder, qui est utilisée pour ajouter des stratégies de résilience au pipeline.

Considérons l'exemple suivant basé sur une chaîne key :

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Registry;
using Polly.Retry;
using Polly.Timeout;

var services = new ServiceCollection();

const string key = "Retry-Timeout";

services.AddResiliencePipeline(key, static builder =>
{
    // See: https://www.pollydocs.org/strategies/retry.html
    builder.AddRetry(new RetryStrategyOptions
    {
        ShouldHandle = new PredicateBuilder().Handle<TimeoutRejectedException>()
    });

    // See: https://www.pollydocs.org/strategies/timeout.html
    builder.AddTimeout(TimeSpan.FromSeconds(1.5));
});

Code précédent :

  • Crée une nouvelle instance ServiceCollection.
  • Définit un key pour identifier le pipeline.
  • Ajoute un pipeline de résilience à l’instance ServiceCollection .
  • Configure le pipeline avec des stratégies de nouvelle tentative et de délai d'expiration.

Chaque pipeline est configuré pour un key donné, et chaque key est utilisé pour identifier son correspondant ResiliencePipeline lorsque l'on récupère le pipeline du fournisseur. Le key est un paramètre de type générique de la méthode AddResiliencePipeline.

Extensions pour le générateur de pipeline de résilience

Pour ajouter une stratégie au pipeline, appelez l’une des méthodes d’extension disponibles Add* sur l’instance ResiliencePipelineBuilder .

  • AddRetry: réessayez si quelque chose échoue, ce qui est utile lorsque le problème est temporaire et peut disparaître.
  • AddCircuitBreaker: arrêtez d’essayer si quelque chose est cassé ou occupé, ce qui vous permet d’éviter de perdre du temps et de rendre les choses pires.
  • AddTimeout: abandonnez si quelque chose prend trop de temps, ce qui peut améliorer les performances en libérant des ressources.
  • AddRateLimiter: limitez le nombre de demandes que vous acceptez, ce qui vous permet de contrôler la charge entrante.
  • AddConcurrencyLimiter: limitez le nombre de demandes que vous effectuez, ce qui vous permet de contrôler la charge sortante.
  • AddFallback: effectuez une autre action en cas d’échecs, ce qui améliore l’expérience utilisateur.
  • AddHedging: émettez plusieurs requêtes en cas de latence ou d’échec élevé, ce qui peut améliorer la réactivité.

Pour plus d’informations, consultez stratégies de résilience. Pour obtenir des exemples, consultez Générer des applications HTTP résilientes : modèles de développement clés.

Enrichissement des mesures

L’enrichissement est l’augmentation automatique des données de télémétrie avec un état connu, sous la forme de paires nom/valeur. Par exemple, une application peut émettre un journal qui inclut l’opération et le code de résultat sous forme de colonnes pour représenter le résultat d’une opération. Dans ce cas et en fonction du contexte périphérique, l’enrichissement ajoute le nom du cluster, le nom du processus, la région, l’ID de locataire, et bien plus encore au journal, car il est envoyé au serveur principal de télémétrie. Lorsque l’enrichissement est ajouté, le code de l’application n’a pas besoin d’effectuer d’autres opérations supplémentaires pour tirer parti des métriques enrichies.

Comment fonctionne l'enrichissement ?

Imaginez 1 000 instances de service réparties à l'échelle mondiale générant des journaux d'activité et des mesures. Lorsque vous rencontrez un problème sur votre tableau de bord de service, il est essentiel d’identifier rapidement la région ou le centre de données problématique. L’enrichissement garantit que les enregistrements de métrique contiennent les informations nécessaires pour identifier les défaillances dans les systèmes distribués. Sans enrichissement, le fardeau dépend du code de l’application pour gérer cet état en interne, l’intégrer dans le processus de journalisation et le transmettre manuellement. L’enrichissement simplifie ce processus, en toute transparence, sans affecter la logique de l’application.

Dans le cas de la résilience, lorsque vous ajoutez l’enrichissement, les dimensions suivantes sont ajoutées aux données de télémétrie sortantes :

  • error.type: version à faible cardinalité des informations concernant une exception.
  • request.name: nom de la requête.
  • request.dependency.name: nom de la dépendance.

En arrière-plan, l'enrichissement de la résilience s'appuie sur la télémétrie Polly MeteringEnricher. Pour plus d'informations, veuillez consulter Polly : Enrichissement de la mesure.

Renforcer la résilience

En plus d'enregistrer un pipeline de résilience, vous pouvez également enregistrer un enrichissement de la résilience. Pour ajouter l’enrichissement, appelez la AddResilienceEnricher(IServiceCollection) méthode d’extensions sur l’instance IServiceCollection .

services.AddResilienceEnricher();

En appelant la AddResilienceEnricher méthode d’extension, vous ajoutez des dimensions au-dessus des dimensions par défaut intégrées à la bibliothèque Polly sous-jacente. Les dimensions d’enrichissement suivantes sont ajoutées :

Utiliser le pipeline de résilience

Pour utiliser un pipeline de résilience configuré, vous devez obtenir le pipeline à partir d'un ResiliencePipelineProvider<TKey>. Lorsque vous avez ajouté le pipeline précédemment, le key était de type string, vous devez donc obtenir le pipeline à partir du ResiliencePipelineProvider<string>.

using ServiceProvider provider = services.BuildServiceProvider();

ResiliencePipelineProvider<string> pipelineProvider =
    provider.GetRequiredService<ResiliencePipelineProvider<string>>();

ResiliencePipeline pipeline = pipelineProvider.GetPipeline(key);

Code précédent :

  • Génère un(e) ServiceProvider à partir de l’instance ServiceCollection.
  • Récupère le ResiliencePipelineProvider<string> auprès du fournisseur de services.
  • Récupère le ResiliencePipeline du ResiliencePipelineProvider<string>.

Exécuter le pipeline de résilience

Pour utiliser le pipeline de résilience, appelez l’une des méthodes disponibles Execute* sur l’instance ResiliencePipeline . Par exemple, considérez un appel à la méthode ExecuteAsync :

await pipeline.ExecuteAsync(static cancellationToken =>
{
    // Code that could potentially fail.

    return ValueTask.CompletedTask;
});

Le code précédent exécute le délégué dans la méthode ExecuteAsync. En cas d’échec, les stratégies configurées sont exécutées. Par exemple, si l’option RetryStrategy est configurée pour réessayer trois fois, le délégué est exécuté quatre fois (une tentative initiale plus trois tentatives de nouvelle tentative) avant la propagation de l’échec.

Étapes suivantes