第一次接觸 Polly 仍是在作某個微服務系統的時候,那時只會使用單一的超時策略與重試策略,更加高級的特性就沒有再進行學習了。最近開爲某個客戶開發 PC 端的上位機的時候,客戶有個需求,在發起請求以後若是 5 秒鐘沒有響應則進行重試,總共能夠重試 3 次,若是 3 次請求都未返回數據,就視爲請求失敗。html
關於 Polly 的高級用法能夠參考官方的 Wiki 文檔便可,國內也有不少優秀的介紹文章,例如 這篇 和 這篇。git
查閱了 Polly 的官方文檔以後,發現 Polly 提供了策略組合功能,每一個 Policy 實例均可以調用其 Wrap()
方法與另一個策略進行組合。github
或者是經過 Policy
靜態類提供的 Warp()
靜態方法來指定須要組合的兩個策略。異步
根據需求描述來看,咱們須要用到超時策略和重試策略,只要將其組合便可。不過這裏須要注意一個坑,即他們的組合順序。async
正確的組合順序應該是 重試策略.Warp(超時策略) ,而不是 超時策略.Warp(重試策略) 。這是由於在超時以後 Polly 會拋出 TimeoutRejectedException
異常,在重試策略捕獲到該異常以後,就會開始重試操做,即後面組合策略的 ExecuteAsync()
方法接收的委託。微服務
首先咱們定義一個方法,該方法用於組合策略(超時+重試),由於我這裏是傳入的異步委託操做,因此返回的是 AsyncPolicy
對象。學習
private AsyncPolicyWrap BuildTimeoutRetryPolicy(string msg) { // 超時策略,執行目標委託超過 5 秒則視爲超時,拋出異常。 var timeoutPolicy = Policy.TimeoutAsync(5); // 重試策略,重試 2 次,每次打印信息。 var retryPolicy = Policy.Handle<TimeoutRejectedException>().RetryAsync(2, (exception, i) => { Console.WriteLine("開始第 i 次重試..."); }); return retryPolicy.WrapAsync(timeoutPolicy); }
定義好策略以後,就是咱們的實際應用了。這裏說明一下執行邏輯,當第一次請求的時候若是發生了超時的狀況,則進入重試策略,重試兩次,當最後一次仍然拋出 TimeoutRejectedException
異常,則重試策略再也不捕獲,直接將異常拋出給調用者。ui
private async Task<string> GetResult(AsyncPolicyWrap policy) { try { return await policy.ExecuteAsync(() => SendDataAsync(sendProtocol)); } catch (TimeoutRejectedException) { return "超時"; } }