Polly失败重试
使用组件包
Polly策略功能
1、失败重试
调用失败的时候,重新尝试操作
方法:retry(重试次数,一直重试,等待事件后重试)
2、服务熔断
部分服务不可用的时候,应用可以快速响应一个熔断的结果,这样熔断的应用就不会一直被请求。从而不会是不可用服务一直被请求从而是整个应用服务崩溃。
方法:CircuitBreaker
发生10以异常,熔断10秒钟
services.AddHttpClient("orderclientv3").AddPolicyHandler(Policy<HttpResponseMessage>.Handle<HttpRequestException>().CircuitBreakerAsync( handledEventsAllowedBeforeBreaking: 10, durationOfBreak: TimeSpan.FromSeconds(10), onBreak: (r, t) => { }, onReset: () => { }, onHalfOpen: () => { } ));
高级用法,跟进失败比例。 80%出错就熔断, 第二个参数 多长时间内出现80%错误,第三个参数 当请求比较少时候,最少的请求数,下面就是 10秒内 请求小于100个就还不需要熔断。第四个参数 熔断时间长度
services.AddHttpClient("orderclientv3").AddPolicyHandler(Policy<HttpResponseMessage>.Handle<HttpRequestException>().AdvancedCircuitBreakerAsync( failureThreshold: 0.8, samplingDuration: TimeSpan.FromSeconds(10), minimumThroughput: 100, durationOfBreak: TimeSpan.FromSeconds(20), onBreak: (r, t) => { }, onReset: () => { }, onHalfOpen: () => { }));
应用程序熔断的时候会抛出一个异常 BrokenCircuitException。这个异常可以让后续策略使用。比如说 熔断后 在降级
3、超时处理
我们给服务设置一个超时时间,如果超过时间。就按照我们设定的返回,比如说一个缓存的结果。
方法:Timeout
4、舱壁隔离
实际上是一个限流的功能,为服务定义最大的流量和队列,控制请求量过大而被压崩。
方法:Bulkhead
限流抛出异常 BulkheadRejectedException,可以供后续策略使用
5、缓存策略
类似于AOP的机制为应用嵌入缓存。当缓存命中快速响应换存,而不是每次都请求服务。
方法:Cache
6、失败降级 也叫 回退
当我的服务不可用的时候,我们响应一个更加友好的结果,而不是报错。
方法:FallBack
7、组合策略
可以将上面的策略组合在一起
我们将超时策略(Timeout)加上回退(FallBack)策略组合使用
Polly使用步骤
失败重试场景
最佳实践
HttpClient
services.AddGrpcClient<OrderGrpc.OrderGrpcClient>(options => { options.Address = new Uri("https://localhost:5001"); }).ConfigurePrimaryHttpMessageHandler(provider => { var handler = new SocketsHttpHandler(); handler.SslOptions.RemoteCertificateValidationCallback = (a, b, c, d) => true; //允许无效、或自签名证书 return handler; }).AddTransientHttpErrorPolicy(t => t.RetryAsync(3)); //1、对HttpRequestException 500 408这样的错误会执行 #region 2、策略 #region 定义策略 //服务中注册策略 var reg= services.AddPolicyRegistry(); //捕捉到异常HttpResponseMessage 且 响应码是BadRequest ,重试3次 reg.Add("Retry3", Policy.HandleResult<HttpResponseMessage>(message => { return message.StatusCode == System.Net.HttpStatusCode.BadRequest; }).RetryAsync(3)); //服务中注册策略 var reg2 = services.AddPolicyRegistry(); //捕捉到异常HttpResponseMessage 且 NotFound ,直接返回ok reg.Add("RetryBack", Policy.HandleResult<HttpResponseMessage>(message => { return message.StatusCode == System.Net.HttpStatusCode.NotFound; }).Fallback(new HttpResponseMessage() { StatusCode=System.Net.HttpStatusCode.OK})); #endregion #region 使用策略 services.AddHttpClient("client1").AddPolicyHandlerFromRegistry("Retry3"); //动态定义策略机制 services.AddHttpClient("client2").AddPolicyHandlerFromRegistry((reg,mes)=> { //这行代码意思如果是httpget 就使用Retry3策略, 如果不是就熔断不做任何处理 // return mes.Method == HttpMethod.Get ? reg.Get<IAsyncPolicy<HttpResponseMessage>>("Retry3") : Policy.NoOpAsync<HttpResponseMessage>(); }); #endregion #endregion #region 3、捕获异常操作 //直接返回 //Policy.Handle<Exception>().Fallback() //熔断 //Policy.Handle<Exception>().CircuitBreaker #endregion
上面代码主要指结合httpclient添加polly
策略分类
策略状态
使用策略的时候,策略设置为单例的模式,但是这些策略是有状态的。
比如要对多个服务的熔断计数,那就需要多个熔断策略实例。
策略组合 熔断-降级
var breakPolicy = Policy<HttpResponseMessage>.Handle<HttpRequestException>().AdvancedCircuitBreakerAsync( failureThreshold: 0.8, samplingDuration: TimeSpan.FromSeconds(10), minimumThroughput: 100, durationOfBreak: TimeSpan.FromSeconds(20), onBreak: (r, t) => { }, onReset: () => { }, onHalfOpen: () => { }); var message = new HttpResponseMessage() { Content = new StringContent("{}") }; var fallback = Policy<HttpResponseMessage>.Handle<BrokenCircuitException>().FallbackAsync(message); var retry = Policy<HttpResponseMessage>.Handle<Exception>().WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(1)); var fallbackBreak = Policy.WrapAsync(fallback, retry, breakPolicy); services.AddHttpClient("httpv3").AddPolicyHandler(fallbackBreak);
1、上面代码组合策略。 熔断-重试-降级
var bulk = Policy.BulkheadAsync<HttpResponseMessage>( //最大并发 处理 数量 maxParallelization: 30, //如果不定义这个参数, 最大请求数超量,就会报错。定义了这个参数其他请求就会排队,如果排队大于20就在报错 maxQueuingActions: 20, //当我们请求被拒绝,被限流了 做的处理 onBulkheadRejectedAsync: contxt => Task.CompletedTask ); var message2 = new HttpResponseMessage() { Content = new StringContent("{}") }; var fallback2 = Policy<HttpResponseMessage>.Handle<BulkheadRejectedException>().FallbackAsync(message); var fallbackbulk = Policy.WrapAsync(fallback2, bulk); services.AddHttpClient("httpv4").AddPolicyHandler(fallbackbulk);
2、上面代码组合策略。 限流-降级