Polly 是一個 .NET 彈性和瞬態(tài)故障處理庫,允許開發(fā)人員以 Fluent 和線程安全的方式來實現(xiàn)重試、斷路、超時、隔離和回退策略。
Polly 的七種策略介紹
重試(Retry): 當出現(xiàn)故障時自動進行重試
斷路(Circuit-breaker):當系統(tǒng)遇到嚴重問題時,快速回饋失敗比讓用戶/調(diào)用者等待要好,限制系統(tǒng)出錯的體量,有助于系統(tǒng)恢復。
超時(Timeout):當系統(tǒng)超過一定時間的等待,我們就幾乎可以判斷不可能會有成功的結(jié)果,直接去干別的事情。
隔離(Bulkhead Isolation):當系統(tǒng)的一處出現(xiàn)故障時,可能促發(fā)多個失敗的調(diào)用,很容易耗盡主機的資源(如 CPU)。下游系統(tǒng)出現(xiàn)故障可能導致上游的故障的調(diào)用,甚至可能蔓延到導致系統(tǒng)崩潰。所以要將可控的操作限制在一個固定大小的資源池中,以隔離有潛在可能相互影響的操作。
回退(Fallback):有些錯誤無法避免,就要有備用的方案。這個就像瀏覽器不支持一些新的 CSS 特性就要額外引用一個 polyfill 一樣。一般情況,當無法避免的錯誤發(fā)生時,我們要有一個合理的返回來代替失敗。
緩存(Cache):一般我們會把頻繁使用且不會怎么變化的資源緩存起來,以提高系統(tǒng)的響應(yīng)速度。如果不對緩存資源的調(diào)用進行封裝,那么我們調(diào)用的時候就要先判斷緩存中有沒有這個資源,有的話就從緩存返回,否則就從資源存儲的地方(比如數(shù)據(jù)庫)獲取后緩存起來,再返回,而且有時還要考慮緩存過期和如何更新緩存的問題。Polly 提供了緩存策略的支持,使得問題變得簡單。
策略包(Policy Wrap):一種操作會有多種不同的故障,而不同的故障處理需要不同的策略。這些不同的策略必須包在一起,作為一個策略包,才能應(yīng)用在同一種操作上。這就是文章開頭說的 Polly 的彈性,即各種不同的策略能夠靈活地組合起來。
通過NuGet安裝Polly類庫:
官方項目地址: https://github.com/App-vNext/Polly
代碼實現(xiàn)
/// <summary> /// FallBack => 當出現(xiàn)故障,則進入降級動作 /// </summary> public static void Case1() { ISyncPolicy policy = Policy.Handle<ArgumentException>() .Fallback(() => { Console.WriteLine("Error occured"); }); policy.Execute(() => { Console.WriteLine("Job Start"); throw new ArgumentException("Hello Polly!"); Console.WriteLine("Job End"); }); } /// <summary> /// Retry => 重試 /// </summary> public static void Case2() { ISyncPolicy policy = Policy.Handle<Exception>().Retry(3); try { policy.Execute(() => { Console.WriteLine("Job Start"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("Special error occured"); } Console.WriteLine("Job End"); }); } catch (Exception ex) { Console.WriteLine("There's one unhandled exception : " + ex.Message); } } /// <summary> /// CircuitBreaker => 短路保護 /// </summary> public static void Case3() { // Stop for 10s after retry 6 times ISyncPolicy policy = Policy.Handle<Exception>() .CircuitBreaker(6, TimeSpan.FromSeconds(10)); while (true) { try { policy.Execute(() => { Console.WriteLine("Job Start"); throw new Exception("Special error occured"); Console.WriteLine("Job End"); }); } catch (Exception ex) { Console.WriteLine("There's one unhandled exception : " + ex.Message); } Thread.Sleep(500); } } /// <summary> /// Timeout 與 Wrap => Wrap是指策略封裝,可以把多個ISyncPolicy合并到一起執(zhí)行。Timeout則是指超時處理,但是超時策略一般不能直接使用,而是其其他策略封裝到一起使用。 /// </summary> public static void Case4() { try { ISyncPolicy policyException = Policy.Handle<TimeoutRejectedException>() .Fallback(() => { Console.WriteLine("Fallback"); }); ISyncPolicy policyTimeout = Policy.Timeout(3, Polly.Timeout.TimeoutStrategy.Pessimistic); ISyncPolicy mainPolicy = Policy.Wrap(policyTimeout, policyException); mainPolicy.Execute(() => { Console.WriteLine("Job Start..."); Thread.Sleep(5000); throw new Exception(); Console.WriteLine("Job End..."); }); } catch (Exception ex) { Console.WriteLine($"Unhandled exception : {ex.GetType()} : {ex.Message}"); } } /// <summary> /// 異步方法 /// </summary> public static async void Case5() { var policy = Policy<byte[]>.Handle<Exception>() .FallbackAsync(async c => { Console.WriteLine("Executed Error!"); return new byte[0]; }, async r => { Console.WriteLine(r.Exception); }); policy.WrapAsync(Policy.TimeoutAsync(5, TimeoutStrategy.Pessimistic, async (context, timespan, task) => { Console.WriteLine("Timeout!"); })); var bytes = await policy.ExecuteAsync(async () => { Console.WriteLine("Start Job"); HttpClient httpClient = new HttpClient(); var result = await httpClient.GetByteArrayAsync("https://img-blog.yssmx.com/img_convert/50f2b9069f40b88ea8348492d56abb87.png"); Console.WriteLine("Finish Job"); return result; }); Console.WriteLine($"Length of bytes : {bytes.Length}"); }
調(diào)用示例
Case1:
Case2:
Case3:文章來源:http://www.zghlxwxcb.cn/news/detail-812069.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-812069.html
到了這里,關(guān)于.NET彈性和瞬時處理庫Polly:理解并實現(xiàn)七種策略的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!