Exercice : Implémenter la résilience de l’application

Effectué

Le projet eShop contient deux services qui communiquent entre eux à l’aide de requêtes HTTP. Le service Store appelle le service Product pour obtenir la liste de tous les produits actuellement disponibles à l’achat.

La version actuelle de l’application n’a aucune gestion de la résilience. Si le service Product n’est pas disponible, le service Store retourne une erreur aux clients et lui demande de réessayer ultérieurement. Ce comportement n’est pas une bonne expérience utilisateur.

Votre responsable vous demande d’ajouter une résilience à l’application afin que le service Store retente l’appel du service back-end en cas d’échec.

Dans cet exercice, vous ajoutez une résilience à une application native cloud existante et testez votre correctif.

Ouvrez l’environnement de développement

Vous pouvez choisir d’utiliser un codespace GitHub qui héberge l’exercice ou effectuer l’exercice localement dans Visual Studio Code.

Pour utiliser un codespace, créez un codespace GitHub préconfiguré avec ce lien de création de codespace.

La création et la configuration du codespace par GitHub prend quelques minutes. Lorsque le processus est terminé, vous voyez les fichiers de code de l’exercice. Le code à utiliser pour le reste de ce module se trouve dans le répertoire /dotnet-resiliency.

Pour utiliser Visual Studio Code, clonez le référentiel https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative sur votre ordinateur local. Ensuite :

  1. Installez la configuration requise pour exécuter le conteneur de développement dans Visual Studio Code.
  2. Vérifiez que Docker est en cours d’exécution.
  3. Dans une nouvelle fenêtre Visual Studio Code, ouvrez le dossier du référentiel cloné.
  4. Appuyez sur Ctrl+Maj+P pour ouvrir la palette de commandes.
  5. Recherche : >Conteneurs de développement : Reconstruire et rouvrir dans un conteneur
  6. Sélectionnez eShopLite - dotnet-resiliency dans la liste déroulante. Visual Studio Code crée votre conteneur de développement localement.

Générer et exécuter l’application

  1. Dans le panneau inférieur, sélectionnez l’onglet TERMINAL et exécutez la commande suivante pour accéder à la racine du code :

    cd dotnet-resiliency
    
  2. Exécutez la commande suivante pour générer les images de l’application eShop :

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Une fois la génération terminée, exécutez la commande suivante pour démarrer l’application :

    docker compose up
    
  4. Dans le volet inférieur, sélectionnez l’onglet PORTS, puis, dans la colonne Adresse transférée de la table, sélectionnez l’icône Ouvrir dans le navigateur pour le port Front-end (32000).

    Si vous exécutez l’application localement, ouvrez une fenêtre de navigateur pour afficher http://localhost:32000/products.

  5. L’application eShop doit être en cours d’exécution. Sélectionnez l’élément de menu Produits. Vous devriez voir la liste des produits.

    Capture d’écran montrant l’application eShop s’exécutant dans un navigateur.

Tester la résilience actuelle

Arrêtez le service du produit pour voir ce qui se passe dans l’application.

  1. Retournez à votre codespace et, dans l’onglet TERMINAL, sélectionnez + pour ouvrir un nouveau terminal bash.

  2. Exécutez la commande Docker suivante pour répertorier les conteneurs en cours d’exécution :

    docker ps
    

    La liste des conteneurs en cours d’exécution s’affiche, par exemple :

    CONTAINER ID   IMAGE                                                                            COMMAND                  CREATED          STATUS          PORTS                                                        NAMES
    c08285e8aaa4   storeimage                                                                       "dotnet Store.dll"       8 minutes ago    Up 8 minutes    80/tcp, 443/tcp, 0.0.0.0:5902->8080/tcp, :::5902->8080/tcp   eshoplite-frontend-1
    6ba80f3c7ab0   productservice                                                                   "dotnet Products.dll"    8 minutes ago    Up 8 minutes    80/tcp, 443/tcp, 0.0.0.0:5200->8080/tcp, :::5200->8080/tcp   eshoplite-backend-1
    cd0c822a5222   vsc-eshoplite-958868d22c9851dd911b2423199bfc782861d1a8f7afac48e5096a1b7516082f   "/bin/sh -c 'echo Co…"   27 minutes ago   Up 27 minutes     
    
  3. Recherchez l’ID DE CONTENEUR du conteneur productservice. Dans l’exemple ci-dessus, l’ID est 6ba80f3c7ab0.

  4. Arrêtez le service de votre produit avec cette commande Docker :

    docker stop <CONTAINER ID>
    

    Dans quel <CONTAINER ID> est l’ID trouvé à l’étape précédente. Par exemple :

    docker stop 6ba80f3c7ab0
    
  5. Retournez à l’onglet du navigateur exécutant l’application et actualisez la page. Un message d’erreur doit s’afficher :

    Le chargement de nos produits rencontre un problème. Veuillez réessayer plus tard.

  6. Retournez à votre codespace et, dans le TERMINAL, sélectionnez le terminal docker et appuyez sur Ctrl+C pour arrêter l’application. Ce qui suit doit s’afficher :

    Gracefully stopping... (press Ctrl+C again to force)
    Aborting on container exit...
    [+] Stopping 2/1
     ✔ Container eshoplite-frontend-1  Stopped                                                                      0.3s 
     ✔ Container eshoplite-backend-1   Stopped                                                                      0.0s 
    canceled
    

Ajouter une résilience à l’application

Les premières étapes pour rendre votre application plus résiliente sont d’ajouter le package NuGet Microsoft.Extensions.Http.Resilience au projet. Vous pouvez ensuite l’utiliser dans Program.cs.

Ajouter le package Microsoft.Extensions.Http.Resilience

  1. Dans votre codespace, sur l’onglet TERMINAL, accédez au dossier du projet Store :

    cd Store
    
  2. Exécutez la commande suivante pour ajouter le package de résilience NuGet :

    dotnet add package Microsoft.Extensions.Http.Resilience
    

    L’exécution de cette commande depuis le terminal dans le dossier du projet d’applications ajoute les informations de référence des packages au fichier projet Store.csproj.

  3. Dans la barre latérale EXPLORER, sélectionnez Program.cs.

  4. Au début du fichier, ajoutez l'instruction using suivante :

    using Microsoft.Extensions.Http.Resilience;
    

Ajouter une stratégie standard de résilience

  1. À la ligne 13, avant ;, ajoutez ce code :

    .AddStandardResilienceHandler()
    

    Votre code doit ressembler à ceci :

    builder.Services.AddHttpClient<ProductService>(c =>
    {
        var url = builder.Configuration["ProductEndpoint"] ?? throw new InvalidOperationException("ProductEndpoint is not set");
    
        c.BaseAddress = new(url);
    }).AddStandardResilienceHandler();
    

    Le code ci-dessus ajoute un gestionnaire standard de résilience à HTTPClient. Le gestionnaire utilise tous les paramètres par défaut pour la stratégie de résilience standard.

    Aucune autre modification de code n’est nécessaire à votre application. Nous allons exécuter l’application et tester la résilience.

  2. Exécutez les commandes suivantes pour régénérer l’application eShop :

    cd ..
    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Quand la génération est terminée, exécutez la commande suivante pour démarrer l’application :

    docker compose up
    
  4. Retournez à l’onglet du navigateur exécutant l’application et actualisez la page du produit. La liste des produits s’affiche.

  5. Retournez à votre codespace et, dans l’onglet TERMINAL, sélectionnez le second terminal bash. Copiez l’ID DE CONTENEUR du conteneur productservice.

  6. Réexécutez la commande docker stop :

    docker stop <CONTAINER ID>
    
  7. Retournez à l’onglet du navigateur exécutant l’application et actualisez la page du produit. Cette fois, cela va durer plus longtemps jusqu’à l’affichage des messages d’erreur des applications :

    Le chargement de nos produits rencontre un problème. Veuillez réessayer plus tard.

    Nous allons vérifier les journaux pour voir si notre stratégie de résilience fonctionne.

  8. Retournez à votre codespace et, dans l’onglet TERMINAL, sélectionnez le terminal docker.

  9. Dans le terminal, appuyez sur Ctrl+C pour arrêter l’exécution de l’application.

  10. Dans les messages du journal, faites défiler jusqu’à ce que vous trouviez des références à Polly.

    eshoplite-frontend-1  | warn: Polly[3]
    eshoplite-frontend-1  |       Execution attempt. Source: 'ProductService-standard//Standard-Retry', Operation Key: '', Result: 'Name or service not known (backend:8080)', Handled: 'True', Attempt: '2', Execution Time: '27.2703'
    

    Vous devriez voir de nombreux messages comme celui-ci, chacun d’eux étant une nouvelle tentative. Le message ci-dessus montre la deuxième tentative et le temps nécessaire à son exécution.

