熔斷:我這裏有一根長度一米的鋼鐵,鋼鐵的熔點1000度(假設),如今我想用力把這根鋼鐵折彎,可是人的力有限達不到折彎的點,而後我使用火給鋼鐵加熱,每隔一段時間我就會嘗試一下是否能折彎,在這個過程當中我發現,隨着不斷的煅燒,折彎鋼鐵是花費的力氣越小,在這個過程出現了意外由於個人疏忽,溫度超過了鋼鐵的熔點了,致使一根變成的兩根,和我最初的目的相違背了,早知道當初我裝個報警的裝置了還能夠提想我。緩存
若是在這個例子中咱們把一根鋼鐵換成咱們程序中的接口(接口能同時承受1000的訪問),而後把火替換成咱們的接口調用者,當接口的併發超過1000這個點的時候接口將會掛掉,做爲調用者並不能控制這個點,當併發量上來的時候致使接口蹦了,爲了防止咱們的接口發生崩潰的狀況,咱們作一個報警的設置,當發生這個狀況的時候佔時切斷服務,防止服務崩潰。安全
降級:接着上一個例子:既然這個鋼鐵由於一個意外致使變成兩個,不能進行使用了,我變找了一個繩子替代一下。服務器
當咱們的服務接口發生錯誤的時候,咱們能夠找到一個替代方法進行使用。這個方法多是啓用另外一臺服務器的接口,也多是隻返回「」服務器繁忙請重試的提示「」。總之不會把一個系統級別的問題暴露給用戶,讓使用者的程序也出現問題。併發
處理熔斷降級的框架本人所知 有NetFlix的Hystrix框架和Polly框架咱們將使用Polly進行熔斷降級處理。框架
Polly的概念:Polly是一個被.net基金會支持承認的框架,Polly是一個.NET彈性和瞬態故障處理庫,容許開發人員以流暢和線程安全的方式表達策略,如重試、斷路器、超時、艙壁隔離和回退。學習
Polly的7種策略:官方文檔是這麼說的:ui
一、重試(Retry):當程序發生短暫的故障、而且故障在延遲後,能夠自動糾正的,前期是暫時的咱們能夠配置自動重試。spa
二、斷路器(Circuit-Breaker):當一個系統陷入嚴重的問題時,讓系統快速的失敗,比讓用戶一直等待着要好的多,保護一個系統不受過載的影響,能夠幫助它快速的恢復。.net
三、超時(Timeout):在等待必定的時間後,沒有返回相應的結果,保證程序不會一直等待下去,使調用者沒必要一直的等待下去。線程
四、隔離(Bulkhead Isolation):當進程出現故障的時,一臺主機中的多個失敗的進程,對資源(例如線程/CPU)的一直佔用,當下遊的系統發生故障的時候,也可能致使上游對資源的調用失敗、這兩種風險的出現都將致使更大範圍的影響、隔離策略是爲了防止「一個點的失敗致使整盤的失敗」把受到管理的操做固定在某個資源中,避免影響到其餘的資源。
五、緩存(Cache):針對相同的請求,在第一次訪問的時候將響應的數據進行緩存,再次訪問的時候直接在緩存中提供響應的數據。
六、回退(FallBack):當程序發生失敗的狀況的時候,咱們將作些什麼,定義一個在程序發生失敗的時候要執行的動做。
七、策略組合(PolicyWrap):Polly針對不一樣的故障有不一樣的策略,咱們能夠靈活的組合策略,上述的六種策略能夠靈活組合使用。
由於Polly對NetCore的友好支持,下面咱們將使用Core的控制檯對Polly的幾種策略進行簡單的演示
首先建立控制檯程序
在Nuget的控制檯中使用 Install-Package Polly 命令進行安裝
注意:在建立項目的時候命名儘可能不要使用Polly命名
Polly 每一個版本的介紹 https://www.nuget.org/packages/Polly/
執行命令進行安裝以下圖所示
首先咱們要學會而且指定但願Policy 處理的異常:
1 /* 2 *指定Policy但願策略處理的異常/錯誤 3 * 這裏只是制定Policy 處理異常的方案不作任何的處理 4 */ 5 6 //單個不加對異常加條件 7 Policy.Handle<Exception>(); 8 9 //單個對處理的異常加上條件 這裏的條件指明瞭當異常的 HResult 值爲 -2146233088 時處理異常 10 Policy.Handle<Exception>(ex => ex.HResult == -2146233088); 11 12 //多個使用Or便可 多個不加條件 13 Policy.Handle<HttpRequestException>(). 14 Or<OperationCanceledException>(); 15 16 //多個加條件 17 Policy.Handle<HttpRequestException>(ex => ex.HResult == 00000000). 18 Or<OperationCanceledException>(ex => ex.HResult == 00000000); 19 20 //多個混合加條件 21 Policy.Handle<HttpRequestException>(). 22 Or<OperationCanceledException>(ex => ex.HResult == 00000000). 23 Or<ArgumentException>(ex => ex.HResult == 00000000). 24 Or<ArgumentException>();
下面咱們指定一個但願Policy處理的異常,而且完成調用
1 /* 2 *指定Policy 處理的異常/錯誤爲 錯誤的基類 Exception 而且給異常加上條件 3 *若是條件不知足則不作任何處理 4 * 不做處理程序將會報錯 5 6 var PolicyExecute = Policy.Handle<Exception>(ex => ex.HResult == -2146233088).Fallback(() =>//動做 7 { 8 Console.WriteLine($"執行出錯監控的異常爲:Exception 異常 HResult值爲:-2146233088 "); 9 //Console.WriteLine($"執行出錯監控的異常爲:ArgumentException 異常 HResult值爲:-2147024809 "); 10 }); 11 12 //執行 13 PolicyExecute.Execute(() => 14 { 15 Console.WriteLine("********************開始執行程序**************************"); 16 //直接拋出異常(Exception) HResult值爲 -2146233088 17 throw new Exception(); 18 //throw new ArgumentException(); 19 } 20 ); 21 */
由於throw new Exception();的 HResult 的值爲
如圖所示
執行結果爲:
當咱們使用throw new ArgumentException(); 時 它的HResult 的值爲
如圖所示:
執行結果爲:
由於咱們沒有作任何的處理因此程序直接報錯
上面演示了Policy的基本用法
一、重試策略(Retry):
1 /* Policy的重試策略 Retry 2 * 若是程序發生錯誤將從新執行 3 次 3 int Count = 0; 4 var PolicyExecutes = 5 Policy<object>.Handle<Exception>(ex => ex.HResult == -2146233088) 6 .Retry(3, (ex, Index) => { 7 Console.WriteLine($"執行出錯監控的異常爲:Exception 異常 HResult值爲:-2146233088 "); 8 Console.WriteLine($"第{Index}次 Retry(重試)"); 9 } 10 ).Execute(() => 11 { 12 Console.WriteLine("********************開始執行程序**************************"); 13 Count = Count + 1; 14 if (Count > 3) 15 { 16 Console.WriteLine("執行成功"); 17 Console.WriteLine("********************結束執行程序**************************"); 18 return ""; 19 } 20 else 21 { 22 throw new Exception(); 23 } 24 25 }); 26 */
執行結果:
二、斷路器(Circuit-Breaker)
1 /*******************************************************************************************************/ 2 /* Policy的斷路器策略 Circuit-Breaker 3 * 程序首次被訪問若是連續出現三次錯誤後,將暫停3秒,三秒結束後 能夠被繼續訪問 4 * 繼續訪問時 若是第一次就出現錯誤 繼續熔斷 5 6 7 var PolicyExecutes = 8 Policy<object>.Handle<Exception>() 9 .CircuitBreaker(3, TimeSpan.FromSeconds(3)); 10 11 //模擬訪問十次 12 for (int i = 0; i < 10; i++) 13 { 14 try 15 { 16 PolicyExecutes.Execute(() => 17 { 18 Console.WriteLine("********************開始執行程序**************************"); 19 throw new Exception("異常"); 20 }); 21 } 22 catch (Exception ex) 23 { 24 Console.WriteLine($"Exception信息{i}" + ex.Message); 25 } 26 //一秒運行一次 27 Thread.Sleep(1000); 28 } 29 */
執行結果:
三、 超時策略(Timeout)
1 /*Policy的超時策略(Timeout) 2 * 程序自己沒有錯誤就是執行的時間超過了咱們制定的超時策略的時間而後程序就抓捕到超時的異常 3 4 try 5 { 6 //超時策略 7 Policy policy = Policy.Timeout(3, TimeoutStrategy.Pessimistic); 8 9 policy.Execute(() => 10 { 11 Console.WriteLine("********************開始執行程序**************************"); 12 Thread.Sleep(5000); 13 }); 14 } 15 catch (Exception ex) 16 { 17 Console.WriteLine(ex.Message); 18 } 19 */
執行結果:
四、隔離策略(Bulkhead Isolation)
1 /*Policy的隔離策略(Bulkhead Isolation) 2 * 3 //制定策略最大的併發數爲5 4 Policy PolicyExecutes = Policy.Bulkhead(5); 5 //程序運行6次 總會有一個失敗的,可是這個失敗的不會影響其餘5個的執行結果 6 for (int i = 0; i < 6; i++) 7 { 8 Task.Factory.StartNew(() => 9 { 10 try 11 { 12 PolicyExecutes.Execute(() => 13 { 14 Console.WriteLine($"********************開始執行程序**************************"); 15 }); 16 } 17 catch (Exception ex) 18 { 19 Console.WriteLine(ex.Message); 20 } 21 }); 22 } 23 */
執行結果:
五、緩存策略(Cache):
1 /*Policy 緩存策略(Cache) 2 * 控制檯不方便演示 3 * Policy.Cache 能夠指定 過時時間,絕對過時時間,滑動過時時間等 4 5 //Policy 的緩存策略的制定 6 MemoryCache memoryCache = null; 7 var PolicyExecutes = Policy.Cache(memoryCache, TimeSpan.FromMinutes(5)); 8 */
六、 回退(FallBack)
1 /*Pollcy 的回退策略(FallBack) 2 * FallBack 當主程序發生錯誤是咱們啓動備用的程序進行程序處理 3 4 var PolicyExecute = Policy.Handle<Exception>().Fallback(() => 5 { 6 Console.WriteLine($"你的程序報錯了,我是替代程序!"); 7 8 }); 9 10 //執行 11 PolicyExecute.Execute(() => 12 { 13 Console.WriteLine("********************開始執行程序**************************"); 14 throw new Exception(); 15 } 16 ); 17 */
執行結果:
七、策略組合(PolicyWrap)
PolicyWrap的上面六種策略能夠任意的組合起來使用:咱們將超時策略(Timeout)加上回退(FallBack)策略組合使用
1 //Fallback策略 2 Policy PolicyExecute = Policy.Handle<Exception>().Fallback(() => 3 { 4 Console.WriteLine($"你的程序超時了,我是替代程序!"); 5 6 }); 7 //超時策略 8 PolicyExecute = PolicyExecute.Wrap(Policy.Timeout(3, TimeoutStrategy.Pessimistic)); 9 //執行 10 PolicyExecute.Execute(() => 11 { 12 Thread.Sleep(5000); 13 } 14 );
執行結果:
OK
這些只是簡單的演示,官方文檔更加詳細。
下一篇咱們是使用 Aop 基於 AspNetCore 的過濾器 實現一下Policy 的使用。
有不足之處 但願你們指出相互學習,
本文原創:轉載請註明出處 謝謝!