熔斷、降級:html
熔斷:熔斷就是咱們常說的「保險絲」,意爲當服務出現某些情況時,切斷服務,從而防止應用程序不斷地常識執行可能會失敗的操做形成系統的「雪崩」,或者大量的超時等待致使系統卡死等狀況,不少地方也將其成爲「過載保護」。git
降級:降級的目的就是當某個服務提供者發生故障的時候,向調用方返回一個替代響應或者錯誤響應。github
POLLY是一個.NET回彈和瞬態故障處理庫,它容許開發人員以流暢和線程安全的方式表達諸如重試、斷路器、超時、隔板隔離和回退等策略。github官方解釋嘿嘿。
windows
Polly以.NET Standard 1.1(覆蓋範圍:.NET Framework 4.5-4.6.1,.NET Core 1.0,Mono,Xamarin,UWP,WP8.1 +)緩存
.NET Standard 2.0+(覆蓋範圍:.NET Framework 4.6.1, .NET Core 2.0+以及後來的Mono,Xamarin和UWP目標)安全
首先固然是建立一個控制檯項目,而後經過NuGet安裝:dom
Install-Package Polly
出現以上界面就說明你已經安裝了最新的版本到你的項目;ide
polly經過官方介紹咱們能夠知道有7種恢復策略,先無論會不會,先列出來再說哈哈:微服務
重試策略(Retry):許多故障是短暫的,而且在短暫的延遲後可能會自我糾正。容許咱們作的是可以自動配置重試機制ui
斷路器(Circuit-breaker):當一個系統嚴重掙扎時,快速失敗優於讓用戶/呼叫者等待。 說白了就是應該優先直接返回失敗,而不是一直讓用戶等待。保護故障系統免受過載能夠幫助恢復。
超時(Timeout):超時策略針對的前置條件是超過必定的等待時間,想要獲得成功的結果是不可能的,保證調用者沒必要等待超時。
隔板隔離(Bulkhead Isolation):隔板隔離針對的前置條件是當進程出現故障時,多個失敗一直在主機中對資源(例如線程/ CPU)一直佔用。下游系統故障也可能致使上游失敗。這兩個風險都將形成嚴重的後果。都說一粒老鼠子屎攪渾一鍋粥,而Polly則將受管制的操做限制在固定的資源池中,免其餘資源受其影響。
緩存(Cache):就是一些請求,會把數據緩存起來,而後在持續一段時間內,直接從緩存中取。
回退(Fallback):操做仍然會失敗,也就是說當發生這樣的事情時咱們打算作什麼。也就是說定義失敗返回操做。咱們在使用時就是所說的降級。
策略包裝(PolicyWrap):不一樣的故障須要不一樣的策略 彈性意味着使用組合。
polly通常分爲三步進行:
定義條件: 定義你要處理的 錯誤異常/返回結果
定義處理方式 : 重試,熔斷,回退
執行
定義條件:
.Handle<ExceptionType>():限定條件的單個異常Policy;
.Handle<ExceptionType>(ex => ex.Number == 10):具備條件的單個異常類型。
.Handle<HttpRequestException>() .Or<OperationCanceledException>():多個異常類型,固然他也能夠變成具備條件的多個異常類型,相似於單個操做。
定義返回結果的條件:
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound):用條件處理返回值,處理單個返回值。
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError) .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadGateway):處理多個返回值。
指定策略(重試):
.Retry():重試一次。
.Retry(3):重試三次,修改數值便可定義本身想使用的次數。
.Retry(3, (exception, retryCount) => { // do something }):重試屢次,在每次重試都執行一個操做,參數爲:當前異常和重試計數。
.Retry(3, (exception, retryCount, context) => { // do something }):重試屢次,在每次重試都執行一個操做,參數爲:當前異常,重試計數和上下文
.RetryForever():永遠重試直到成功,同時也也有重試的相同擴展,能夠寫參數。
.WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }):等待並重試,就是在每一個重試的時候須要等待指定的執行時間,一樣有相同擴展,能夠在每一個重試調用一個操做。
.WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) ):等待和重試永遠(直到成功)
指定策略(熔斷):
.CircuitBreaker(2, TimeSpan.FromMinutes(1)):在指定數量的連續異常以後中斷開。這裏就不作過多解釋了。
指定策略(降級):回退
.Fallback<UserAvatar>(UserAvatar.Blank):若是執行錯誤,則提供替代值,就是出現錯誤,定義一個返回值給他
.Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar()) :定義一個方法給他,該方法代替提供值。
執行:
.Execute(() => DoSomething()):執行一項方法
執行經過任意上下文數據的操做:
var policy = Policy .Handle<SomeExceptionType>() .Retry(3, (exception, retryCount, context) => { var methodThatRaisedException = context["methodName"]; Log(exception, methodThatRaisedException); }); policy.Execute( () => DoSomething(), new Dictionary<string, object>() {{ "methodName", "some method" }} );
降級的使用代碼:
#region 降級 public static void Downgrade() { //降級處理程序 ISyncPolicy policy = Policy.Handle<ArgumentException>() .Fallback(() => { Console.WriteLine("降級給的返回值結果"); }); //運行程序 policy.Execute(() => { Console.WriteLine("任務開始"); throw new ArgumentException("降級任務出錯,立刻要降級了"); Console.WriteLine("任務結束"); }); } #endregion
運行結果:
重試機制的代碼:
出錯後重復3次。
#region 重試機制 public static void Retry() { //配置重試次數 ISyncPolicy policy = Policy.Handle<Exception>().Retry(3); try { policy.Execute(() => { Console.WriteLine("任務開始"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("任務出錯了,開始重試"); } Console.WriteLine("任務結束"); }); } catch (Exception ex) { Console.WriteLine("異常結果 : " + ex.Message); } } #endregion
運行結果:
熔斷機制代碼:
但出現錯誤連續三次後,等待20秒後進行
#region 熔斷機制 public static void Fusing() { Action<Exception, TimeSpan> onBreak = (exception, timespan) => { Console.WriteLine("1"); }; Action onReset = () => { Console.WriteLine("2"); }; ISyncPolicy policy = Policy.Handle<Exception>().CircuitBreaker(3, TimeSpan.FromSeconds(20), onBreak, onReset); while (true) { try { policy.Execute(() => { Console.WriteLine("任務開始"); throw new Exception("出錯了"); Console.WriteLine("任務結束"); }); } catch (Exception ex) { Console.WriteLine("---------------異常結果-------------- : " + ex.Message + "時間:" + DateTime.Now); } System.Threading.Thread.Sleep(5000); } } #endregion
運行結果:
混合示例(重試+降級)代碼:
出錯重試三次後第四次進行降級處理:主要是warp方法來實現的,特別說明warp方法是:最外面(在左邊)到最裏面(右邊)的策略。也就是說從右向左執行方法;
#region 重試+降級 public static void RetryDowngrade() { try { //降級處理程序 ISyncPolicy policy = Policy.Handle<Exception>() .Fallback(() => { Console.WriteLine("降級成功"); }); //配置重試次數 ISyncPolicy policy2 = Policy.Handle<Exception>().Retry(3, (exception, retryCount, context) => { Console.WriteLine(retryCount); }); //合併 ISyncPolicy mainPolicy = Policy.Wrap(policy, policy2); mainPolicy.Execute(() => { Console.WriteLine("任務開始"); throw new Exception("出錯了"); Console.WriteLine("任務結束"); }); } catch (Exception ex) { Console.WriteLine("異常結果 : " + ex.Message); } } #endregion
運行結果:
源碼下載:PollyConsole.rar
微服務系列文章主要介紹微服務所使用到的一些技術和一些技術示例: