Polly重试回退熔断策略组合示例
2024-09-08
42
Polly重试回退熔断策略组合示例
假设服务A是一个集群(2个节点),首先调用其中一个节点的服务,如果失败或者超时,则用轮询的方式进行重试调用。
重试多次仍然失败,则直接返回一个替代数据(服务降级),之后一段时间,服务被熔断。再熔断时间内,所有对该服务的调用都以替代数据返回。
熔断时间过后,尝试再次调用,如果成功,则关闭熔断器,服务通道打通。否则,继续熔断这个服务一段时间。
要用到几个策略?超时策略,重试策略,断路器策略,回退策略(降级),策略组合。
实现代码如下
namespace ConsulTest
{
public class PolicyBuilder
{
public static ISyncPolicy CreatePolly() {
// 超时1秒
var timeoutPolicy = Policy.Timeout(1, (context, timespan, task) => {
Console.WriteLine("执行超时,抛出TimeoutRejectedException异常");
});
// 重试2次
var retryProlicy = Policy.Handle<Exception>().WaitAndRetry(2,
retryAttempt => TimeSpan.FromSeconds(2),
(exception, timespan, retryCount, context) => {
Console.WriteLine($"{DateTime.Now} = 重试 {retryCount} 次 - 抛出{exception.GetType()}");
});
// 连续发生两次故障,就熔断3秒
var circuitBreakerPolicy = Policy.Handle<Exception>().CircuitBreaker(
// 熔断前允许出现几次错误
2,
// 熔断时间
TimeSpan.FromSeconds(3),
// 熔断时触发
onBreak: (ex, breakDelay) =>
{
Console.WriteLine($"{DateTime.Now} - 断路器:开启状态(熔断时触发)");
},
// 熔断回恢复时触发
onReset:()=> {
Console.WriteLine($"{DateTime.Now} - 断路器:关闭状态(熔断恢复时触发)");
},
// 熔断时间到了之后触发,尝试放行少量(1次)的请求
onHalfOpen:()=> {
Console.WriteLine($"{DateTime.Now} - 断路器:半开启状态(熔断时间到了之后触发)");
});
// 回退策略,降级
var fallbackPolicy = Policy.Handle<Exception>().Fallback(() => {
Console.WriteLine("这是一个Fallback");
}, exception => {
Console.WriteLine($"Fallback异常:{exception.GetType()}");
});
// 策略从右到左依次进行调用
return Policy.Wrap(fallbackPolicy, circuitBreakerPolicy, retryProlicy, timeoutPolicy);
}
}
}
测试代码如下,服务注册和服务发现代码可以参考
.NET Core Consul服务注册
.NET Core Consul服务发现
Polly瞬态故障处理熔断降级用法
namespace ConsulTest
{
public class ConsulBasic
{
public static void Run() {
var serviceProvider = new ConsulServiceProvider(new Uri("http://192.168.31.175:8500"));
var aspNetCoreService = serviceProvider.CreateServiceBuilder(builder => {
builder.ServiceName = "AspNetCore";
builder.LoadBalancer = TypeLoadBalancer.RoundRobinLoad;//可选RandomLoad
builder.UriScheme = Uri.UriSchemeHttp;
});
var httpClient = new HttpClient();
var policy = PolicyBuilder.CreatePolly();
for (int i = 0; i < 100; i++)
{
Console.WriteLine($"----------第{i}次请求-----------");
policy.Execute(() => {
try
{
var uri = aspNetCoreService.BuildAsync("/Health").Result;
Console.WriteLine($"{DateTime.Now} - 正在调用:{uri}");
var content = httpClient.GetStringAsync(uri).Result;
Console.WriteLine($"返回结果:{content}");
}
catch (Exception ex)
{
Console.WriteLine("调用异常:"+ex.GetType());
// 如果你要在策略里捕捉异常,如果这个异常还是你定义的故障,一定要把这个异常抛出来
throw ex;
}
});
Task.Delay(500).Wait();
}
Console.ReadLine();
}
}
}
我关闭两个服务,并且运行程序,结果如下
可以看到
首先判断调用是否超时,如果超时就会触发异常,发生超时故障,然后就触发重试策略
如果重试两次中只要成功一次,就直接返回调用结果
如果重试两次都失败,第三次再次失败,就会发生故障
重试之后是断路器策略,所以这个故障会被断路器接收,当断路器收到两次故障,就会触发熔断,也就是说断路器开启
断路器开启的3秒内,任何故障或者操作,都会通过断路器到达回退策略,触发降级操作
3秒后,断路器进入到半开启状态,操作可以正常执行
接下来我开启一个服务,运行结果如下
在断路器半开启状态时,调用服务成功了,于是断路器被关闭了。
更新于:4个月前赞一波!1
相关文章
文章评论
评论问答