首页 > 其他 > 详细

Polly:提升服务可用性

时间:2020-04-25 18:51:25      阅读:68      评论:0      收藏:0      [点我收藏+]

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

一 介绍

Polly 的能力

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

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

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

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

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

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

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

Polly 使用步骤

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

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

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

适合失败重试的场景

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

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

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

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

场景举例

网络闪断

部分服务节点异常

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

最佳实践

设置失败重试次数

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

设置降级响应

设置断路器

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

策略的类型

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

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

组合策略

降级响应

失败重试

断路器

舱壁隔离

策略与状态共享

Policy类型

状态

说明

CircuitBreaker(断路器)

有状态

共享成功失败率,以决定是否熔断

Bulkhead(舱壁隔离)

有状态

共享容量使用情况,以决定是否执行动作

Cache(缓存)

有状态

共享缓存的对象,以决定是否命中

其它策略

无状态

-

 

 

 

 

 

 

 

 

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

二  应用

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

Polly 

Polly.Extensions.Http 

Microsoft.Extensions.Http.Polly

瞬时Http错误重试策略

  错误规则

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

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

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

 1    public void ConfigureServices(IServiceCollection services)
 2         {
 3             //定义自己的策略
 4             var reg = services.AddPolicyRegistry();
 5             //根据返回的状态码自定义自己的返回策略
 6             reg.Add("retryforever", Policy.HandleResult<HttpResponseMessage>(message =>
 7             {
 8                 return message.StatusCode == System.Net.HttpStatusCode.Created;
 9             }).RetryForeverAsync());
10             //配置httpclient使用retryforever 的策略
11             services.AddHttpClient("myClient2").AddPolicyHandlerFromRegistry("retryforever");
12             //根据HttpRequestMessage 来定义策略
13             services.AddHttpClient("myClient3").AddPolicyHandlerFromRegistry((registry, message) =>
14             {
15                 return message.Method == HttpMethod.Get ? registry.Get<IAsyncPolicy<HttpResponseMessage>>("retryforever") : Policy.NoOpAsync<HttpResponseMessage>();
16             });
17         }

熔断策略

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

高级熔断策略

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

服务降级策略

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

熔断降级时,定义友好的返回值

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

限流策略

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

 

 参考地址:

http://www.thepollyproject.org/  

https://github.com/App-vNext/Polly.git  

https://github.com/App-vNext/Polly.Extensions.Http.git 

https://github.com/App-vNext/Polly-Samples.git  

 

Polly:提升服务可用性

原文:https://www.cnblogs.com/dotnetcore-cnblogs/p/12774144.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!