練習 - 實施應用程式韌性
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 存放庫複製到本機電腦。 然後:
- 安裝任何系統要求,以在 Visual Studio Code 中執行開發容器。
- 請確保 Docker 正在運行。
- 在新的 Visual Studio Code 視窗中,開啟複製存放庫的資料夾
- 按下 Ctrl+Shift+P,以開啟命令選擇區。
- 搜尋:>開發容器:重建並在容器中重新開啟
- 從下拉式清單中選取 [eShopLite - dotnet-resiliency ]。 Visual Studio Code 會在本機上建立您的開發容器。
建置並執行應用程式
在底部面板中,選取終端機索引標籤,然後執行下列命令以切換到原始碼根目錄:
cd dotnet-resiliency執行下列命令來建置 eShop 應用程式映像:
dotnet publish /p:PublishProfile=DefaultContainer建置完成後,請執行下列命令來啟動應用程式:
docker compose up在底部面板中,選取 [埠] 索引標籤,然後在數據表的 [轉寄位址] 欄中,選取前端 (32000) 埠的 [在瀏覽器中開啟] 圖示。
如果您要在本機執行應用程式,請開啟瀏覽器視窗以檢視
http://localhost:32000/products。eShop 應用程式應該是正在運行中。 選取 [ 產品 ] 功能表項,您應該會看到產品清單。
測試目前的復原能力
停止產品服務以查看應用程式會發生什麼事。
返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中選取 + 以開啟新的Bash終端機。
執行下列 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尋找 productservice 容器的容器標識碼。 在上述範例中,標識碼為 6ba80f3c7ab0。
使用下列 docker 命令停止您的產品服務:
docker stop <CONTAINER ID><CONTAINER ID>其中 是您在上一個步驟中找到的標識碼。 例如:docker stop 6ba80f3c7ab0返回執行應用程式的瀏覽器索引標籤,然後重新整理頁面。 您應該會看到錯誤訊息:
載入產品時發生問題。 請稍後再試一次。
返回您的程式代碼空間,然後在 終端 機中選取 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 套件
在您的 codespace 中,於 TERMINAL 索引標籤上,導航至 Store 專案資料夾:
cd Store執行下列命令以新增復原 NuGet 套件:
dotnet add package Microsoft.Extensions.Http.Resilience從應用程式項目資料夾中的終端機執行此命令,會將套件參考新增至 Store.csproj 項目檔。
在 [總管] 提要欄位中,選取 [Program.cs]。
在檔案頂端新增下列 using 陳述式:
using Microsoft.Extensions.Http.Resilience;
新增標準復原策略
在行 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。 處理程式會使用標準復原策略的所有預設設定。
您的應用程式不需要其他程式代碼變更。 讓我們執行應用程式並測試復原能力。
執行下列命令以重建 eShop 應用程式:
cd .. dotnet publish /p:PublishProfile=DefaultContainer建置完成時,請執行下列命令來啟動應用程式:
docker compose up返回執行應用程式的瀏覽器索引標籤,然後重新整理產品頁面。 您應該會看到產品清單。
返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中選取第二個Bash終端機。 複製 productservice 容器的容器標識碼。
重新執行 docker stop 命令:
docker stop <CONTAINER ID>返回執行應用程式的瀏覽器索引標籤,然後重新整理產品頁面。 這一次,可能稍微長一點才會看到應用程式的錯誤訊息:
載入產品時發生問題。 請稍後再試一次。
讓我們檢查記錄,以查看我們的復原策略是否正常運作。
返回您的程式代碼空間,然後在 [ 終端機 ] 索引標籤中選取 Docker 終端機。
在終端機中,按 Ctrl+C 以停止應用程式執行。
在記錄訊息中,向上捲動,直到您找到 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'您應該會看到許多類似這樣的訊息;每一個都是重試嘗試。 上述訊息會顯示第二次嘗試,以及執行所需的時間。
設定復原策略
當您將復原功能新增至應用程式時,您會平衡快速回應使用者的需求,而不需要多載任何後端服務。 只有您可以決定預設選項是否符合您的企業需求。
在此範例中,您想要讓市集服務等候更長的時間,讓市集服務有機會復原。
在Program.cs的程式代碼視窗中,將第13行的程式代碼變更為:
.AddStandardResilienceHandler(options => { options.Retry.MaxRetryAttempts = 7; });上述程式代碼會將重試策略的預設值變更為最多淘汰次數為 7。 請記住,策略是指數退避策略,因此總時間約為 5 分鐘。
使用 Ctrl+C 停止 Docker 運行。 然後執行下列命令來重建 eShop 應用程式:
dotnet publish /p:PublishProfile=DefaultContainer建置完成時,請執行下列命令來啟動應用程式:
docker compose up停止 Bash 終端機中的後端服務容器,然後刷新 eShop。 請注意,看到錯誤訊息需要較長的時間。 不過,如果您檢查記錄,您可以看到重試策略只會重試五次。 Polly 的最後一則訊息為:
Polly.Timeout.TimeoutRejectedException: The operation didn't complete within the allowed timeout of '00:00:30'.上述訊息告訴您,要求逾時總計會避免達到重試次數上限。 您可以藉由增加要求總逾時來修正問題。
在終端機中,按 Ctrl+C 以停止應用程式。
在Program.cs的程式代碼視窗中,將第13行的程式代碼變更為:
.AddStandardResilienceHandler(options => { options.Retry.RetryCount = 7; options.TotalRequestTimeout = new HttpTimeoutStrategyOptions { Timeout = TimeSpan.FromMinutes(5) }; });上述程式代碼會將要求總逾時變更為 260 秒,現在比重試策略還長。
有了這些變更,您應該有足夠的時間執行應用程式、停止產品服務、檢查終端機記錄是否有重試嘗試、重新整理 eShop 以查看載入訊息,最後重新啟動產品服務以成功查看產品清單。
執行下列命令以重建 eShop 應用程式:
dotnet publish /p:PublishProfile=DefaultContainer建置完成時,請執行下列命令來啟動應用程式:
docker compose up
測試新的復原選項
若要協助測試容器中的應用程式,請使用 Docker 擴充功能。 延伸模組提供 GUI 來檢視及控制容器的狀態。
