歡迎光臨
每天分享高質量文章

基於.NET的彈性及瞬間錯誤處理庫Polly

作者:LamondLu

連結:https://www.cnblogs.com/lwqlun/p/8119856.html

什麼是Polly?

Polly是一款基於.NET的彈性及瞬間錯誤處理庫, 它允許開發人員以順暢及執行緒安全的方式執行重試(Retry),斷路器(Circuit),超時(Timeout),隔板隔離(Bulkhead Isolation)及後背策略(Fallback)。

 

Polly適用於.NET 4.0, .NET 4.5及.NET Standard 1.1(改寫.NET Core, Mono, Xamarin.IOS, Xamarin.Android, UWP, WP 8.1+)。

安裝Polly

.NET 4.0版本

 

Install-Package Polly.Net40Async

 

.NET 4.5及以上版本, .Net Standard 1.1

 

Install-Package Polly

彈性策略

Polly提供多種彈性策略。

 

重試策略

 

前提

 

程式會產生許多瞬時故障,但是在一定時間延遲之後,程式會自動糾正故障。

 

實現效果

 

允許配置自動重試。

 

斷路器策略

 

前提

 

當系統發生嚴重故障時,快速響應請求失敗比讓使用者等待要好。

避免故障系統過載有助於恢復系統。

 

實現效果

 

當系統錯誤超過預配置的數量,系統將斷路一段時間。

 

超時策略

 

前提

 

超出一定時間的等待,想要得到正確的結果是不太可能的。

 

實現效果

 

保證呼叫者不需要等待超時。

 

隔板隔離

 

前提

當行程出現故障,多個失敗的請求很容易佔滿伺服器資源(執行緒/CPU)。


一個處於故障狀態的下游系統,也會導致其上游系統故障。

 

實現效果

 

將嚴格管控故障行程,使其使用固定大小的資源池,隔離他們對其他行程的潛在影響

 

快取策略

 

前提

 

一定比例的請求可能是相似的。

 

實現效果

 

從快取中提供已知的響應。
當第一次讀取的時候,將響應自動快取起來。

 

後備策略

前提

 

當故障依然存在的時候,你打算做什麼。

 

實現效果

 

當程式依然發生故障時,執行指定操作。

 

包裝策略

 

前提

 

不同的故障需要不同的策略。包裝策略即組合策略。

 

實現效果

 

允許靈活的將以上任意幾種策略組合在一起。

如何使用Polly進行故障/異常處理?

Polly處理故障/異常有以下幾個步驟。

 

  1. 指定處理的異常/故障型別
  2. [可選] 指定處理的異常傳回值
  3. 指定處理策略
  4. 執行策略

 

指定處理異常/故障的型別

 

Polly使用Policy類的泛型方法Handle指定Polly需要處理異常/故障的型別。

 

指定單個異常型別

 

Policy.Handle<DivideByZeroException>()

 

指定帶條件的異常型別

 

Policy.Handle(ex => ex.Number == 1205)

 

Polly也支援指定多種異常/故障型別, 這裡需要使用Or方法

 

Policy.Handle<DivideByZeroException>().Or<ArgumentException>()

指定多個帶條件的異常型別

 

Policy
   .Handle<SqlException>(ex =ex.Number == 1205)
   .Or<ArgumentException>(ex =ex.ParamName == "example")

 

Polly也支援指定內部異常

 

Policy
    .HandleInner()
    .OrInner(ex => ex.CancellationToken == myToken)

 

指定處理的異常傳回值

 

Polly除了支援處理異常/故障型別,還支援處理異常傳回值。所謂的處理異常結果,就是當Polly監控的方法,傳回某些特定結果時, Polly會觸發異常/故障處理策略。

 

Polly使用Policy類的泛型方法HandleResult制定Polly需要處理的異常結果.

 

指定觸發異常/故障處理策略的傳回值

 

例如:當某個方法的傳回值型別是HttpResposneMessage, 並且傳回值的StatusCode是NotFound時,觸發異常/故障處理策略。

 

Policy
.HandleResult(r => r.StatusCode == HttpStatusCode.NotFound)

 

指定多個傳回值

 

