<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ASP VNext 開(kāi)源服務(wù)容錯(cuò)處理庫(kù)Polly使用文檔

      在進(jìn)入SOA之后,我們的代碼從本地方法調(diào)用變成了跨機(jī)器的通信。任何一個(gè)新技術(shù)的引入都會(huì)為我們解決特定的問(wèn)題,都會(huì)帶來(lái)一些新的問(wèn)題。比如網(wǎng)絡(luò)故障、依賴服務(wù)崩潰、超時(shí)、服務(wù)器內(nèi)存與CPU等其它問(wèn)題。正是因?yàn)檫@些問(wèn)題無(wú)法避免,所以我們?cè)谶M(jìn)行系統(tǒng)設(shè)計(jì)、特別是進(jìn)行分布式系統(tǒng)設(shè)計(jì)的時(shí)候以“Design For Failure”(為失敗而設(shè)計(jì))為指導(dǎo)原則。把一些邊緣場(chǎng)景以及服務(wù)之間的調(diào)用發(fā)生的異常和超時(shí)當(dāng)成一定會(huì)發(fā)生的情況來(lái)預(yù)先進(jìn)行處理。

       

      Design For Failure
      1. 一個(gè)依賴服務(wù)的故障不會(huì)嚴(yán)重破壞用戶的體驗(yàn)。
      2. 系統(tǒng)能自動(dòng)或半自動(dòng)處理故障,具備自我恢復(fù)能力。

      以下是一些經(jīng)驗(yàn)的服務(wù)容錯(cuò)模式

      • 超時(shí)與重試(Timeout and Retry)
      • 限流(Rate Limiting)
      • 熔斷器(Circuit Breaker)
      • 艙壁隔離(Bulkhead Isolation)
      • 回退(Fallback)

      如果想詳細(xì)了解這幾種模式可以參考美團(tuán)技術(shù)團(tuán)隊(duì)的總結(jié):服務(wù)容錯(cuò)模式。我們今天要講的是,thanks to the community 多謝社區(qū), Polly已經(jīng)為我們實(shí)現(xiàn)了以上全部的功能。Polly是一個(gè)C#實(shí)現(xiàn)的彈性瞬時(shí)錯(cuò)誤處理庫(kù)(resilience and transient-fault-handling library一直覺(jué)得這個(gè)英文翻譯不是很好) 。在Polly中,對(duì)這些服務(wù)容錯(cuò)模式分為兩類:

      • 錯(cuò)誤處理fault handling :重試、熔斷、回退
      • 彈性應(yīng)變r(jià)esilience:超時(shí)、艙壁、緩存

      可以說(shuō)錯(cuò)誤處理是當(dāng)錯(cuò)誤已經(jīng)發(fā)生時(shí),防止由于該錯(cuò)誤對(duì)整個(gè)系統(tǒng)造成更壞的影響而設(shè)置。而彈性應(yīng)變,則在是錯(cuò)誤發(fā)生前,針對(duì)有可能發(fā)生錯(cuò)誤的地方進(jìn)行預(yù)先處理,從而達(dá)到保護(hù)整個(gè)系統(tǒng)的目地。

      Polly 錯(cuò)誤處理使用三步曲

      • 定義條件: 定義你要處理的 錯(cuò)誤異常/返回結(jié)果
      • 定義處理方式 : 重試,熔斷,回退
      • 執(zhí)行

      先看一個(gè)簡(jiǎn)單的例子

      // 這個(gè)例子展示了當(dāng)DoSomething方法執(zhí)行的時(shí)候如果遇到SomeExceptionType的異常則會(huì)進(jìn)行重試調(diào)用。
      var policy = Policy
                    .Handle<SomeExceptionType>()   // 定義條件 
                    .Retry(); // 定義處理方式
      
      // 執(zhí)行
      policy.Execute(() => DoSomething());

      定義條件

      我們可以針對(duì)兩種情況來(lái)定義條件:錯(cuò)誤異常和返回結(jié)果。

      // 單個(gè)異常類型
      Policy
        .Handle<HttpRequestException>()
      
      // 限定條件的單個(gè)異常
      Policy
        .Handle<SqlException>(ex => ex.Number == 1205)
      
      // 多個(gè)異常類型
      Policy
        .Handle<HttpRequestException>()
        .Or<OperationCanceledException>()
      
      // 限定條件的多個(gè)異常
      Policy
        .Handle<SqlException>(ex => ex.Number == 1205)
        .Or<ArgumentException>(ex => ex.ParamName == "example")
      
      // Inner Exception 異常里面的異常類型 
      Policy
        .HandleInner<HttpRequestException>()
        .OrInner<OperationCanceledException>(ex => ex.CancellationToken != myToken)
      

        

      以及用返回結(jié)果來(lái)限定

      // 返回結(jié)果加限定條件 
      Policy
        .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound)
      
      // 處理多個(gè)返回結(jié)果
      Policy
        .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
        .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadGateway)
      
      // 處理元類型結(jié)果 (用.Equals)
      Policy
        .HandleResult<HttpStatusCode>(HttpStatusCode.InternalServerError)
        .OrResult<HttpStatusCode>(HttpStatusCode.BadGateway)
       
      // 在一個(gè)policy里面同時(shí)處理異常和返回結(jié)果。
      HttpStatusCode[] httpStatusCodesWorthRetrying = {
         HttpStatusCode.RequestTimeout, // 408
         HttpStatusCode.InternalServerError, // 500
         HttpStatusCode.BadGateway, // 502
         HttpStatusCode.ServiceUnavailable, // 503
         HttpStatusCode.GatewayTimeout // 504
      }; 
      HttpResponseMessage result = Policy
        .Handle<HttpRequestException>()
        .OrResult<HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode))
        .RetryAsync(...)
        .ExecuteAsync( /* some Func<Task<HttpResponseMessage>> */ )
      

        

      定義處理方式

      在這里使用的處理方式就是我們最開(kāi)始說(shuō)的服務(wù)容錯(cuò)模式,我們將介紹以下三種:重試、熔斷、回退。

      重試

      重試很好理解,當(dāng)發(fā)生某種錯(cuò)誤或者返回某種結(jié)果的時(shí)候進(jìn)行重試。Polly里面提供了以下幾種重試機(jī)制

      • 按次數(shù)重試
      • 不斷重試(直到成功)
      • 等待之后按次數(shù)重試
      • 等待之后不斷重試(直到成功)

      按次數(shù)重試

      // 重試1次
      Policy
        .Handle<SomeExceptionType>()
        .Retry()
      
      // 重試3(N)次
      Policy
        .Handle<SomeExceptionType>()
        .Retry(3)
      
      // 重試多次,加上重試時(shí)的action參數(shù)
      Policy
          .Handle<SomeExceptionType>()
          .Retry(3, (exception, retryCount) =>
          {
              // 干點(diǎn)什么,比如記個(gè)日志之類的 
          });
      

        

      不斷重試

      // 不斷重試,直到成功
      Policy
        .Handle<SomeExceptionType>()
        .RetryForever()
      
      // 不斷重試,帶action參數(shù)在每次重試的時(shí)候執(zhí)行
      Policy
        .Handle<SomeExceptionType>()
        .RetryForever(exception =>
        {
              // do something       
        });
      

        

      等待之后重試

      // 重試3次,分別等待1、2、3秒。
      Policy
        .Handle<SomeExceptionType>()
        .WaitAndRetry(new[]
        {
          TimeSpan.FromSeconds(1),
          TimeSpan.FromSeconds(2),
          TimeSpan.FromSeconds(3)
        });
      

        

      當(dāng)然也可以在每次重試的時(shí)候添加一些處理,這里我們可以從上下文中獲取一些數(shù)據(jù),這些數(shù)據(jù)在policy啟動(dòng)執(zhí)行的時(shí)候可以傳進(jìn)來(lái)。

      Policy
        .Handle<SomeExceptionType>()
        .WaitAndRetry(new[]
        {
          TimeSpan.FromSeconds(1),
          TimeSpan.FromSeconds(2),
          TimeSpan.FromSeconds(3)
        }, (exception, timeSpan, context) => {
          // do something    
        });
      

        

      把WiatAndRetry抱成WaitAndRetryForever()則可以實(shí)現(xiàn)重試直到成功。

      熔斷

      熔斷也可以被作為當(dāng)遇到某種錯(cuò)誤場(chǎng)景下的一個(gè)操作。以下代碼展示了當(dāng)發(fā)生2次SomeExceptionType的異常的時(shí)候則會(huì)熔斷1分鐘,該操作后續(xù)如果繼續(xù)嘗試執(zhí)行則會(huì)直接返回錯(cuò)誤 。

      Policy
          .Handle<SomeExceptionType>()
          .CircuitBreaker(2, TimeSpan.FromMinutes(1));
      

        

      可以在熔斷和恢復(fù)的時(shí)候定義委托來(lái)做一些額外的處理。onBreak會(huì)在被熔斷時(shí)執(zhí)行,而onReset則會(huì)在恢復(fù)時(shí)執(zhí)行。

      
      

      熔斷器狀態(tài)

      我們的CircuitBreakPolicy的State定義了當(dāng)前熔斷器的狀態(tài),我們也可能調(diào)用它的Is

      Action<Exception, TimeSpan> onBreak = (exception, timespan) => { ... };
      Action onReset = () => { ... };
      CircuitBreakerPolicy breaker = Policy
          .Handle<SomeExceptionType>()
          .CircuitBreaker(2, TimeSpan.FromMinutes(1), onBreak, onReset);
      

        

      olate和Reset方法來(lái)手動(dòng)熔斷和恢復(fù) 。

      CircuitState state = breaker.CircuitState;
      

        

      • Closed 關(guān)閉狀態(tài),允許執(zhí)行
      • Open 自動(dòng)打開(kāi),執(zhí)行會(huì)被阻斷
      • Isolate 手動(dòng)打開(kāi),執(zhí)行會(huì)被阻斷
      • HalfOpen  從自動(dòng)打開(kāi)狀態(tài)恢復(fù)中,在熔斷時(shí)間到了之后從Open狀態(tài)切換到Closed
      // 手動(dòng)打開(kāi)熔斷器,阻止執(zhí)行
      breaker.Isolate(); 
      // 恢復(fù)操作,啟動(dòng)執(zhí)行 
      breaker.Reset(); 
      

        

      回退(Fallback)

      // 如果執(zhí)行失敗則返回UserAvatar.Blank
      Policy
         .Handle<Whatever>()
         .Fallback<UserAvatar>(UserAvatar.Blank)
      
      // 發(fā)起另外一個(gè)請(qǐng)求去獲取值
      Policy
         .Handle<Whatever>()
         .Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar()) // where: public UserAvatar GetRandomAvatar() { ... }
      
      // 返回一個(gè)指定的值,添加額外的處理操作。onFallback
      Policy
         .Handle<Whatever>()
         .Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) => 
          {
              // do something
          });
      

        

      執(zhí)行polly policy

      為我聲明了一個(gè)Policy,并定義了它的異常條件和處理方式,那么接下來(lái)就是執(zhí)行它。執(zhí)行是把我們具體要運(yùn)行的代碼放到Policy里面。

      // 執(zhí)行一個(gè)Action
      var policy = Policy
                    .Handle<SomeExceptionType>()
                    .Retry();
      
      policy.Execute(() => DoSomething());
      

        

      這就是我們最開(kāi)始的例子,還記得我們?cè)诋惓L幚淼臅r(shí)候有一個(gè)context上下文嗎?我們可以在執(zhí)行的時(shí)候帶一些參數(shù)進(jìn)去

      // 看我們?cè)趓etry重試時(shí)被調(diào)用的一個(gè)委托,它可以從context中拿到我們?cè)趀xecute的時(shí)候傳進(jìn)來(lái)的參數(shù) 。
      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" }}
      );
      

        

      當(dāng)然,我們也可以將Handle,Retry, Execute 這三個(gè)階段都串起來(lái)寫(xiě)。

      Policy
        .Handle<SqlException>(ex => ex.Number == 1205)
        .Or<ArgumentException>(ex => ex.ParamName == "example")
        .Retry()
        .Execute(() => DoSomething());
      

        

      Polly 彈性應(yīng)變處理Resilience

      我們?cè)谏厦嬷v了Polly在錯(cuò)誤處理方面的使用,接下來(lái)我們介紹Polly在彈性應(yīng)變這塊的三個(gè)應(yīng)用: 超時(shí)、艙壁和緩存。

      超時(shí)

      Policy
        .Timeout(TimeSpan.FromMilliseconds(2500))
      

        

      支持傳入action回調(diào)

      Policy
        .Timeout(30, onTimeout: (context, timespan, task) => 
          {
              // do something 
          });
      

        

      超時(shí)分為樂(lè)觀超時(shí)與悲觀超時(shí),樂(lè)觀超時(shí)依賴于CancellationToken ,它假設(shè)我們的具體執(zhí)行的任務(wù)都支持CancellationToken。那么在進(jìn)行timeout的時(shí)候,它會(huì)通知執(zhí)行線程取消并終止執(zhí)行線程,避免額外的開(kāi)銷。下面的樂(lè)觀超時(shí)的具體用法 。

      // 聲明 Policy 
      Policy timeoutPolicy = Policy.TimeoutAsync(30);
      HttpResponseMessage httpResponse = await timeoutPolicy
          .ExecuteAsync(
            async ct => await httpClient.GetAsync(endpoint, ct), 
            CancellationToken.None 
      // 最后可以把外部的 CacellationToken附加到 timeoutPollcy的 CT上,在這里我們沒(méi)有附加
            );
      

        

      悲觀超時(shí)與樂(lè)觀超時(shí)的區(qū)別在于,如果執(zhí)行的代碼不支持取消CancellationToken,它還會(huì)繼續(xù)執(zhí)行,這會(huì)是一個(gè)比較大的開(kāi)銷。

      Policy
        .Timeout(30, TimeoutStrategy.Pessimistic)
      

        

      上面的代碼也有悲觀sad...的寫(xiě)法

      Policy timeoutPolicy = Policy.TimeoutAsync(30, TimeoutStrategy.Pessimistic);
      var response = await timeoutPolicy
          .ExecuteAsync(
            async () => await FooNotHonoringCancellationAsync(), 
            );// 在這里我們沒(méi)有 任何與CancllationToken相關(guān)的處理
      

        

      艙壁

      在開(kāi)頭的那篇文章中詳細(xì)解釋了艙壁這種模式,它用來(lái)限制某一個(gè)操作的最大并發(fā)執(zhí)行數(shù)量 。比如限制為12

      Policy
        .Bulkhead(12)
      

        

      同時(shí),我們還可以控制一個(gè)等待處理的隊(duì)列長(zhǎng)度

      Policy
        .Bulkhead(12, 2)
      

        

      以及當(dāng)請(qǐng)求執(zhí)行操作被拒絕的時(shí)候,執(zhí)行回調(diào)

      Policy
        .Bulkhead(12, context => 
          {
              // do something 
          });
      

        

      緩存

      Polly的緩存需要依賴于一個(gè)外部的Provider。

      var memoryCacheProvider = new Polly.Caching.MemoryCache.MemoryCacheProvider(MemoryCache.Default);
      var cachePolicy = Policy.Cache(memoryCacheProvider, TimeSpan.FromMinutes(5));
      
      // 設(shè)置一個(gè)絕對(duì)的過(guò)期時(shí)間
      var cachePolicy = Policy.Cache(memoryCacheProvider, new AbsoluteTtl(DateTimeOffset.Now.Date.AddDays(1));
      
      // 設(shè)置一個(gè)滑動(dòng)的過(guò)期時(shí)間,即每次使用緩存的時(shí)候,過(guò)期時(shí)間會(huì)更新
      var cachePolicy = Policy.Cache(memoryCacheProvider, new SlidingTtl(TimeSpan.FromMinutes(5));
      
      // 我們用Policy的緩存機(jī)制來(lái)實(shí)現(xiàn)從緩存中讀取一個(gè)值,如果該值在緩存中不存在則從提供的函數(shù)中取出這個(gè)值放到緩存中。
      // 借且于Polly Cache  這個(gè)操作只需要一行代碼即可。
      TResult result = cachePolicy.Execute(() => getFoo(), new Context("FooKey")); // "FooKey" is the cache key used in this execution.
      
      // Define a cache Policy, and catch any cache provider errors for logging. 
      var cachePolicy = Policy.Cache(myCacheProvider, TimeSpan.FromMinutes(5), 
         (context, key, ex) => { 
             logger.Error($"Cache provider, for key {key}, threw exception: {ex}."); // (for example) 
         }
      );
      

        

      組合Policy

      最后我們要說(shuō)的是如何將多個(gè)policy組合起來(lái)。大致的操作是定義多個(gè)policy,然后用Wrap方法即可。

      var policyWrap = Policy
        .Wrap(fallback, cache, retry, breaker, timeout, bulkhead);
      policyWrap.Execute(...)
      

        

      在另一個(gè)Policy聲明時(shí)組合使用其它外部聲明的Policy。

      PolicyWrap commonResilience = Policy.Wrap(retry, breaker, timeout);
      
      Avatar avatar = Policy
         .Handle<Whatever>()
         .Fallback<Avatar>(Avatar.Blank)
         .Wrap(commonResilience)
         .Execute(() => { /* get avatar */ });

       寫(xiě)在后面

      上一篇我們介紹了《asp.net core開(kāi)源api 網(wǎng)關(guān)Ocelot的中文使用文檔》,Ocelot里面的一些關(guān)于Qos服務(wù)質(zhì)量的處理就是用Polly來(lái)實(shí)現(xiàn)的。當(dāng)然在沒(méi)有網(wǎng)關(guān)介入的情況 下,我們也可以單獨(dú)來(lái)使用Polly做彈性應(yīng)對(duì)和瞬時(shí)錯(cuò)誤處理。關(guān)于分布式架構(gòu),這是一個(gè)很大的話題,我們后面繼續(xù)展示,歡迎關(guān)注 。

       

      posted @ 2018-03-29 09:16  騰飛(Jesse)  閱讀(6861)  評(píng)論(10)    收藏  舉報(bào)
      主站蜘蛛池模板: 国外av片免费看一区二区三区| 无码伊人久久大杳蕉中文无码| 亚洲精品日韩在线观看| 婷婷六月天在线| 国产欧美日韩视频怡春院| 国产首页一区二区不卡| 精品国产熟女一区二区三区| 国产最新AV在线播放不卡| 午夜大尺度福利视频一区| 92精品国产自产在线观看481页| 日本亚洲欧洲免费无线码 | 99精品热在线在线观看视| 人妻少妇精品视频专区| 亚洲 成人 无码 在线观看| 在线看片免费不卡人成视频| 国产国语一级毛片| 亚洲第四色在线中文字幕| 中文字幕无码精品亚洲35| 男人和女人高潮做爰视频| 亚洲夂夂婷婷色拍WW47| 国产精品成人午夜久久| 国产精品熟女乱色一区二区| 欧美三级a做爰在线观看| 亚洲一区二区三区十八禁| 国产不卡一区二区精品| 岳阳县| 性色av无码不卡中文字幕| 激情内射亚洲一区二区三区 | 高清免费毛片| 国产玖玖玖玖精品电影| 美女把尿囗扒开让男人添| 国产自产视频一区二区三区| 人妻中文字幕在线视频无码| 4480yy亚洲午夜私人影院剧情| 怡红院一区二区三区在线| 国产亚洲精品久久久久5区| 国内自拍小视频在线看| 成人国产精品一区二区网站公司| 欧美色欧美亚洲高清在线观看| 福利一区二区在线观看| 丁香婷婷在线观看|