糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > Polly:提升服务可用性

Polly:提升服务可用性

时间:2019-04-01 19:50:36

相关推荐

Polly:提升服务可用性

Polly是.NET生态非常著名的组件包

一 介绍

Polly的能力

•失败重试:当我们服务调用失败时,能够自动的重试

•服务熔断:当我们服务部分不可用时,我们的应用可以快速响应一个熔断结果,避免持续的请求这些不可用的服务而导致整个应用程序出现问题

•超时处理:我们为服务的请求设置一个超时时间,当超过超时时间可以按照我们预定的操作进行处理,比如返回一个缓存的结果。

•舱壁隔离:实际上是一个限流的功能,我们可以为服务定义最大的流量和队列,这样可以避免我们的服务因为请求量过大而被压崩。

•缓存策略:可以让我与类似于AOP方式为应用嵌入缓存的机制,当缓存命中时,我们可以快速地响应缓存,而不是持续的请求服务。

•失败降级:当我们的服务不可用时,我们可以响应一个更友好的结果而不是报错。

•组合策略:可以让我们将上面的 策略组合在一起,按照一定的顺序,我们可以对不同的场景组合不同的策略类,实现我们的应用程序。

Polly使用步骤

•定义要处理的异常类型或返回值

•定义要处理动作(重试、熔断、降级响应等)

•使用定义的策略来执行代码

适合失败重试的场景

•服务“失败”是短暂的,可自愈的

在失败的场景里,我们可以非常有效的避免这种网络闪断这种情况

•服务是幂等的,重复调用不会有副作用

在失败重试情况下,有可能会造成多次调用的情况,因为有些失败,可能是你的命令已经发出了,但是你没收到响应,它会重试。

场景举例

•网络闪断

•部分服务节点异常

重试的过程可能就可以命中到正常的节点

最佳实践

•设置失败重试次数

•设置带有步长策略的失败等待间隔

•设置降级响应

•设置断路器

尽量设置重试的次数,尽量设置不同的间隔,否则会造成类似于DDOS的情况,当我们的重试的次数达到上限以后,我们应该为服务提供一个降级的响应,更友好的响应结果。(DDOS 全称Distributed Denial of Service,中文意思为“分布式拒绝服务”,就是利用大量合法的分布式服务器对目标发送请求,从而导致正常合法用户无法获得服务)

策略的类型

•被动策略(异常处理、结果处理)

•主动策略(超时处理、断路器、舱壁隔离、缓存)

组合策略

•降级响应

•失败重试

•断路器

•舱壁隔离

策略与状态共享

有状态:时间参数、次数参数等计数实例来承载的,对不同的服务进行定义不同的策略

二 应用

我们本次使用的组件包如下:

Polly

Polly.Extensions.Http

Microsoft.Extensions.Http.Polly

瞬时Http错误重试策略

错误规则

网络故障(HttpRequestException)

HTTP 5XX 状态代码(服务器错误)

HTTP 408 状态代码(请求超时)

有关配置策略的指南,请参阅有关 PolicyHttpMessageHandler 的备注。

public void ConfigureServices(IServiceCollection services){services.AddHttpClient("myClient", conifg =>{conifg.BaseAddress = new Uri("http://localhost:9090");}).//瞬时http错误重试策略 执行10次//抛出 HttpRequestException 或者响应码为5XX或者408AddTransientHttpErrorPolicy(p =>//错误重试配置 重试次数p.RetryAsync(10)).AddTransientHttpErrorPolicy(p =>p.WaitAndRetryAsync(10, i => TimeSpan.FromSeconds(2))).AddTransientHttpErrorPolicy(p =>//等待第i次*两秒重试 总共重试10次 越往后等的时间越久p.WaitAndRetryAsync(10, i => TimeSpan.FromSeconds(2 * i))).AddTransientHttpErrorPolicy(p =>//等待第i次*两秒重试 一直重试 直到成功p.WaitAndRetryForeverAsync(i => TimeSpan.FromSeconds(i * 3)));}

使用自定义的Http错误重试策略

可以根据HttpResponseMessage定义自己的重试条件

public void ConfigureServices(IServiceCollection services){//定义自己的策略var reg = services.AddPolicyRegistry();//根据返回的状态码自定义自己的返回策略reg.Add("retryforever",Policy.HandleResult<HttpResponseMessage>(message =>{return message.StatusCode == .HttpStatusCode.Created;}).RetryForeverAsync());//配置httpclient使用retryforever 的策略services.AddHttpClient("myClient2").AddPolicyHandlerFromRegistry("retryforever");//根据HttpRequestMessage 来定义策略services.AddHttpClient("myClient3").AddPolicyHandlerFromRegistry((registry, message) =>{return message.Method == HttpMethod.Get ?registry.Get<IAsyncPolicy<HttpResponseMessage>>("retryforever") :Policy.NoOpAsync<HttpResponseMessage>();});}});}

熔断策略

public void ConfigureServices(IServiceCollection services){//熔断services.AddHttpClient("myClient4").AddPolicyHandler(Policy<HttpResponseMessage>.Handle<HttpRequestException>().CircuitBreakerAsync(//报错10次后尽行熔断handledEventsAllowedBeforeBreaking: 10,//熔断的时间 10秒durationOfBreak: TimeSpan.FromSeconds(10),//当我们熔断时触发的一个事件onBreak: (r, t) => { },//当我们熔断恢复时的事件onReset: () => { },//在我们恢复之前进行验证服务是否可用//打一部分的流量去验证我们的服务是否可用的事件onHalfOpen: () => { }));}

高级熔断策略

public void ConfigureServices(IServiceCollection services){//高级熔断策略services.AddHttpClient("myClient4").AddPolicyHandler(Policy<HttpResponseMessage>.Handle<HttpRequestException>().AdvancedCircuitBreakerAsync(//比例0.8服务出错进行熔断failureThreshold: 0.8,//10秒以内 请求出错比例0.8 进行熔断samplingDuration: TimeSpan.FromSeconds(10),//最小的吞吐量100//当我们请求量比较小的时候//比如说我们十秒采样范围内//当我们的请求数超过100个时才会进行熔断//当请求量比较小的时候是不需要熔断minimumThroughput: 100,//熔断的时长 20秒durationOfBreak: TimeSpan.FromSeconds(20),//当我们熔断时触发的一个事件onBreak: (r, t) => { },//当我们熔断恢复时的事件onReset: () => { },//在我们恢复之前进行验证服务是否可用//打一部分的流量去验证我们的服务是否可用的事件onHalfOpen: () => { }));}

服务降级策略

publicvoid ConfigureServices(IServiceCollection services)

{//定义服务降级的策略//当我们遇到熔断时 我们响应一个异常的友好结果//定义我们的熔断var breakPolicy = Policy<HttpResponseMessage>.Handle<HttpRequestException>().AdvancedCircuitBreakerAsync(//百分之八十的服务出错进行熔断failureThreshold: 0.8,//10秒以内 请求出错比例0.8 进行熔断samplingDuration: TimeSpan.FromSeconds(10),//最小的吞吐量100//当我们请求量比较小的时候,比如说我们十秒采样范围内//当我们的请求数超过00个时才会进行熔断//当请求量比较小的时候是不需要熔断minimumThroughput: 100,//熔断的时长 20秒durationOfBreak: TimeSpan.FromSeconds(20),//当我们熔断时触发的一个事件onBreak: (r, t) => { },//当我们熔断恢复时的事件onReset: () => { },//在我们恢复之前进行验证服务是否可用//打一部分的流量去验证我们的服务是否可用的事件onHalfOpen: () => { } );//定义返回结果var message2 = new HttpResponseMessage(){Content =new StringContent("{\"IsError\":true,\"ErrorMsg\":\"服务异常\"}")};};//定义降级策略var fallback = Policy<HttpResponseMessage>.Handle<BrokenCircuitException>().FallbackAsync(message2);//定义重试var retry = Policy<HttpResponseMessage>.Handle<Exception>().WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(1));//定义请求策略组合var fallbackBreak = Policy.WrapAsync(fallback, retry, breakPolicy);//注入HttpClient定义策略services.AddHttpClient("myClient5").AddPolicyHandler(fallbackBreak);}}

限流策略

public void ConfigureServices(IServiceCollection services){//限流//定义请求的并发是多少var bulk = Policy.BulkheadAsync<HttpResponseMessage>(//最大请求并发数maxParallelization: 30,// 当我们请求超过30的并发数时//剩下的请求怎么处理的问题// 如果我们不定义我们的队列数// 它就会抛出异常//如果定义了队列数// 可以有20个请求在队列里排队// 只有超出队列的请求才会抛出异常// 让多出来的请求不至于直接报错maxQueuingActions: 20,//当我们的请求超出了并发数时怎么处理 这里可以定义自己的规则onBulkheadRejectedAsync: context => pletedTask);var message3 = new HttpResponseMessage(){Content = new StringContent("{}")};//定义超出并发数策略var fallback2 = Policy<HttpResponseMessage>.Handle<BulkheadRejectedException>().FallbackAsync(message3);//定义限流组合策略var fallbackBulk = Policy.WrapAsync(fallback2, bulk);//注入HttpClient定义策略services.AddHttpClient("myClient6").AddPolicyHandler(fallbackBulk);}}

参考地址:

/App-vNext/Polly.git

/App-vNext/Polly.Extensions.Http.git

/App-vNext/Polly-Samples.git

如果觉得《Polly:提升服务可用性》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。