Polly簡介 — 2. 彈性策略


和故障處理策略不同的是,彈性策略並不是針對委托執行過程中的異常進行處理,而是改變委托本身的行為,因此彈性策略並沒有故障定義這一過程,它的處理流程為:

  1. 定義策略
  2. 應用策略

Polly對彈性策略也做了不少支持,本文這里就簡單的介紹一下。

 

彈性策略:超時(Timeout)

超時策略用於控制委托的運行時間,如果達到指定時間還沒有運行,則觸發超時異常。

Policy.Timeout(TimeSpan.FromSeconds(3), TimeoutStrategy.Pessimistic);

超時策略常見的重載版本有如下幾個:

Policy.Timeout(300);
Policy.Timeout(TimeSpan.FromMilliseconds(3));
Policy.Timeout(() => TimeSpan.FromSeconds(3));
Policy.Timeout(TimeSpan.FromSeconds(3), TimeoutStrategy.Optimistic);

超時策略:

Polly支持兩種超時策略:

  • TimeoutStrategy.Pessimistic: 悲觀模式
    當委托到達指定時間沒有返回時,不繼續等待委托完成,並拋超時TimeoutRejectedException異常。
  • TimeoutStrategy.Optimistic:樂觀模式
    這個模式依賴於 co-operative cancellation,只是觸發CancellationTokenSource.Cancel函數,需要等待委托自行終止操作。

其中悲觀模式比較容易使用,因為它不需要在委托額外的操作,但由於它本身無法控制委托的運行,函數本身並不知道自己被外圍策略取消了,也無法在超時的時候中斷后續行為。因此用起來反而還不是那么實用。

一個樂觀模式的的策略示例如下:

var policy = Policy.Timeout(300);
var cts = new CancellationTokenSource();
policy.Execute(ct =>
{
    for (int i = 0; i < 1000; i++)
    {
        Thread.Sleep(100);
        ct.ThrowIfCancellationRequested();
    }
}, cts.Token);

復合策略:

在日常的使用中,僅僅只有超時往往是並不夠的,很多時候還需要和重試等其它故障處理策略一起使用,如:

Policy.Handle<TimeoutRejectedException>()
    .Retry(3)
    .Wrap(Policy.Timeout(3, TimeoutStrategy.Pessimistic));

 

彈性策略:無操作(NoOp)

在開發過程中,處於測試或定位問題時的需要,有時我們也需要一個沒有任何行為的策略,Polly系統默認提供了一個.

Policy.NoOp();

這個啥都沒干,也沒啥好介紹的了。

 

彈性策略:緩存(Cache)

有的時候,數據更新並不是頻繁的,此時可以使用緩存策略減少對服務的訪問,提高系統性能:

var memoryCacheProvider =
    new Polly.Caching.MemoryCache.MemoryCacheProvider(new System.Runtime.Caching.MemoryCache("cache"));

var cachePolicy = Policy.Cache(memoryCacheProvider, TimeSpan.FromMinutes(5));

//Context.ExecutionKey
就是cachekey
var context = new Context("cache_key");
for (int i = 0; i < 3; i++)
{
    var cache = cachePolicy.Execute(_ =>
    {
        Console.WriteLine("get value");
        return 3;
    }, context);
    Console.WriteLine(cache);
}

PS:這個示例使用了MemoryCache,需要使用Nuget安裝Polly.Caching.MemoryCache程序包,以及添加System.Runtime.Caching的引用。

從運行結果可以看到,雖然三次執行都有結果,但系統只有第一次才需要執行函數,剩下兩次都是直接從緩存中獲取的結果。

系統也提供了多種不同的過期策略:

Policy.Cache(memoryCacheProvider, new AbsoluteTtl(DateTimeOffset.Now.Date.AddDays(1)));
Policy.Cache(memoryCacheProvider, new SlidingTtl(TimeSpan.FromMinutes(5)));

對於布式緩存,Polly也有默認的實現,只需要安裝Polly.Caching.IdistributedCache程序包即可,它提供了SqlServer和Redis的支持。

關於Cache的更多內容,可以參考官方文檔:Cache

 

彈性策略:艙壁隔離(Bulkhead Isolation)

艙壁隔離是一種並發控制的行為,並發控制是一個比較常見的模式,Polly也提供了這方面的支持,如:

//該策略下最多只有12個任務並發執行
Policy.Bulkhead(12);

超過了並發數的任務會拋BulkheadRejectedException,如果要放在隊列中等待,Polly也提供了等待隊列的支持:

Policy.Bulkhead(12, 100);

這種方式下,有12個並發任務,每個任務維持着一個並發隊列,每個隊列可以自持最大100個任務。

不過,和微軟自己的DataFlow模塊比起來,感覺Polly模塊的並發控制的功能還是比較弱的。不過這也它本身的應用場景也相關,如果需要更強大的策略,也可以自行封裝。

 

彈性策略:策略封裝(PolicyWrap)

我們可以通過PolicyWrap的方式,封裝出一個更加強大的策略:

var fallback = Policy<int>.Handle<TimeoutException>().Fallback(100);
var retry = Policy<int>.Handle<TimeoutException>().Retry(2);

Policy.Wrap(fallback, retry);

這個策略就是將Retry和Fallback組合起來,形成一個retry and fallback的策略,也可以寫成如下形式:

var retryAndFallback = fallback.Wrap(retry);

當執行這個新策略時:

retryAndFallback.Execute(DoSomething);

等價於執行:

fallback.Execute(()=> retry.Execute(DoSomething));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM