1、熔斷降級的概念:
熔斷:我這裡有一根長度一米的鋼鐵,鋼鐵的熔點1000度(假設),現在我想用力把這根鋼鐵折彎,但是人的力有限達不到折彎的點,然後我使用火給鋼鐵加熱,每隔一段時間我就會嘗試一下是否能折彎,在這個過程中我發現,随着不斷的煅燒,折彎鋼鐵是花費的力氣越小,在這個過程出現了意外因為我的疏忽,溫度超過了鋼鐵的熔點了,導緻一根變成的兩根,和我最初的目的相違背了,早知道當初我裝個報警的裝置了還可以提想我。
如果在這個例子中我們把一根鋼鐵換成我們程式中的接口(接口能同時承受1000的通路),然後把火替換成我們的接口調用者,當接口的并發超過1000這個點的時候接口将會挂掉,作為調用者并不能控制這個點,當并發量上來的時候導緻接口蹦了,為了防止我們的接口發生崩潰的情況,我們做一個報警的設定,當發生這個情況的時候占時切斷服務,防止服務崩潰。
降級:接着上一個例子:既然這個鋼鐵因為一個意外導緻變成兩個,不能進行使用了,我變找了一個繩子替代一下。
當我們的服務接口發生錯誤的時候,我們可以找到一個替代方法進行使用。這個方法可能是啟用另一台伺服器的接口,也可能是隻傳回“”伺服器繁忙請重試的提示“”。總之不會把一個系統級别的問題暴露給使用者,讓使用者的程式也出現問題。
2、Polly的7中政策
處理熔斷降級的架構本人所知 有NetFlix的Hystrix架構和Polly架構我們将使用Polly進行熔斷降級處理。
Polly的概念:Polly是一個被.net基金會支援認可的架構,Polly是一個.NET彈性和瞬态故障處理庫,允許開發人員以流暢和線程安全的方式表達政策,如重試、斷路器、逾時、艙壁隔離和回退。
Polly的7種政策:官方文檔是這麼說的:
1、重試(Retry):當程式發生短暫的故障、并且故障在延遲後,可以自動糾正的,前期是暫時的我們可以配置自動重試。
2、斷路器(Circuit-Breaker):當一個系統陷入嚴重的問題時,讓系統快速的失敗,比讓使用者一直等待着要好的多,保護一個系統不受過載的影響,可以幫助它快速的恢複。
3、逾時(Timeout):在等待一定的時間後,沒有傳回相應的結果,保證程式不會一直等待下去,使調用者不必一直的等待下去。
4、隔離(Bulkhead Isolation):當程序出現故障的時,一台主機中的多個失敗的程序,對資源(例如線程/CPU)的一直占用,當下遊的系統發生故障的時候,也可能導緻上遊對資源的調用失敗、這兩種風險的出現都将導緻更大範圍的影響、隔離政策是為了防止“一個點的失敗導緻整盤的失敗”把受到管理的操作固定在某個資源中,避免影響到其他的資源。
5、緩存(Cache):針對相同的請求,在第一次通路的時候将響應的資料進行緩存,再次通路的時候直接在緩存中提供響應的資料。
6、回退(FallBack):當程式發生失敗的情況的時候,我們将做些什麼,定義一個在程式發生失敗的時候要執行的動作。
7、政策組合(PolicyWrap):Polly針對不同的故障有不同的政策,我們可以靈活的組合政策,上述的六種政策可以靈活組合使用。
3、Polly的基本用法
因為Polly對NetCore的友好支援,下面我們将使用Core的控制台對Polly的幾種政策進行簡單的示範
首先建立控制台程式
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2EzN1QzN0ATMx0yN2UzMzAjM3EjMxcDM4EDMy0CO1UzNyATMvw1NwgTMwIzLchTN1cjMwEzLcd2bsJ2Lc12bj5ycn9Gbi52YugTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
在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的基本用法
4、Polly7種政策的使用
1、重試政策(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 */
執行結果:
2、斷路器(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 */
3、 逾時政策(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 */
4、隔離政策(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 */
5、緩存政策(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 */
6、 回退(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 */
7、政策組合(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 的使用。
有不足之處 希望大家指出互相學習,
本文原創:轉載請注明出處 謝謝!
不要在自己迷茫的時候不學習