練習 - 實施應用程式韌性

已完成

eShop 專案有兩個服務,可使用 HTTP 要求彼此通訊。 服務 Store 會呼叫 Product 服務,以取得可供購買之所有目前產品的清單。

應用程式的目前版本沒有復原處理。 Product如果服務無法使用,服務Store會傳回錯誤給客戶,並要求他們稍後再試一次。 此行為不是良好的用戶體驗。

您的經理要求您將復原功能新增至應用程式,讓 Store 服務在失敗時重試後端服務呼叫。

在此練習中,您會將復原功能新增至現有的雲端原生應用程式,並測試您的修正程式。

開啟開發環境

您可以選擇使用裝載本練習的 GitHub Codespace,或在 Visual Studio Code 本機上完成該練習。

若要使用 Codespace,請使用 此 Codespace 建立連結 來建立預先設定的 GitHub Codespace。

GitHub 需要幾分鐘的時間才能建立及設定 Codespace。 程式完成時,您會看到練習的程式代碼檔案。 此課程模組其餘部分所使用的程式代碼位於 /dotnet-resiliency 目錄中。

若要使用 Visual Studio Code,請將 https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative 存放庫複製到本機電腦。 然後:

  1. 安裝任何系統要求,以在 Visual Studio Code 中執行開發容器。
  2. 請確保 Docker 正在運行。
  3. 在新的 Visual Studio Code 視窗中,開啟複製存放庫的資料夾
  4. 按下 Ctrl+Shift+P,以開啟命令選擇區。
  5. 搜尋:>開發容器:重建並在容器中重新開啟
  6. 從下拉式清單中選取 [eShopLite - dotnet-resiliency ]。 Visual Studio Code 會在本機上建立您的開發容器。

建置並執行應用程式

  1. 在底部面板中,選取終端機索引標籤,然後執行下列命令以切換到原始碼根目錄:

    cd dotnet-resiliency
    
  2. 執行下列命令來建置 eShop 應用程式映像:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. 建置完成後,請執行下列命令來啟動應用程式:

    docker compose up
    
  4. 在底部面板中,選取 [] 索引標籤,然後在數據表的 [轉寄位址] 欄中,選取前端 (32000) 埠的 [在瀏覽器中開啟] 圖示。

    如果您要在本機執行應用程式,請開啟瀏覽器視窗以檢視 http://localhost:32000/products

  5. eShop 應用程式應該是正在運行中。 選取 [ 產品 ] 功能表項,您應該會看到產品清單。

    這個螢幕快照顯示瀏覽器中執行的 eShop 應用程式。

測試目前的復原能力

停止產品服務以查看應用程式會發生什麼事。

  1. 返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中選取 + 以開啟新的Bash終端機。

  2. 執行下列 docker 命令以列出執行中的容器:

    docker ps
    

    您應該會看到目前正在執行的容器清單,例如:

    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. 尋找 productservice 容器的容器標識碼。 在上述範例中,標識碼為 6ba80f3c7ab0

  4. 使用下列 docker 命令停止您的產品服務:

    docker stop <CONTAINER ID>
    

    <CONTAINER ID>其中 是您在上一個步驟中找到的標識碼。 例如:

    docker stop 6ba80f3c7ab0
    
  5. 返回執行應用程式的瀏覽器索引標籤,然後重新整理頁面。 您應該會看到錯誤訊息:

    載入產品時發生問題。 請稍後再試一次。

  6. 返回您的程式代碼空間,然後在 終端 機中選取 Docker 終端機,然後按 Ctrl+C 以停止應用程式。 您應該會看到:

    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
    

將復原功能新增至應用程式

讓您的應用程式更具復原性的第一個步驟是將 Microsoft.Extensions.Http.Resilience NuGet 套件新增至專案。 然後,您可以在 Program.cs中使用。

新增 Microsoft.Extensions.Http.Resilience 套件

  1. 在您的 codespace 中,於 TERMINAL 索引標籤上,導航至 Store 專案資料夾:

    cd Store
    
  2. 執行下列命令以新增復原 NuGet 套件:

    dotnet add package Microsoft.Extensions.Http.Resilience
    

    從應用程式項目資料夾中的終端機執行此命令,會將套件參考新增至 Store.csproj 項目檔。

  3. 在 [總管] 提要欄位中,選取 [Program.cs]

  4. 在檔案頂端新增下列 using 陳述式:

    using Microsoft.Extensions.Http.Resilience;
    

