Übung: Implementieren der Anwendungsresilienz

Abgeschlossen

Das eShop-Projekt verfügt über zwei Dienste, die über HTTP-Anforderungen miteinander kommunizieren. Der Store-Dienst ruft den Product-Dienst auf, um die Liste aller Produkte abzurufen, die aktuell zum Kauf verfügbar sind.

Die aktuelle Version der App bietet keine Resilienzbehandlung. Wenn der Product-Dienst nicht verfügbar ist, gibt der Store-Dienst einen Fehler an die Kund*innen zurück und fordert sie auf, es später nochmal zu versuchen. Dieses Verhalten ist keine gute Benutzererfahrung.

Sie wurden gebeten, der App Resilienz hinzuzufügen, damit der Store-Dienst den Back-End-Dienstaufruf im Fall eines Fehlers wiederholt.

In dieser Übung fügen Sie einer vorhandenen cloudnativen App Resilienz hinzu und testen, ob Ihr Fix funktioniert hat.

Öffnen Sie die Entwicklungsumgebung

Sie können entweder einen GitHub-Codespace verwenden, der die Übung hostet, oder die Übung lokal in Visual Studio Code durchführen.

Um einen Codespace zu verwenden, erstellen Sie einen vorkonfigurierten GitHub Codespace mit diesem Link zur Codespace-Erstellung.

Die Erstellung und Konfiguration des Codespace auf GitHub dauert ein paar Minuten. Nach Abschluss des Vorgangs werden die Codedateien für die Übung angezeigt. Der Code, der für den Rest des Moduls verwendet wird, befindet sich im Verzeichnis /dotnet-resiliency.

Um Visual Studio Code zu verwenden, klonen Sie das https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative Repository auf Ihrem lokalen Computer. Führen Sie dann folgende Schritte aus:

  1. Installieren Sie alle Systemanforderungen, um Dev Container in Visual Studio Code auszuführen.
  2. Achten Sie darauf, dass Docker ausgeführt wird.
  3. Öffnen Sie in einem neuen Visual Studio Code-Fenster den Ordner des geklonten Repositorys
  4. Drücken Sie STRG+UMSCHALT+P, um die Befehlspalette zu öffnen.
  5. Suche: >Dev-Containers: In Container neu erstellen und noch einmal öffnen
  6. Wählen Sie eShopLite - dotnet-resilienz aus der Dropdownliste aus. Visual Studio Code erstellt Ihren Entwicklungscontainer lokal.

Erstellen und Ausführen der App

  1. Wählen Sie im unteren Bereich die Registerkarte TERMINAL und führen Sie den folgenden Befehl aus, um zum Stammverzeichnis des Codes zu gelangen:

    cd dotnet-resiliency
    
  2. Führen Sie den folgenden Befehl aus, um die eShop-App-Bilder zu erstellen:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Führen Sie nach der Erstellung den folgenden Befehl aus, um die App zu starten:

    docker compose up
    
  4. Wählen Sie im unteren Bereich die Registerkarte PORTS und dann in der Spalte „Weitergeleitete Adresse“ der Tabelle für den Port Front-End (32000) das Symbol Im Browser öffnen aus.

    Wenn Sie die App lokal ausführen, öffnen Sie ein Browserfenster, um die http://localhost:32000/products anzuzeigen.

  5. Die eShop-App sollte ausgeführt werden. Wählen Sie das Menüelement Products aus. Daraufhin sollte die Liste der Produkte angezeigt werden.

    Screenshot: Die eShop-App wird in einem Browser ausgeführt.

Testen der aktuellen Resilienz

Sie beenden nun den Product-Dienst, um zu überprüfen, was mit der App passiert.

  1. Kehren Sie zu Ihrem Codespace zurück, und wählen Sie auf der Registerkarte TERMINAL die Option + aus, um ein neues Bash-Terminal zu öffnen.

  2. Führen Sie den folgenden Docker-Befehl aus, um die ausgeführten Container aufzulisten:

    docker ps
    

    Die Liste der derzeit ausgeführten Container sollte angezeigt werden, z. B.:

    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. Suchen Sie nach der CONTAINER-ID für den Container productservice. Im obigen Beispiel lautet die ID 6ba80f3c7ab0.

  4. Beenden Sie den Product-Dienst mit dem folgenden Docker-Befehl:

    docker stop <CONTAINER ID>
    

    Dabei ist <CONTAINER ID> die ID, die Sie im vorherigen Schritt ermittelt haben. Beispiel:

    docker stop 6ba80f3c7ab0
    
  5. Kehren Sie zur Browserregisterkarte zurück, auf der die App ausgeführt wird, und aktualisieren Sie die Seite. Es sollte eine Fehlermeldung angezeigt werden:

    „There is a problem loading our products.“ Versuchen Sie es später noch mal.

  6. Kehren Sie zu Ihrem Codespace zurück, wählen Sie im TERMINAL das Docker-Terminal aus, und drücken Sie Strg+C, um die Anwendung zu beenden. Folgendes sollte angezeigt werden:

    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
    

Hinzufügen von Resilienz zur App

Die ersten Schritte, um ihre Anwendung resilienter zu machen, bestehen darin, das Microsoft.Extensions.Http.Resilience-NuGet-Paket zum Projekt hinzuzufügen. Sie können es dann in Program.cs verwenden.

Hinzufügen des Pakets „Microsoft.Extensions.Http.Resilience“

  1. Navigieren Sie in Ihrem Codespace auf der Registerkarte TERMINAL zum Projektordner Store:

    cd Store
    
  2. Führen Sie den folgenden Befehl aus, um das NuGet-Resilienzpaket hinzuzufügen:

    dotnet add package Microsoft.Extensions.Http.Resilience
    

    Wenn Sie diesen Befehl über das Terminal im Projektordner der App ausführen, wird der Projektdatei Store.csproj der Paketverweis hinzugefügt.

  3. Wählen Sie auf der EXPLORER-Randleiste die Datei Program.cs aus.

  4. Fügen Sie am Anfang der Datei die folgende using-Anweisung hinzu:

    using Microsoft.Extensions.Http.Resilience;
    

Hinzufügen einer Standardresilienzstrategie

  1. Fügen Sie in Zeile 13 vor ; den folgenden Code hinzu:

    .AddStandardResilienceHandler()
    

    Ihr Code sollte folgendermaßen aussehen:

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

    Der obige Code fügt dem HTTPClient-Dienst einen Standardresilienzhandler hinzu. Der Handler verwendet alle Standardeinstellungen für die Standard-Resilienzstrategie.

    Für Ihre Anwendung sind keine weiteren Codeänderungen erforderlich. Lassen Sie uns die Anwendung ausführen und die Resilienz testen.

  2. Führen Sie die folgenden Befehle aus, um die eShop-App neu zu erstellen:

    cd ..
    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Wenn der Build abgeschlossen ist, führen Sie den folgenden Befehl aus, um die App zu starten:

    docker compose up
    
  4. Kehren Sie zur Browserregisterkarte zurück, auf der die App ausgeführt wird, und aktualisieren Sie die Produktseite. Die Liste mit den Produkten sollte angezeigt werden.

  5. Kehren Sie zu Ihrem Codespace zurück, und wählen Sie auf der Registerkarte TERMINAL das zweite Bash-Terminal aus. Kopieren Sie die CONTAINER-ID für den Produktservice-Container.

  6. Führen Sie den Befehl „docker stop“ erneut aus:

    docker stop <CONTAINER ID>
    
  7. Kehren Sie zur Browserregisterkarte zurück, auf der die App ausgeführt wird, und aktualisieren Sie die Produktseite. Dieses Mal sollte es etwas länger dauern, bis die Fehlermeldung der App angezeigt wird:

    „There‘s a problem loading our products.“ Versuchen Sie es später noch mal.

    Sehen wir uns die Protokolle an, um festzustellen, ob die Resilienzstrategie funktioniert.

  8. Kehren Sie zu Ihrem Codespace zurück, und wählen Sie auf der Registerkarte TERMINAL das docker-Terminal aus.

  9. Drücken Sie im Terminal Strg+C, um die Ausführung der Anwendung zu beenden.

  10. Scrollen Sie in den Protokollmeldungen nach oben, bis Sie Verweise auf Polly finden.

    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'
    

    Es sollten viele Meldungen wie die folgenden angezeigt werden, die jeweils einen Wiederholungsversuch darstellen. Die obige Meldung zeigt den zweiten Versuch und die Zeit, die zum Ausführen benötigt wurde.

Konfigurieren einer Resilienzstrategie

