Ćwiczenie — implementowanie odporności aplikacji

Ukończone

Projekt eShop ma dwie usługi, które komunikują się ze sobą przy użyciu żądań HTTP. Usługa Store wywołuje usługę Product , aby uzyskać listę wszystkich bieżących produktów dostępnych do zakupu.

Bieżąca wersja aplikacji nie obsługuje odporności. Product Jeśli usługa jest niedostępna, Store usługa zwraca klientowi błąd i prosi ich o próbę ponownie później. To zachowanie nie jest dobrym środowiskiem użytkownika.

Menedżer prosi Cię o dodanie odporności do aplikacji, aby Store usługa ponawiała próbę wywołania usługi zaplecza w przypadku niepowodzenia.

W tym ćwiczeniu dodasz odporność do istniejącej aplikacji natywnej dla chmury i przetestujesz poprawkę.

Otwieranie środowiska projektowego

Możesz użyć przestrzeni kodu usługi GitHub, która hostuje ćwiczenie, lub wykonać ćwiczenie lokalnie w programie Visual Studio Code.

Aby użyć przestrzeni kodu, utwórz wstępnie skonfigurowany element GitHub Codespace za pomocą tego linku tworzenia usługi Codespace.

Utworzenie i skonfigurowanie przestrzeni kodu w usłudze GitHub trwa kilka minut. Po zakończeniu procesu zobaczysz pliki kodu dla ćwiczenia. Kod do użycia w pozostałej części tego modułu znajduje się w katalogu /dotnet-resiliency .

Aby użyć programu Visual Studio Code, sklonuj https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative repozytorium na komputer lokalny. Następnie:

  1. Zainstaluj wszystkie wymagania systemowe, aby uruchomić kontener deweloperski w programie Visual Studio Code.
  2. Upewnij się, że platforma Docker jest uruchomiona.
  3. W nowym oknie programu Visual Studio Code otwórz folder sklonowanego repozytorium
  4. Naciśnij klawisze Ctrl+Shift+P, aby otworzyć paletę poleceń.
  5. Wyszukiwanie: Tworzenie kontenerów: >ponowne kompilowanie i ponowne otwieranie w kontenerze
  6. Wybierz pozycję eShopLite — dotnet-resiliency z listy rozwijanej. Program Visual Studio Code tworzy kontener dewelopera lokalnie.

Skompiluj i uruchom aplikację

  1. W dolnym panelu wybierz kartę TERMINAL i uruchom następujące polecenie, aby przejść do katalogu głównego kodu:

    cd dotnet-resiliency
    
  2. Uruchom następujące polecenie, aby skompilować obrazy aplikacji eShop:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Po zakończeniu kompilacji uruchom następujące polecenie, aby uruchomić aplikację:

    docker compose up
    
  4. W dolnym panelu wybierz kartę PORTY, a następnie w kolumnie Adres przekazany w tabeli wybierz ikonę Otwórz w przeglądarce dla portu frontonu (32000).

    Jeśli używasz aplikacji lokalnie, otwórz okno przeglądarki, aby wyświetlić http://localhost:32000/products.

  5. Aplikacja eShop powinna być uruchomiona. Wybierz element menu Produkty. Powinna zostać wyświetlona lista produktów.

    Zrzut ekranu przedstawiający aplikację eShop działającą w przeglądarce.

Testowanie bieżącej odporności