新增標準復原策略

  1. 在行 13 的分號 ; 之前新增以下程式碼:

    .AddStandardResilienceHandler()
    

    您的程式碼看起來應該類似:

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

    上述程式代碼會將標準復原處理程式新增至 HTTPClient。 處理程式會使用標準復原策略的所有預設設定。

    您的應用程式不需要其他程式代碼變更。 讓我們執行應用程式並測試復原能力。

  2. 執行下列命令以重建 eShop 應用程式:

    cd ..
    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. 建置完成時,請執行下列命令來啟動應用程式:

    docker compose up
    
  4. 返回執行應用程式的瀏覽器索引標籤,然後重新整理產品頁面。 您應該會看到產品清單。

  5. 返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中選取第二個Bash終端機。 複製 productservice 容器的容器標識碼。

  6. 重新執行 docker stop 命令:

    docker stop <CONTAINER ID>
    
  7. 返回執行應用程式的瀏覽器索引標籤,然後重新整理產品頁面。 這一次,可能稍微長一點才會看到應用程式的錯誤訊息:

    載入產品時發生問題。 請稍後再試一次。

    讓我們檢查記錄,以查看我們的復原策略是否正常運作。

  8. 返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中選取 Docker 終端機。

  9. 在終端機中,按 Ctrl+C 以停止應用程式執行。

  10. 在記錄訊息中,向上捲動,直到您找到 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'
    

    您應該會看到許多類似這樣的訊息;每一個都是重試嘗試。 上述訊息會顯示第二次嘗試,以及執行所需的時間。

設定復原策略

當您將復原功能新增至應用程式時,您會平衡快速回應使用者的需求,而不需要多載任何後端服務。 只有您可以決定預設選項是否符合您的企業需求。

在此範例中,您想要讓市集服務等候更長的時間,讓市集服務有機會復原。

  1. 在Program.cs的程式代碼視窗中,將第13行的程式代碼變更為:

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

    上述程式代碼會將重試策略的預設值變更為最多淘汰次數為 7。 請記住,策略是指數退避策略,因此總時間約為 5 分鐘。

  2. 使用 Ctrl+C 停止 Docker 運行。 然後執行下列命令來重建 eShop 應用程式:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. 建置完成時,請執行下列命令來啟動應用程式:

    docker compose up
    

    停止 Bash 終端機中的後端服務容器,然後刷新 eShop。 請注意,看到錯誤訊息需要較長的時間。 不過,如果您檢查記錄,您可以看到重試策略只會重試五次。 Polly 的最後一則訊息為:

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

    上述訊息告訴您,要求逾時總計會避免達到重試次數上限。 您可以藉由增加要求總逾時來修正問題。

  4. 在終端機中,按 Ctrl+C 以停止應用程式。

  5. 在Program.cs的程式代碼視窗中,將第13行的程式代碼變更為:

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

    上述程式代碼會將要求總逾時變更為 260 秒,現在比重試策略還長。

    有了這些變更,您應該有足夠的時間執行應用程式、停止產品服務、檢查終端機記錄是否有重試嘗試、重新整理 eShop 以查看載入訊息,最後重新啟動產品服務以成功查看產品清單。

  6. 執行下列命令以重建 eShop 應用程式:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  7. 建置完成時,請執行下列命令來啟動應用程式:

    docker compose up
    

測試新的復原選項

若要協助測試容器中的應用程式,請使用 Docker 擴充功能。 延伸模組提供 GUI 來檢視及控制容器的狀態。

  1. 從左側功能表中,選取 Docker 圖示。

    Docker 延伸模組的螢幕快照,其中顯示如何停止產品服務。

  2. DOCKER 面板中的 [容器] 下,以滑鼠右鍵按兩下 產品 容器,然後選取 [ 停止]。

  3. 返回執行應用程式的瀏覽器索引標籤,然後重新整理產品頁面。 您應該會看到 載入... 訊息。

  4. 返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中,選取 Docker 終端機。 復原策略正在運作。

  5. DOCKER 面板中的 [容器] 下,以滑鼠右鍵按兩下 產品 容器,然後選取 [ 啟動]。

  6. 返回執行應用程式的瀏覽器索引標籤。 等候,應用程式應該復原以顯示產品清單。

  7. 在終端機中,使用 Ctrl+C 停止 Docker。