Wenn Sie Ihrer App Resilienz hinzufügen, müssen Sie die Notwendigkeit, schnell auf Anforderungen Ihrer Benutzer*innen zu reagieren, mit der Notwendigkeit, Back-End-Dienste nicht zu überlasten, in Einklang bringen. Nur Sie können entscheiden, ob die Standardoptionen den Anforderungen Ihres Unternehmens entsprechen.

In diesem Beispiel möchten Sie, dass der Store-Dienst etwas länger wartet, um ihm die Möglichkeit zur Wiederherstellung zu geben.

  1. Ändern Sie im Codefenster für „Program.cs“ den Code in Zeile 13 wie folgt:

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

    Der obige Code ändert die Standardeinstellungen der Wiederholungsstrategie in eine maximale Anzahl von sieben Wiederholungen. Denken Sie daran, dass die Strategie ein exponentielles Backoff ist, so dass die Gesamtzeit etwa 5 Minuten beträgt.

  2. Beenden Sie „docker up“ mit STRG+C. Führen Sie dann den folgenden Befehl aus, um die eShop-App neu zu erstellen:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Wenn der Build abgeschlossen ist, führen Sie den folgenden Befehl aus, um die App zu starten:

    docker compose up
    

    Beenden Sie den Back-End-Dienstcontainer im Bash-Terminal, und aktualisieren Sie den eShop. Beachten Sie, dass die Fehlermeldung länger angezeigt wird. Wenn Sie die Protokolle überprüfen, können Sie jedoch sehen, dass die Wiederholungsstrategie nur fünf Wiederholungen ausgeführt hat. Die letzte Meldung von Polly lautet wie folgt:

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

    Die obige Meldung besagt, dass die maximale Anzahl von Wiederholungsversuchen durch die Zeitüberschreitung für die gesamte Anfrage nicht erreicht wird. Sie können das Problem beheben, indem Sie die Gesamtzeitspanne für Anfragen erhöhen.

  4. Drücken Sie im Terminal Strg+C, um die Anwendung zu beenden.

  5. Ändern Sie im Codefenster für „Program.cs“ den Code in Zeile 13 wie folgt:

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

    Der obige Code ändert das Gesamtanforderungstimeout in 260 Sekunden, sodass es jetzt länger ist als die Wiederholungsstrategie.

    Mit diesen Änderungen sollten Sie genug Zeit haben, um die Anwendung auszuführen, den Produktdienst zu stoppen, die Terminalprotokolle auf Wiederholungsversuche zu prüfen, den eShop zu aktualisieren, um die Ladenachricht zu sehen, und schließlich den Produktdienst neu zu starten, um die Liste der Produkte erfolgreich anzuzeigen.

  6. Führen Sie den folgenden Befehl aus, um die eShop-App neu zu erstellen:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  7. Wenn der Build abgeschlossen ist, führen Sie den folgenden Befehl aus, um die App zu starten:

    docker compose up
    

Testen der neuen Resilienzoptionen

Verwenden Sie die Docker-Erweiterung, um die Anwendung in Ihrem Container zu testen. Die Erweiterung stellt eine GUI zum Anzeigen und Steuern des Status von Containern bereit.

  1. Wählen Sie im linken Menü das Docker-Symbol aus.

    Screenshot: Docker-Erweiterung und Darstellung, wie der Produktdienst beendet wird

  2. Klicken Sie im Bereich DOCKER unter CONTAINER mit der rechten Maustaste auf den Container products, und wählen Sie Beenden aus.

  3. Kehren Sie zur Browserregisterkarte zurück, auf der die App ausgeführt wird, und aktualisieren Sie die Produktseite. Es sollte die Meldung Laden... angezeigt werden.

  4. Kehren Sie zu Ihrem Codespace zurück, und wählen Sie auf der Registerkarte TERMINAL das Docker-Terminal aus. Wie Sie sehen, funktioniert die Resilienzstrategie.

  5. Klicken Sie im Bereich DOCKER unter CONTAINER mit der rechten Maustaste auf den Container products, und wählen Sie Starten aus.

  6. Wechseln Sie zurück zur Browserregisterkarte, auf der die App ausgeführt wird. Warten Sie, und die App sollte die Liste der Produkte wiederherstellen.

  7. Beenden Sie im Terminal Docker mit Ctrl+C.