Zatrzymaj usługę produktu, aby zobaczyć, co się stanie z aplikacją.

  1. Wróć do przestrzeni kodu, a na karcie TERMINAL wybierz pozycję + , aby otworzyć nowy terminal powłoki bash.

  2. Uruchom następujące polecenie platformy Docker, aby wyświetlić listę uruchomionych kontenerów:

    docker ps
    

    Powinna zostać wyświetlona lista aktualnie uruchomionych kontenerów, na przykład:

    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. Wyszukaj identyfikator KONTENERa dla kontenera productservice . W powyższym przykładzie identyfikator to 6ba80f3c7ab0.

  4. Zatrzymaj usługę produktu za pomocą tego polecenia platformy Docker:

    docker stop <CONTAINER ID>
    

    <CONTAINER ID> Gdzie znajduje się identyfikator znaleziony w poprzednim kroku. Na przykład:

    docker stop 6ba80f3c7ab0
    
  5. Wróć do karty przeglądarki z uruchomioną aplikacją i odśwież stronę. Powinien zostać wyświetlony komunikat o błędzie:

    Wystąpił problem podczas ładowania naszych produktów. Spróbuj ponownie później.

  6. Wróć do przestrzeni kodu, a w terminalu wybierz terminal platformy Docker i naciśnij klawisze Ctrl+C, aby zatrzymać aplikację. Powinien zostać wyświetlony następujący ekran:

    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
    

Dodawanie odporności do aplikacji

Pierwszymi krokami umożliwiającymi zwiększenie odporności aplikacji jest dodanie Microsoft.Extensions.Http.Resilience pakietu NuGet do projektu. Następnie można go użyć w Program.cs.

Dodaj pakiet Microsoft.Extensions.Http.Resilience

  1. W obszarze codespace na karcie TERMINAL przejdź do folderu Projektu Store :

    cd Store
    
  2. Uruchom następujące polecenie, aby dodać pakiet NuGet odporności:

    dotnet add package Microsoft.Extensions.Http.Resilience
    

    Uruchomienie tego polecenia z poziomu terminalu w folderze projektu apps powoduje dodanie odwołania do pakietu do pliku projektu Store.csproj .

  3. Na pasku bocznym EKSPLORATORa wybierz pozycję Program.cs.

  4. W górnej części pliku dodaj następującą instrukcję using:

    using Microsoft.Extensions.Http.Resilience;
    

Dodawanie standardowej strategii odporności

  1. W wierszu 13 przed ;dodaj następujący kod:

    .AddStandardResilienceHandler()
    

    Twój kod powinien wyglądać następująco:

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

    Powyższy kod dodaje standardową procedurę obsługi odporności do klienta HTTPClient. Procedura obsługi używa wszystkich domyślnych ustawień standardowej strategii odporności.

    Do aplikacji nie są potrzebne żadne inne zmiany kodu. Uruchomimy aplikację i przetestujmy odporność.

  2. Uruchom następujące polecenia, aby ponownie skompilować aplikację eShop:

    cd ..
    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Po zakończeniu kompilacji uruchom następujące polecenie, aby uruchomić aplikację:

    docker compose up
    
  4. Wróć do karty przeglądarki z uruchomioną aplikacją i odśwież stronę produktu. Powinna zostać wyświetlona lista produktów.

  5. Wróć do przestrzeni kodu, a na karcie TERMINAL wybierz drugi terminal powłoki bash. Skopiuj identyfikator KONTENERa dla kontenera productservice .

  6. Uruchom ponownie polecenie docker stop:

    docker stop <CONTAINER ID>
    
  7. Wróć do karty przeglądarki z uruchomioną aplikacją i odśwież stronę produktu. Tym razem powinno upłynąć nieco dłużej, dopóki nie zostanie wyświetlony komunikat o błędzie aplikacji:

    Wystąpił problem podczas ładowania naszych produktów. Spróbuj ponownie później.

    Sprawdźmy dzienniki, aby sprawdzić, czy nasza strategia odporności działa.

  8. Wróć do przestrzeni kodu, a na karcie TERMINAL wybierz terminal platformy Docker .

  9. W terminalu naciśnij klawisze Ctrl+C , aby zatrzymać działanie aplikacji.

  10. W komunikatach dziennika przewiń w górę do momentu znalezienia odwołań do usługi 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'
    

    Powinien zostać wyświetlonych wiele takich komunikatów; każda z nich to próba ponawiania próby. Powyższy komunikat pokazuje drugą próbę i czas wykonania.

Konfigurowanie strategii odporności

Gdy dodasz odporność do aplikacji, równoważysz potrzebę szybkiego reagowania na użytkowników, a konieczność nie przeciążenia żadnych usług zaplecza. Tylko ty możesz zdecydować, czy opcje domyślne spełniają Twoje potrzeby firmy.

W tym przykładzie chcesz, aby usługa sklepu czekała nieco dłużej, aby dać usłudze sklepu szansę na odzyskanie.

  1. W oknie kodu dla Program.cs zmień kod w wierszu 13 na:

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

    Powyższy kod zmienia domyślną strategię ponawiania prób na maksymalną liczbę wycofań do siedmiu. Pamiętaj, że strategia jest wykładniczym wycofywaniem, więc łączny czas wynosi około 5 minut.

  2. Zatrzymaj platformę Docker za pomocą klawiszy Ctrl+C. Następnie uruchom następujące polecenie, aby ponownie skompilować aplikację eShop:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Po zakończeniu kompilacji uruchom następujące polecenie, aby uruchomić aplikację:

    docker compose up
    

    Zatrzymaj kontener usługi zaplecza w terminalu powłoki bash i odśwież aplikację eShop. Zwróć uwagę, że wyświetlenie komunikatu o błędzie trwa dłużej. Jeśli jednak sprawdzisz dzienniki, zobaczysz, że strategia ponawiania prób została ponowiona pięć razy. Ostatni komunikat z polly to:

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

    Powyższy komunikat informuje, że łączny limit czasu żądania uniemożliwia osiągnięcie maksymalnej liczby ponownych prób. Problem można rozwiązać, zwiększając łączny limit czasu żądania.

  4. W terminalu naciśnij klawisze Ctrl+C , aby zatrzymać aplikację.

  5. W oknie kodu dla Program.cs zmień kod w wierszu 13 na:

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

    Powyższy kod zmienia łączny limit czasu żądania na 260 sekund, co jest teraz dłuższe niż strategia ponawiania prób.

    Dzięki tym zmianom należy mieć wystarczająco dużo czasu, aby uruchomić aplikację, zatrzymać usługę produktu, sprawdzić dzienniki terminalu pod kątem ponownych prób, odświeżyć sklep eShop, aby wyświetlić komunikat ładowania, a następnie ponownie uruchomić usługę produktu, aby pomyślnie wyświetlić listę produktów.

  6. Uruchom następujące polecenie, aby ponownie skompilować aplikację eShop:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  7. Po zakończeniu kompilacji uruchom następujące polecenie, aby uruchomić aplikację:

    docker compose up
    

Testowanie nowych opcji odporności

Aby ułatwić testowanie aplikacji w kontenerze, użyj rozszerzenia platformy Docker. Rozszerzenie udostępnia graficzny interfejs użytkownika do wyświetlania i kontrolowania stanu kontenerów.

  1. W menu po lewej stronie wybierz ikonę platformy Docker .

    Zrzut ekranu rozszerzenia platformy Docker przedstawiający sposób zatrzymywania usługi produktów.

  2. W panelu DOCKER w obszarze KONTENERY kliknij prawym przyciskiem myszy kontener products i wybierz pozycję Zatrzymaj.

  3. Wróć do karty przeglądarki z uruchomioną aplikacją i odśwież stronę produktu. Powinien zostać wyświetlony komunikat Trwa ładowanie...

  4. Wróć do przestrzeni kodu, a następnie na karcie TERMINAL wybierz terminal platformy Docker . Strategia odporności działa.

  5. W panelu DOCKER w obszarze KONTENERY kliknij prawym przyciskiem myszy kontener products i wybierz polecenie Uruchom.

  6. Wróć do karty przeglądarki z uruchomioną aplikacją. Poczekaj, a aplikacja powinna odzyskać listę produktów.

  7. W terminalu zatrzymaj platformę Docker za pomocą klawiszy Ctrl+C.