Git 源码 :https://github.com/tangsong1995/TS.Microservices
CSDN 资源 :https://download.csdn.net/download/qq_33649351/34675095
系列文章目录 :https://blog.csdn.net/qq_33649351/article/details/120998558
使用 AddTransientHttpErrorPolicy 添加瞬时 Http 请求失败策略:
public static IHttpClientBuilder AddPolly(this IHttpClientBuilder builder)
{
builder.AddTransientHttpErrorPolicy(p => p.RetryAsync()); // p.RetryAsync() 表示重试一次,可指定重试次数
return builder;
}
AddTransientHttpErrorPolicy 表示在以下情况会触发失败策略:
使用 WaitAndRetryAsync 指定重试时间间隔:
public static IHttpClientBuilder AddPolly(this IHttpClientBuilder builder)
{
builder.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(1 * 2)));
return builder;
}
使用 WaitAndRetryForeverAsync ,直到请求成功,否则一直重试:
public static IHttpClientBuilder AddPolly(this IHttpClientBuilder builder)
{
builder.AddTransientHttpErrorPolicy(p => p.WaitAndRetryForeverAsync(i => TimeSpan.FromSeconds(1 * 2)));
return builder;
}
自定义重试策略:
var reg = services.AddPolicyRegistry();
reg.Add("retryforever", Policy.HandleResult<HttpResponseMessage>(message =>
{
return message.StatusCode == System.Net.HttpStatusCode.Created;
}).RetryForeverAsync());
services.AddHttpClient("httpclient").AddPolicyHandlerFromRegistry("retryforever");
通过注入委托实现动态定义重试策略:
var reg = services.AddPolicyRegistry();
reg.Add("retryforever", Policy.HandleResult<HttpResponseMessage>(message =>
{
return message.StatusCode == System.Net.HttpStatusCode.Created;
}).RetryForeverAsync());
services.AddHttpClient("httpclient").AddPolicyHandlerFromRegistry((registry, message) =>
{
// Get请求执行重试策略,其他请求不执行
return message.Method == HttpMethod.Get ? registry.Get<IAsyncPolicy<HttpResponseMessage>>("retryforever") : Policy.NoOpAsync<HttpResponseMessage>();
});
添加熔断策略:
services.AddHttpClient("httpclient").AddPolicyHandler(Policy<HttpResponseMessage>.Handle<HttpRequestException>().CircuitBreakerAsync(
handledEventsAllowedBeforeBreaking: 10,
durationOfBreak: TimeSpan.FromSeconds(10),
onBreak: (r, t) => { },
onReset: () => { },
onHalfOpen: () => { }
));
handledEventsAllowedBeforeBreaking:在报错十次后进行熔断
durationOfBreak:熔断时间
onBreak:发生熔断时触发的事件
onReset:熔断恢复时触发的事件
onHalfOpen:恢复之前验证服务是否可用(打一部分流量验证)
根据请求失败比例配置熔断策略:
services.AddHttpClient("httpclient").AddPolicyHandler(Policy<HttpResponseMessage>.Handle<HttpRequestException>().AdvancedCircuitBreakerAsync(
failureThreshold: 0.8,
samplingDuration: TimeSpan.FromSeconds(10),
minimumThroughput: 100,
durationOfBreak: TimeSpan.FromSeconds(20),
onBreak: (r, t) => { },
onReset: () => { },
onHalfOpen: () => { }));
failureThreshold:请求失败比例,达到比例时进行熔断
samplingDuration:采样时间,在此规定的时间范围内请求有80%失败则进行熔断
minimumThroughput:最小吞吐量,采样时间内请求小于此数量时,不论失败比例是多少,都不触发熔断
当触发熔断时,会抛出熔断异常 BrokenCircuitException,我们可以为为熔断异常配置降级响应:
//熔断策略
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 fallbackBreak = Policy.WrapAsync(fallback, breakPolicy);
services.AddHttpClient("httpclient").AddPolicyHandler(fallbackBreak);
上面代码的意义是:在十秒内,请求量超过100,并且失败比例超过80%时,触发熔断;并且会对 BrokenCircuitException 熔断异常进行降级,响应友好结果。
定义限流策略:
//限流策略
var bulk = Policy.BulkheadAsync<HttpResponseMessage>(
maxParallelization: 30,
maxQueuingActions: 20,
onBulkheadRejectedAsync: contxt => Task.CompletedTask
);
services.AddHttpClient("httpclient").AddPolicyHandler(bulk);
maxParallelization:最大并发量
maxQueuingActions:最大队列数量
onBulkheadRejectedAsync:超出最大并发量和最大队列数量时的处理逻辑
当触发限流时,会抛出限流异常 BulkheadRejectedException,我们可以为为限流异常配置降级响应:
//限流策略
var bulk = Policy.BulkheadAsync<HttpResponseMessage>(
maxParallelization: 30,
maxQueuingActions: 20,
onBulkheadRejectedAsync: contxt => Task.CompletedTask
);
var fallback2 = Policy<HttpResponseMessage>.Handle<BulkheadRejectedException>().FallbackAsync(new HttpResponseMessage()
{
Content = new StringContent("{}")
});
var fallbackbulk = Policy.WrapAsync(fallback2, bulk);
services.AddHttpClient("httpclient").AddPolicyHandler(fallbackbulk);
上面代码的意义是:当超出最大并发量30,且超出队列数量20时,触发限流;并且会对 BulkheadRejectedException 限流异常进行降级,响应友好结果。
public class MyAsyncCacheProvider : IAsyncCacheProvider
{
public Task PutAsync(string key, object value, Ttl ttl, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
throw new NotImplementedException();
}
public Task<(bool, object)> TryGetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
throw new NotImplementedException();
}
}
services.AddSingleton<IAsyncCacheProvider, MyAsyncCacheProvider>();
var serviceProvider = services.BuildServiceProvider();
var cachePolicy = Policy.CacheAsync<HttpResponseMessage>(serviceProvider.GetRequiredService<IAsyncCacheProvider>(), TimeSpan.FromSeconds(10));
services.AddHttpClient("httpclient").AddPolicyHandler(cachePolicy);
定义熔断、降级、重试策略,然后组合起来:
//熔断策略
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("httpclient").AddPolicyHandler(fallbackBreak);
组合策略的顺序,与中间件类似,后注册的执行在最内层,也就是最先起作用。
熔断、限流及缓存策略都是有状态的。其他策略是无状态的。需要为不同服务定义各自的策略。
如有以下限流策略:
//限流策略
var bulk = Policy.BulkheadAsync<HttpResponseMessage>(
maxParallelization: 30,
maxQueuingActions: 20,
onBulkheadRejectedAsync: contxt => Task.CompletedTask
);
services.AddHttpClient("httpclient").AddPolicyHandler(bulk);
services.AddHttpClient("httpclient2").AddPolicyHandler(bulk);
那么 httpclient 和 httpclient2 两个服务的请求会共享 maxParallelization 和 maxQueuingActions 。