練習 - 實作應用程式復原

已完成

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. 返回您的 Codespace,然後在 [終端機] 索引標籤中選取 + 以開啟新的 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. 返回您的 Codespace,然後在 [終端] 中選取 [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 中,於 [終端機] 索引標籤上,瀏覽至 [市集] 專案資料夾:

    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. 返回您的 Codespace,然後在 [終端機] 索引標籤中選取第二個 Bash 終端機。 複製 productservice 容器的容器識別碼。

  6. 重新執行 docker stop 命令:

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

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

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

  8. 返回您的 Codespace,然後在 [終端機] 索引標籤中選取 [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. 返回您的 Codespace,然後在 [終端] 分頁中選取 [Docker] 終端。 復原策略正在運作中。

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

  6. 返回執行應用程式的瀏覽器分頁。 稍候片刻,應用程式應該重新顯示產品清單。

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