概述
很多朋友包括我,對於“八股文”可以說是比較熟練的,每次面試前都會專研不少東西,各種固定答案、專業術語都是張口就來,一個字,穩。
八股文:程序員八股文是指程序員在面試過程中經常被問到的問題,大多都有固定化、格式化的答案,俗稱為面經。
八股文是明清科舉考試的一種文體,也稱制義、制藝、時文、八比文。
八股文就是指文章的八個部分,文體有固定格式:由破題、承題、起講、入題、起股、中股、后股、束股八部分組成,題目一律出自四書五經中的原文。
后四個部分每部分有兩股排比對偶的文字,合起來共八股。
相信大家對熔斷、降級、隔離、限流、容災備份、故障轉移、異地多活等專業術語不陌生吧,或多或少都能聊上一兩句。
但是在實際開發中卻望着鍵盤發呆,不知道怎么實現,今天我們就簡單演示一下再項目當中怎么實現熔斷、降級。
實現的方式有很多,我們這里講解Polly,但是大家不要過分依賴,可以多種方式進行預演防范。
強如淘寶,在今年(2021年10月20號)20點10分左右都崩了,20點27分左右修復。
熔斷和降級概念理解
熔斷機制概念
當下游服務因訪問壓力過大而響應變慢或失敗,或者下游服務出現異常時,上游服務為了保護系統整體的可用性,可以暫時切斷對下游服務的調用。
PS:如果項目中不使用熔斷將會影響到整個系統的使用。
舉例:
家庭里有很多大功率電器(微波爐,電磁爐,電炒鍋,空調,飲水機,電熱水器、浴霸、太陽能抽水電機等),
一旦我們全部開啟大功能電器,就會造成超負荷運行引起跳閘停電,導致家里面全面停電,這就不符合用電目的,我們想哪個大功能超負荷就停哪個,不能因為局部影響全局。
這個時候我們需要在家庭總電閘下面加裝二級電閘、三級電閘.....,達到一機一閘一保護的目的(也可以多個電器安裝一個電閘)。
如果在這個例子中,把用電換成我們程序中的接口(接口能承受3000人同時訪問),然后把大功率電器替換成我們的接口調用者。
當接口的並發超過3000這個點的時候接口將會掛掉,導致服務器崩潰,作為調用者並不能控制這個點。
為了防止我們的接口發生崩潰的情況,我們做一個報警的設置,當發生這個情況的時候暫時切斷服務,防止服務崩潰(用戶量到達3000的時候,拒絕其他請求,只服務這3000以內的請求)。
降級機制概念
降級是當某個服務出現故障啟動熔斷機制后,向調用方返回一個替代響應或者規范化的錯誤響應。
舉例:
我們的程序需要發送郵件,首先調用自建郵箱發送,當自建郵箱發送失敗后調用網易郵箱發送郵件,如果網易郵箱發送失敗,那么我們就調用 QQ 郵箱發送,如果 QQ 郵箱也發送失敗,那么我們就返回發送失敗響應。
降級也可以看作服務的選擇性放棄。
例如1:上面的多個大功能電器不需要同時運行時,我們可以關閉其他電器,等待當前電器用完后在使用。
例如2:李佳琪和薇婭的直播帶貨時,平台流量優先傾斜,導致其他主播的直播間卡慢不清晰等問題,等待李佳琪薇婭直播結束后其他主播恢復正常。
例如3:李佳琪和薇婭的直播帶貨時,平台流量優先傾斜,導致其他主播的直播間卡慢不清晰等問題,等待李佳琪薇婭直播結束后其他主播恢復正常。
當服務接口發生錯誤的時候,可以找到一個替代方法進行使用。這個方法可能是啟用另一台服務器的接口,也可能是只返回“服務器繁忙請重試的提示”。總之不會把一個系統級別的問題暴露給用戶。
什么是 Polly
暫時我所了解的處理熔斷降級的框架有NetFlix的Hystrix框架和Polly框架。我們這里使用Polly。
Polly 是被 .NET 基金會認可的彈性和瞬態故障處理庫,允許開發人員以流暢和線程安全的方式表達策略,如重試、斷路器、超時、艙壁隔離和回退。
Polly 的7種策略 [1]:重試、斷路(熔斷)、降級、超時、隔離、緩存以及策略包集合 Polly 的核心是動作和故障,其中動作主要包含降級、熔斷和重試等,策略則包含用來執行的代碼。
1、重試(Retry):
當程序發生短暫的故障、並且故障在延遲后,可以自動糾正的,前期是暫時的我們可以配置自動重試。
2、斷路器(Circuit-Breaker):
當一個系統陷入嚴重的問題時,讓系統快速的失敗,比讓用戶一直等待着要好的多,保護一個系統不受過載的影響,可以幫助它快速的恢復。
3、超時(Timeout):
在等待一定的時間后,沒有返回相應的結果,保證程序不會一直等待下去,使調用者不必一直的等待下去。
4、隔離(Bulkhead Isolation):
當進程出現故障的時,一台主機中的多個失敗的進程,對資源(例如線程/CPU)的一直占用,當下游的系統發生故障的時候,也可能導致上游對資源的調用失敗、這兩種風險的出現都將導致更大范圍的影響、隔離策略是為了防止“一個點的失敗導致整盤的失敗”把受到管理的操作固定在某個資源中,避免影響到其他的資源。
5、緩存(Cache):
針對相同的請求,在第一次訪問的時候將響應的數據進行緩存,再次訪問的時候直接在緩存中提供響應的數據。
6、回退(FallBack):
當程序發生失敗的情況的時候,我們將做些什么,定義一個在程序發生失敗的時候要執行的動作。
7、策略組合(PolicyWrap):
Polly針對不同的故障有不同的策略,我們可以靈活的組合策略,上述的六種策略可以靈活組合使用。
Polly的基本用法
我們創建一個.NET Core 2.1 控制台應用程序,命名為 PollyDemo。
在Nuget中引用第三方庫Polly,選擇最新穩定版。
1、重試策略(Retry)
我們定義一個 GetUser 方法,這個方法用來模擬網絡請求並在方法結尾制造了一個 Http 異常。
在 Main 方法中我們設定了重試次數 5 次,並且規定了重試過程中要執行的業務邏輯,最后調用 Execute 方法指定針對哪段代碼執行這個策略。
我們運行代碼可以發現當觸發異常后,程序不斷的重試調用指定的代碼段,直到達到重試次數后不再重試並拋出異常。
我們在使用重試策略需要注意的是,當達到重試次數后代碼會拋出異常,因此我們必須在將充實策略代碼包裹在 try_catch 代碼段中。
using Polly; using System; using System.Net.Http; using System.Threading; namespace PollyDemo { class Program { static void Main(string[] args) { try { //如果程序發生錯誤將重新執行 5 次 Policy.Handle<HttpRequestException>().Retry(5, ((exception, count, context) => { Console.WriteLine($"執行失敗,第 {count} 次重試"); })).Execute(GetUser); } catch (Exception e) { Console.WriteLine("異常拋出:"+e.Message); } Console.Read(); } //開始執行代碼塊 static void GetUser() { Console.WriteLine("開始執行"); Thread.Sleep(1000); throw new HttpRequestException(); //直接定義錯誤拋出 } } }
執行結果
2、斷路器(Circuit-Breaker)
程序首次被訪問如果連續出現三次錯誤后,將暫停3秒,三秒結束后 可以被繼續訪問,
繼續訪問時 如果第一次就出現錯誤 ,繼續熔斷10次。
using Polly; using System; using System.Net.Http; using System.Threading; namespace PollyDemo { class Program { static void Main(string[] args) { //連續訪問3ci var PolicyExecutes = Policy<object>.Handle<Exception>() .CircuitBreaker(3, TimeSpan.FromSeconds(3)); //模擬訪問10次 for (int i = 0; i < 10; i++) { try { PolicyExecutes.Execute(() => { Console.WriteLine("********************開始執行程序**************************"); throw new Exception("異常"); }); } catch (Exception ex) { Console.WriteLine($"Exception信息{i}" + ex.Message); } //一秒運行一次 Thread.Sleep(1000); } Console.Read(); } } }
執行結果
3、超時策略(Timeout)
程序本身沒有錯誤就是執行的時間超過了我們制定的超時策略的時間然后程序就抓捕到超時的異常。
using Polly; using Polly.Timeout; using System; using System.Net.Http; using System.Threading; namespace PollyDemo { class Program { static void Main(string[] args) { try { //超時策略(程序沒錯,只是執行時間超過設置的時間) Policy policy = Policy.Timeout(3, TimeoutStrategy.Pessimistic); policy.Execute(() => { Console.WriteLine("********************開始執行程序**************************"); Console.WriteLine("等待執行中..."); Thread.Sleep(5000); //設置5s超時 }); } catch (Exception ex) { Console.WriteLine("執行超時,請重試"); } Console.Read(); } } }
執行過程
4、隔離策略(Bulkhead Isolation)
制定策略最大的並發數為5
using Polly; using Polly.Timeout; using System; using System.Net.Http; using System.Threading; using System.Threading.Tasks; namespace PollyDemo { class Program { static void Main(string[] args) { Policy PolicyExecutes = Policy.Bulkhead(5); //程序運行6次 總會有一個失敗的,但是這個失敗的不會影響其他5個的執行結果 for (int i = 0; i < 6; i++) { Task.Factory.StartNew(() => { try { PolicyExecutes.Execute(() => { Console.WriteLine($"********************開始執行程序**************************"); Thread.Sleep(5000); //為了看出效果,設置5s停頓,便於並發執行錯誤 }); } catch (Exception ex) { Console.WriteLine(ex.Message); } }); } Console.Read(); } } }
執行結果
5、緩存策略(Cache)
在開發時我們會把頻繁使用並且很少變化的資源緩存起來,來提高系統的性能。
Polly 提供了強大且易於上手的緩存策略的支持,使得我們不用再手動編寫緩存策略。
這里我不提供示例代碼,一來我暫時還沒使用這個策略,二來這一小部分需要根據不同項目和不同公司的框架來訂。
using System; namespace PollyDemo { class Program { static void Main(string[] args) { //Policy.Cache 可以指定 過期時間,絕對過期時間,滑動過期時間等 //Policy 的緩存策略的制定 MemoryCache memoryCache = null; var PolicyExecutes = Policy.Cache(memoryCache, TimeSpan.FromMinutes(5)); Console.Read(); } } }
6、回退(FallBack)
當主程序發生錯誤是我們啟動備用的程序進行程序處理。
using Polly; using System; namespace PollyDemo { class Program { static void Main(string[] args) { var PolicyExecute = Policy.Handle<Exception>().Fallback(() => { Console.WriteLine($"你的程序報錯了,我是替代程序!"); }); //執行 PolicyExecute.Execute(() => { Console.WriteLine("開始執行程序"); Console.WriteLine(""); throw new Exception(); }); Console.Read(); } } }
執行結果
7、策略組合(PolicyWrap)
PolicyWrap的上面六種策略可以任意的組合起來使用:我們將超時策略(Timeout)加上回退(FallBack)策略組合使用。
using Polly; using Polly.Timeout; using System; using System.Threading; namespace PollyDemo { class Program { static void Main(string[] args) { Policy PolicyExecute = Policy.Handle<Exception>().Fallback(() => { Console.WriteLine("你的執行程序超時了,我是替代程序!"); }); //超時策略 PolicyExecute = PolicyExecute.Wrap(Policy.Timeout(3, TimeoutStrategy.Pessimistic)); //執行 PolicyExecute.Execute(() => { Console.WriteLine($"我是一開始的執行程序"); Console.WriteLine(""); Thread.Sleep(5000); }); Console.Read(); } } }
執行結果
總結
本文開頭主要介紹了熔斷和降級的相關概念,然后用講解了 Polly 的其中策略,這些都可以作為掌握 Polly 的基礎。
因為 Polly 是一個強大而豐富的 .NET 第三方庫,無法通過一篇文章具體而又詳細的講解出來,因此對於 Polly 和 熔斷以及降級有興趣的同學可以上 Polly 官方文檔中具體學習。
參考文獻
1.Polly的7種策略:https://blog.csdn.net/sd7o95o/article/details/117003880
2.使用.NetCore 控制台演示 熔斷 降級(polly)
歡迎關注訂閱微信公眾號【熊澤有話說】,更多好玩易學知識等你來取
作者:熊澤-學習中的苦與樂 公眾號:熊澤有話說 出處: https://www.cnblogs.com/xiongze520/p/15693245.html 您可以隨意轉載、摘錄,但請在文章內注明作者和原文鏈接。
|