Übung – Implementieren der Anwendungsresilienz

Abgeschlossen

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

Die aktuelle Version der App hat keine Resilienzbehandlung. Wenn der Dienst nicht verfügbar ist, gibt der ProductStore Dienst einen Fehler an die Kunden zurück und fordert ihn auf, ihn später erneut zu versuchen. Dieses Verhalten ist keine gute Benutzererfahrung.

Ihr Vorgesetzter fordert Sie auf, der App Resilienz hinzuzufügen, damit der Store Dienst den Back-End-Dienstaufruf erneut aufruft, wenn er fehlschlägt.

In dieser Übung fügen Sie einer vorhandenen cloudeigenen App Resilienz hinzu, und testen Sie Ihren Fix.

Öffnen der 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 Codespace-Erstellungslink.

GitHub dauert mehrere Minuten, um den Codespace zu erstellen und zu konfigurieren. Nach Abschluss des Vorgangs werden die Codedateien für die Übung angezeigt. Der Code, der für den Rest dieses Moduls verwendet werden soll, 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-Container: Neu erstellen und erneut im Container ö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 aus, und führen Sie den folgenden Befehl aus, um zum Codestamm zu wechseln:

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

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

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

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

  5. Die eShop-App sollte laufen. Wählen Sie das Menüelement "Produkte " aus, es sollte die Liste der Produkte angezeigt werden.

    Screenshot der eShop-App, die in einem Browser ausgeführt wird.

Testen Sie die aktuelle Ausfallsicherheit

Beenden Sie den Produktdienst, um zu sehen, was mit der App passiert.

  1. Wechseln Sie zurück zum Codespace, und wählen Sie auf der Registerkarte + aus, um ein neues Bash-Terminal zu öffnen.

  2. Führen Sie den folgenden Docker-Befehl aus, um die ausgeführten Container auflisten zu können:

    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 ProductService-Container . Im obigen Beispiel ist die ID 6ba80f3c7ab0.

  4. Beenden Sie Ihren Produktdienst mit diesem Docker-Befehl:

    docker stop <CONTAINER ID>
    

    Dabei handelt es <CONTAINER ID> sich um die ID, die Sie im vorherigen Schritt gefunden 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:

    Es besteht ein Problem beim Laden unserer Produkte. Versuchen Sie es später erneut.

  6. Wechseln Sie zurück zum Codespace, und wählen Sie im TERMINAL das Docker-Terminal aus, und drücken Sie STRG+C , um die App 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 App stabiler zu machen, sind das Hinzufügen des Microsoft.Extensions.Http.Resilience NuGet-Pakets zum Projekt. Sie können es dann in Program.cs verwenden.

Hinzufügen des Microsoft.Extensions.Http.Resilience-Pakets

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

    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 Ordner "Apps-Projekt" ausführen, wird der Store.csproj-Projektdatei der Paketverweis hinzugefügt.

  3. Wählen Sie in der EXPLORER-RandleisteProgram.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 ;diesen 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 einen Standardresilienzhandler hinzu. Der Handler verwendet alle Standardeinstellungen für die Standardresilienzstrategie.

    Für Ihre App sind keine weiteren Codeänderungen erforderlich. Lassen Sie uns die App 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. Führen Sie nach Abschluss des Builds 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. Sie sollten die Produktliste sehen.

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

  6. Führen Sie den Docker Stop-Befehl erneut aus:

    docker stop <CONTAINER ID>
    
  7. Kehren Sie zur Browser-Registerkarte zurück, auf der die App läuft, und laden Sie die Produktseite neu. Dieses Mal sollte es etwas länger dauern, bis die Fehlermeldung der Apps angezeigt wird:

    Beim Laden unserer Produkte ist ein Problem aufgetreten. Versuchen Sie es später erneut.

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

  8. Wechseln Sie zurück zum Codespace, 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 App zu beenden.

  10. Scrollen Sie in den Protokollnachrichten 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'
    

    Sie sollten viele Nachrichten wie diese sehen; jedes ist ein Wiederholungsversuch. 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 schnell auf Ihre Benutzer reagieren und keine Back-End-Dienste überladen. Nur Sie können entscheiden, ob die Standardoptionen Ihren Anforderungen ihres Unternehmens entsprechen.

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

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

    .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 exponentieller Backoff ist, sodass die Gesamtzeit ungefähr 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. Führen Sie nach Abschluss des Builds 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 jedoch überprüfen, können Sie sehen, dass die Wiederholungsstrategie nur fünf Mal wiederholt wurde. Die letzte Nachricht von Polly lautet:

    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 das Gesamtanforderungstimeout erhöhen.

  4. Drücken Sie im Terminal STRG+C , um die App zu beenden.

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

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

    Der obige Code ändert das Gesamtanforderungstimeout auf 260 Sekunden, was jetzt länger als die Wiederholungsstrategie ist.

    Mit diesen Änderungen sollten Sie genügend Zeit haben, um die App auszuführen, den Produktdienst zu beenden, die Terminalprotokolle auf Wiederholungsversuche zu überprüfen, den eShop zu aktualisieren, um die Lademeldung anzuzeigen, und schließlich den Produktdienst neu 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. Führen Sie nach Abschluss des Builds den folgenden Befehl aus, um die App zu starten:

    docker compose up
    

Testen der neuen Resilienzoptionen

Verwenden Sie die Docker-Erweiterung, um die App 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 der Docker-Erweiterung, der zeigt, wie der Produktdienst beendet wird.

  2. Klicken Sie im DOCKER-Bereich unter CONTAINERn mit der rechten Maustaste auf den Produktcontainer , und wählen Sie "Beenden" aus.

  3. Gehen Sie zurück zum geöffneten Browser-Tab, auf dem die App ausgeführt wird, und aktualisieren Sie die Produktseite. Es sollte die Meldung "Laden... " angezeigt werden.

  4. Wechseln Sie zurück zum Codespace, und wählen Sie auf der Registerkarte TERMINAL das Docker-Terminal aus. Die Resilienzstrategie funktioniert.

  5. Klicken Sie im DOCKER-Bereich unter CONTAINERn mit der rechten Maustaste auf den Produktcontainer , und wählen Sie "Start" aus.

  6. Gehen Sie zurück zur Browser-Registerkarte, auf der die App läuft. Warten Sie, und die App sollte die Liste der Produkte wiederherstellen.

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