參考:
通過 Polly 實現使用指數退避算法的 HTTP 調用重試
Polly 和 IHttpClientFactory一起使用
HttpClientFactory 結合 Polly 輕松實現重試機制
熔斷
熔斷就是在被調用端出現宕機(死機 / 斷開),和超時兩種情況出現的一種策略應對機制,直接拋異常。
只斷開某一服務功能,也為了防止影響其他服務的整體運行。
熔斷就好比保險絲,我們先來看一看保險絲的情況
舉例:家里電器短路了只有家里跳閘了,而不影響整棟樓的電路。
為什么要使用熔斷
1、服務調用出現異常(包括超時和宕機兩種情況)
如果服務連續幾次都出現異常,那么就將服務進行熔斷一段時間,程序知道這個服務是熔斷狀態就暫時不連接它,避免影響這個系統性能。
降級
保證核心功能可用,放棄一些非核心的外圍功能減壓,例如返回“系統繁忙”提示
例如:電商系統中高峰期訪問壓力過大時,保證購物車和支付功能可用,暫停后面還有的請求(直接返回系統繁忙),或者暫停一些瀏覽功能
1、服務主動降級(選擇性放棄)
主動將服務進行進行異常返回
2、服務異常降級
如果服務調用出現超時或者宕機的情況,就按照自定義的策略進行返回。
項目中熔斷降級的目的是保證系統的彈性,使系統高可用
熔斷與降級區別
參考:
熔斷是直接拋異常,降級是返回自定義信息。
熔斷是針對單一服務,降級是為了整個系統穩定而減少請求或者暫停外圍非核心服務
Polly主要功能
重試(Retry)
斷路器(Circuit-breaker)
超時檢測(Timeout)
緩存(Cache)
降級(FallBack)
Polly使用步驟
1 nuget包安裝
先通過nuget進行安裝,在AggregateService(聚合服務)、MicroService.Core(核心層/公共層/工具層)都需要安裝:Microsoft.Extensions.Http.Polly
2 添加Polly擴展類和方法
然后在HttpClient后面添加擴展方法AddPolicyHandler()
在MicroService.Core(核心服務/公共服務/工具層)中添加類
/// <summary> /// 微服務中HttpClient熔斷,降級策略擴展 /// </summary> public static class PollyHttpClientServiceCollectionExtensions { /// <summary> /// Httpclient擴展Polly方法 /// </summary> /// <param name="services">ioc容器</param> /// <param name="name">HttpClient 名稱(針對不同的服務進行熔斷,降級)</param> /// <param name="action">熔斷降級配置</param> /// <param name="TResult">降級處理錯誤的結果</param> /// <returns></returns> public static IServiceCollection AddPollyHttpClient(this IServiceCollection services, string name,Action<PollyHttpClientOptions> action) { // 1、創建選項配置類 PollyHttpClientOptions options = new PollyHttpClientOptions(); action(options); // 2、配置httpClient,熔斷降級策略 services.AddHttpClient(name,client => { client.Timeout = TimeSpan.FromSeconds(60); }) //1.1 降級策略 .AddPolicyHandler(Policy<HttpResponseMessage>.HandleInner<Exception>().FallbackAsync(options.httpResponseMessage, async b => { // 1、降級打印異常 Console.WriteLine($"服務{name}開始降級,異常消息:{b.Exception.Message}"); // 2、降級后的數據 Console.WriteLine($"服務{name}降級內容響應:{options.httpResponseMessage.Content.ToString()}"); await Task.CompletedTask; })) // 1.2 斷路器策略 .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().CircuitBreakerAsync(options.CircuitBreakerOpenFallCount, TimeSpan.FromSeconds(options.CircuitBreakerDownTime), (ex, ts) => { Console.WriteLine($"服務{name}斷路器開啟,異常消息:{ex.Exception.Message}"); Console.WriteLine($"服務{name}斷路器開啟時間:{ts.TotalSeconds}s"); }, () => { Console.WriteLine($"服務{name}斷路器關閉"); }, () => { Console.WriteLine($"服務{name}斷路器半開啟(時間控制,自動開關)"); })) // 1.3 重試策略 .AddPolicyHandler(Policy<HttpResponseMessage> .Handle<Exception>() .RetryAsync(options.RetryCount) ) // 1.4 超時策略 .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(options.TimeoutTime))); return services; } }
3 使用Polly方法
在聚合服務的Startup類的ConfigureServices中測試宕機,和超時情況
// 1、自定義異常處理(用緩存處理) var fallbackResponse = new HttpResponseMessage { Content = new StringContent("系統正繁忙,請稍后重試"),// 內容,自定義內容 StatusCode = HttpStatusCode.GatewayTimeout // 504 }; // 1.2 封裝之后的調用PollyHttpClient services.AddPollyHttpClient("mrico", options => { options.TimeoutTime = 60; // 1、超時時間 options.RetryCount = 3;// 2、重試次數 options.CircuitBreakerOpenFallCount = 2;// 3、熔斷器開啟(多少次失敗開啟) options.CircuitBreakerDownTime = 100;// 4、熔斷器開啟時間 options.httpResponseMessage = fallbackResponse;// 5、降級處理 }) .AddHttpClientConsul<ConsulHttpClient>(); // 1.3、HttpClient下consul封裝(實現負載均衡請求)