Configurer une stratégie de résilience

Lorsque vous ajoutez la résilience à votre application, vous équilibrez la nécessité de répondre rapidement à vos utilisateurs, avec la nécessité de ne pas surcharger les services back-end. Seuls vous pouvez décider si les options par défaut répondent aux besoins de vos entreprises.

Dans cet exemple, vous souhaitez que le service de magasin attende un peu plus longtemps afin de permettre au service du magasin de récupérer.

  1. Dans la fenêtre de code de Program.cs, remplacez le code dans la ligne 13 par :

    .AddStandardResilienceHandler(options =>
    {
        options.Retry.MaxRetryAttempts = 7;
    });
    

    Le code ci-dessus modifie la stratégie par défaut de nouvelle tentative pour avoir au maximum sept retraits. N’oubliez pas que la stratégie est un backoff exponentiel, donc le temps total est d’environ 5 minutes.

  2. Arrêtez docker avec le raccourci Ctrl+C. Exécutez ensuite la commande suivante pour régénérer l’application eShop :

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Quand la génération est terminée, exécutez la commande suivante pour démarrer l’application :

    docker compose up
    

    Arrêtez le conteneur de service back-end dans le terminal bash et actualisez l’eShop. Notez qu’il faut plus de temps pour voir le message d’erreur. Si vous vérifiez les journaux d’activité, vous pouvez voir que la stratégie de nouvelle tentative n’a été retentée que cinq fois. Le dernier message de Polly est le suivant :

    Polly.Timeout.TimeoutRejectedException: The operation didn't complete within the allowed timeout of '00:00:30'.
    

    Le message ci-dessus vous indique que le délai d’expiration maximal des requêtes empêche le nombre maximal de nouvelles tentatives d’être atteint. Vous pouvez corriger le problème en augmentant le délai d’expiration maximal des requêtes.

  4. Dans le terminal, appuyez sur Ctrl+C pour arrêter l’application.

  5. Dans la fenêtre de code de Program.cs, remplacez le code dans la ligne 13 par :

    .AddStandardResilienceHandler(options =>
    {
        options.Retry.RetryCount = 7;
        options.TotalRequestTimeout = new HttpTimeoutStrategyOptions
        {
            Timeout = TimeSpan.FromMinutes(5)
        };
    });
    

    Le code ci-dessus modifie le délai total d’expiration de la requête à 260 secondes, ce qui est désormais plus long que la stratégie de nouvelle tentative.

    Avec ces modifications, vous devriez avoir suffisamment de temps pour exécuter l’application, arrêter le service de produit, vérifier les journaux de nouvelles tentatives, actualiser l’eShop pour afficher le message de chargement et enfin redémarrer le service de produit pour afficher correctement la liste des produits.

  6. Exécutez la commande suivante pour régénérer l’application eShop :

    dotnet publish /p:PublishProfile=DefaultContainer
    
  7. Quand la génération est terminée, exécutez la commande suivante pour démarrer l’application :

    docker compose up
    

Tester les nouvelles options de résilience

Pour pouvoir tester l’application dans votre conteneur, utilisez l’extension Docker. L’extension fournit une interface graphique utilisateur pour afficher et contrôler l’état des conteneurs.

  1. Dans le menu de gauche, sélectionnez l’icône Docker.

    Capture d’écran de l’extension Docker montrant comment arrêter le service de produits.

  2. Dans le panneau DOCKER, sous CONTENEURS, cliquez avec le bouton droit sur le conteneur products, puis sélectionnez Arrêter.

  3. Retournez à l’onglet du navigateur exécutant l’application et actualisez la page du produit. Vous devriez voir le message Chargement....

  4. Retournez à votre codespace et, dans l’onglet TERMINAL, sélectionnez le terminal docker. La stratégie de résilience fonctionne.

  5. Dans le panneau DOCKER, sous CONTENEURS, cliquez avec le bouton droit sur le conteneur products, puis sélectionnez Démarrer.

  6. Revenez à l’onglet du navigateur exécutant l’application. Patientez, l’application devrait afficher la liste des produits.

  7. Dans le terminal, arrêtez docker avec Ctrl+C.