雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

Polly瞬态故障处理熔断降级用法

2024-09-08 13

Polly是一个被.NET基金会认可的弹性和瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如行重试,断路,超时,故障恢复等策略,其主要功能如下:重试(Retry)断路器(Circuit-Breaker)超时检测(Timeout)缓存(Cache)降级(Fallback)。

首先通过NuGet安装Polly,我当前使用的是最新7.2.1版本的Polly。

Polly的基本使用方法:定义故障,当发生了HttpRequestException异常的时候,就会触发策略。指定策略。

以下示例代码,定义了在执行某业务代码时如果出现HttpRequestException异常就是出现故障,会触发降级策略。

Policy.Handle<HttpRequestException>().
                Fallback(()=> { 
                    // 降级方法
                }).Execute(()=> {
                    // 业务方法,一般是跨服务的调用,可以合HttpClient结合使用
                    throw new HttpRequestException();
                });

Polly故障的定义方法

// 单个异常的故障
Policy.Handle<Exception>();
// 带条件的异常类型
Policy.Handle<Exception>(ex => ex.Message.Contains("xxx"));
// 多个异常类型带条件
Policy.Handle<HttpRequestException>(ex => ex.Message.Contains("xxx"))
.Or<ArgumentException>()
.Or<NetworkInformationException>();

注意:Polly是故障处理库,一般定义服务调用环节产生的不可控的异常作为故障(请求出错等不可控的异常)。业务代码出现异常不需要Polly。

Polly弹性策略

// 默认重试一次
Policy.Handle<Exception>().Retry();//.Execute(() => { });
// 重试N次
Policy.Handle<Exception>().Retry(3, (ex, i) =>
{
    //委托,可以做一些日志记录等操作
});
// 无限重试直到成功(不推荐)
Policy.Handle<Exception>().RetryForever();
// 重试且等待
Policy.Handle<Exception>().WaitAndRetry(new[] {
    TimeSpan.FromSeconds(1),
    TimeSpan.FromSeconds(1),
    TimeSpan.FromSeconds(1)
});
// 重试且等待2的i(次数)次方
Policy.Handle<Exception>().WaitAndRetry(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)));
// 每一种策略最后一个参数都是一个委托,这个委托就是异常委托
// 断路器,非常使用的策略
// 连续触发了指定(2)次数的故障后,就开启断路器(OPEN),进入熔断状态,1分钟
// 断路器有三种状态,OPEN CLOSED HALF-OPEN
var breaker = Policy.Handle<HttpRequestException>().CircuitBreaker(2, TimeSpan.FromMinutes(1),
    (exception,span)=> { },//OPEN 断路器开启
    ()=> { });//CLOSE 断路器关闭
//breaker.CircuitState = Polly.CircuitBreaker.CircuitState.Closed;
//breaker.CircuitState = Polly.CircuitBreaker.CircuitState.HalfOpen;
//breaker.CircuitState = Polly.CircuitBreaker.CircuitState.Open;
// 这个不是断路器模式的状态,这个是Polly断路器策略里的一种特殊状态
// 手动的打开断路器,断路器:手动开启状态
//breaker.CircuitState = Polly.CircuitBreaker.CircuitState.Isolated;
// 手动开启断路器,断路器默认是关闭的
breaker.Isolate();
// 手动关闭断路器
breaker.Reset();
// 如果再故障采样持续时间内,导致处理异常的操作的比例超过故障阈值,则发生熔断
// 前提是再次期间,通过断路器的操作的数量至少是最小吞吐量
Policy.Handle<HttpRequestException>().AdvancedCircuitBreaker(
    0.5,// 故障阈值,50%
    TimeSpan.FromSeconds(10),// 故障采样时间,10秒
    8,// 最小吞吐量,10秒内最少执行了8次操作
    TimeSpan.FromSeconds(30)// 熔断时间,30秒
    );
// 熔断30秒后,变成HALF-OPEN,半开启状态,
// 断路器会尝试着释放(1次)操作,如果成功就变成CLOSE,如果失败断路器打开OPEN(30秒)

// 超时,服务调用慢也是故障,自己定义n秒
// 不会用单独策略,只会用策略组合
// 超时不需要定义故障
Policy.Timeout(3, (context, span, arg3, arg4) =>
{
    // arg4 is TimeoutRejectedException
    // 委托可选
}).Execute(() => { });
// 舱壁隔离,通过控制并发数量来管理负载。主动式策略也不需要定义故障
// 最大并发数12,超过12的都拒绝掉
Policy.Bulkhead(12).Execute(()=> { });
// 超过12个的最多20个等待
Policy.Bulkhead(12,20).Execute(() => { });

// 缓存比较复杂,以来其他库,集合Redis
// Policy.Cache()

Polly策略包装 策略组合

// 降级策略
var fullback = Policy.Handle<Exception>().
    Fallback(() =>
    {
        Console.WriteLine("Polly Fallback!");
    });
// 重试策略
var retry = Policy.Handle<Exception>().Retry(3, (ex, i) =>
{
    Console.WriteLine($"retryCount:{i}");
    //委托,可以做一些日志记录等操作
});
// 如果重试3次仍然发生故障就降级
var policy = Policy.Wrap(fullback, retry);
policy.Execute(() => {
    Console.WriteLine("Polly Begin");
    throw new Exception("Error");
});

策略组合运行结果:

更新于:8天前
赞一波!

文章评论

全部评论