Policy
    .HandleResult(r => r.StatusCode == HttpStatusCode.InternalServerError)
    .OrResult(r => r.StatusCode == HttpStatusCode.BadGateway)

 

同時指定異常型別和傳回值

 

HttpStatusCode[] httpStatusCodesWorthRetrying = {
    HttpStatusCode.RequestTimeout, // 408
    HttpStatusCode.InternalServerError, // 500
    HttpStatusCode.BadGateway, // 502
    HttpStatusCode.ServiceUnavailable, // 503
    HttpStatusCode.GatewayTimeout // 504
}; 
HttpResponseMessage result = Policy
    .Handle()
    .OrResult(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode))

 

指定異常處理策略

 

重試策略

 

重試一次

 

Policy
    .Handle<DivideByZeroException>()
    .Retry()

 

重試多次

 

Policy
    .Handle<DivideByZeroException>()
    .Retry(3)

 

重試多次,每次重試觸發一個行為

 

Policy
    .Handle()
    .Retry(3(exception, retryCount) =>
    {
        // do something 
    });

 

永久重試(直到成功)

 

永久重試

 

Policy
    .Handle<DivideByZeroException>()
    .RetryForever()

 

永久重試,每次重試觸發一個行為

 

Policy
    .Handle()
    .RetryForever(exception =>
    {
            // do something       
    });

 

等待並重試

 

指定每個重試的間隔時間

 

Policy
    .Handle()
    .WaitAndRetry(new[]
    {
        TimeSpan.FromSeconds(1),
        TimeSpan.FromSeconds(2),
        TimeSpan.FromSeconds(3)
    });

 

在這個例子如果第一次出現異常,會在1秒後重試,如果依然出現異常,會在再次出現異常後2秒繼續重試,以此類推,下次異常後3秒繼續重試

 

每次重試,觸發一個行為

 

Policy
    .Handle()
    .WaitAndRetry(new[]
    {
      TimeSpan.FromSeconds(1),
      TimeSpan.FromSeconds(2),
      TimeSpan.FromSeconds(3)
    }, (exception, timeSpan) => {
      // do something    
    }); 

 

斷路器策略

 

在發生指定次數的異常/故障之後,斷開迴路

 

Policy
    .Handle<DivideByZeroException>()
    .CircuitBreaker(2, TimeSpan.FromMinutes(1));

 

發生2次異常之後,斷開迴路1分鐘

 

Action onBreak = (exception, timespan) => { ... };
Action onReset = () => { ... };
CircuitBreakerPolicy breaker = Policy
    .Handle()
    .CircuitBreaker(2, TimeSpan.FromMinutes(1), onBreak, onReset);

 

發生2次異常之後,斷開迴路1分鐘, 在觸發斷路時觸發onBreak方法,當重置斷路器時,觸發onReset方法

 

後備策略

 

Policy
    .Handle<Whatever>()
    .Fallback<UserAvatar>(UserAvatar.Blank)

 

當程式觸發異常/故障後,傳回一個備用值

 

Policy
    .Handle()
    .Fallback(() => UserAvatar.GetRandomAvatar())

 

當程式觸發異常/故障後,使用一個方法傳回一個備用值

 

Policy
   .Handle()
   .Fallback(UserAvatar.Blank, onFallback: (exception, context) => 
    {
        // do something
    });

 

當程式觸發異常/故障後,傳回一個備用值,並觸發一個方法

 

Policy
   .Handle()
   .Fallback(UserAvatar.Blank, onFallback: (exception, context) => 
    {
        // do something
    });

 

執行策略

 

Polly將監控DoSomething方法,如果發生DivideByZeroException異常,就使用重試策略

 

var policy = Policy
              .Handle()
              .Retry();

policy.Execute(() => DoSomething());

 

向Polly背景關係中傳遞任意值

 

var policy = Policy
    .Handle()
    .Retry(3(exception, retryCount, context) =>
    {
        var methodThatRaisedException = context["methodName"];
        Log(exception, methodThatRaisedException);
});

policy.Execute(
    () => DoSomething(),
    new Dictionary() {{ "methodName""some method" }}
);
已同步到看一看
贊(0)

分享創造快樂