httpClient 请求接口失败要重试,一般人想到的可能是 做try catch 然后循环请求,但是这种方法写起来很麻烦,而且不优雅。今天就说下另外一种重试的方法,就是引入Microsoft.Extensions.Http.Polly,来进行请求的重试。
Polly 添加策略分为三种:
1. AddTransientHttpErrorPolicy:是处理Http请求的错误,如HTTP 5XX 的状态码,HTTP 408 的状态码 以及System.Net.Http.HttpRequestException异常
2. AddPolicyHandler:添加自定义策列
3. AddPolicyHandlerFromRegistry:从Policy注册表集合里面选择添加
1. AddTransientHttpErrorPolicy
//错误重试上面是间隔都是500毫秒
services.AddHttpClient("client1")
.AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(3, t => TimeSpan.FromMilliseconds(500))));
或者
//定义每次重试的时间间隔
services.AddHttpClient("client1")
.AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] {
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(30)
})
2. AddPolicyHandler
先定义策略,通过AddPolicyHandler方法添加,该方法接收一个泛型的IAsyncPolicy<HttpResponseMessage>。HttpResponseMessage我理解为出站请求上下文
var retryPolicy = Policy.Handle<HttpRequestException>()
.OrResult<HttpResponseMessage>(response => {
//异常处理的逻辑
return true;
}).WaitAndRetryAsync(3,t => TimeSpan.FromMilliseconds(50));
services.AddHttpClient("client1")
.AddPolicyHandler(retryPolicy);
3. AddPolicyHandlerFromRegistry
先注册策略表服务,为策略表添加策略,最后通过AddPolicyHandlerFromRegistry方法选用某个或几个策略
//注册,策略表服务
var registry = services.AddPolicyRegistry();//创建策略var retryPolicy = Policy.Handle<HttpRequestException>().OrResult<HttpResponseMessage>(response => {//异常处理的逻辑return true;
}).WaitAndRetryAsync(3, t => TimeSpan.FromMilliseconds(500));registry.Add("registry1", retryPolicy);
services.AddHttpClient("client1")
.AddPolicyHandlerFromRegistry("registry1");
做一个例子看下,创建一个控制台程序
using Microsoft.Extensions.DependencyInjection;
using Polly;
using System;
using System.Net.Http;
namespace ConsoleAppTest
{ class Program
{ static void Main(string[] args)
{ Console.WriteLine("Hello World!");
var service = new ServiceCollection();
service.AddHttpClient("client1").AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(3, t => TimeSpan.FromMilliseconds(500)));
IHttpClientFactory httpClientFactory = service.BuildServiceProvider().GetService<IHttpClientFactory>(); var httpClient = httpClientFactory.CreateClient("client1");
var response = httpClient.GetAsync("http://www.pikoudai.com/");
Console.ReadKey(); } }}
这里的http://www.pikoudai.com/ 其实是访问不通的,就是要看看重试是否生效了。
抓包看下程序效果:
可以看到http://www.pikoudai.com/访问了一次,之后又重试了3次。
Polly除了重试功能外还有断路器、超时、隔板隔离、回退、缓存等功能
重试策略(Retry)
重试策略针对的前置条件是短暂的故障延迟且在短暂的延迟之后能够自我纠正。允许我们做的是能够自动配置重试机制。
断路器(Circuit-breaker)
断路器策略针对的前置条件是当系统繁忙时,快速响应失败总比让用户一直等待更好。保护系统故障免受过载,Polly可以帮其恢复。
超时(Timeout)
超时策略针对的前置条件是超过一定的等待时间,想要得到成功的结果是不可能的,保证调用者不必等待超时。
隔板隔离(Bulkhead Isolation)
隔板隔离针对的前置条件是当进程出现故障时,多个失败一直在主机中对资源(例如线程/ CPU)一直占用。下游系统故障也可能导致上游失败。这两个风险都将造成严重的后果。都说一粒老鼠子屎搅浑一锅粥,而Polly则将受管制的操作限制在固定的资源池中,免其他资源受其影响。
缓存(Cache)
缓存策略针对的前置条件是数据不会很频繁的进行更新,为了避免系统过载,首次加载数据时将响应数据进行缓存,如果缓存中存在则直接从缓存中读取。
回退(Fallback)
操作仍然会失败,也就是说当发生这样的事情时我们打算做什么。也就是说定义失败返回操作。