参考:
通过 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封装(实现负载均衡请求)