使用 Polly 實現複雜策略(超時重試)

1、背景

第一次接觸 Polly 仍是在作某個微服務系統的時候,那時只會使用單一的超時策略與重試策略,更加高級的特性就沒有再進行學習了。最近開爲某個客戶開發 PC 端的上位機的時候,客戶有個需求,在發起請求以後若是 5 秒鐘沒有響應則進行重試,總共能夠重試 3 次,若是 3 次請求都未返回數據,就視爲請求失敗。html

關於 Polly 的高級用法能夠參考官方的 Wiki 文檔便可,國內也有不少優秀的介紹文章,例如 這篇這篇git

2、思路

查閱了 Polly 的官方文檔以後,發現 Polly 提供了策略組合功能,每一個 Policy 實例均可以調用其 Wrap() 方法與另一個策略進行組合。github

或者是經過 Policy 靜態類提供的 Warp() 靜態方法來指定須要組合的兩個策略。異步

根據需求描述來看,咱們須要用到超時策略和重試策略,只要將其組合便可。不過這裏須要注意一個坑,即他們的組合順序。async

正確的組合順序應該是 重試策略.Warp(超時策略) ,而不是 超時策略.Warp(重試策略) 。這是由於在超時以後 Polly 會拋出 TimeoutRejectedException 異常,在重試策略捕獲到該異常以後,就會開始重試操做,即後面組合策略的 ExecuteAsync() 方法接收的委託。微服務

3、實現

首先咱們定義一個方法,該方法用於組合策略(超時+重試),由於我這裏是傳入的異步委託操做,因此返回的是 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 "超時";
    }
}
相關文章
相關標籤/搜索