.Net Core 之 Polly 策略

Polly 是一个 .NET 弹性和瞬态故障处理库,允许开发人员以流畅和线程安全的方式表达重试、断路器、超时、隔板隔离、速率限制和回退等策略。

查看源码或者一些基础用法点击了解详情, 如果想更深入的了解,点击进入官网。

polly提供的几种弹性策略:

 

普通用法

引用NuGet包:

Install-Package Polly

 悲观超时(TimeoutStrategy.Pessimistic),依然会返回结果

int res = 0;
var testPolicy = Policy.Timeout(5, TimeoutStrategy.Pessimistic, (context, timespan, task) =>
{
    res = 1;
    Console.WriteLine("你已经超时了");
});

try
{
    testPolicy.Execute(() =>
    {
        Console.WriteLine("开始执行方法");
        Thread.Sleep(10000);
        Console.WriteLine("执行结束了");
        res = 2;
    });
}
catch (Exception ex)
{
    Console.WriteLine("异常了");
}
Console.WriteLine("最后的结果是:" + res);
View Code

乐观超时(TimeoutStrategy.Optimistic),不会返回结果

var testPolicy = Policy.TimeoutAsync(5, TimeoutStrategy.Optimistic, (context, timespan, task) =>
{
    Console.WriteLine("你已经超时了");
});
try
{
    var str = testPolicy.ExecuteAsync<string>((cancel) =>
    {
        //如果5秒钟超时会触发
        cancel.Register(() => {

            Console.WriteLine("你已经超时了 ");
        });
        Console.WriteLine("开始执行方法");
        Thread.Sleep(1000);
        Console.WriteLine("执行结束了");
        return Task.FromResult(res.ToString());
    }, CancellationToken.None);
}
catch (Exception ex)
{
    Console.WriteLine("异常了");
}
View Code

重试

try
{
    var policy = Policy.Handle<Exception>().Retry(5, (exception, count, context) =>
    {
        Console.WriteLine($"第{count}次异常,异常信息:{exception.Message}");
    });
    Console.WriteLine("开始执行");
    policy.Execute(() =>
    {
        throw new Exception("我异常了");
    });
}
catch (Exception ex)
{
    Console.WriteLine("进入最后的异常了");
}
View Code

重试等待

try
{
    var policy = Policy.Handle<Exception>().WaitAndRetryAsync(5,
        (count) => {
            //每次等待时间一致
            //return TimeSpan.FromSeconds(5);
            //根据次数等待时间不一样
            return TimeSpan.FromSeconds(5 * count);
        },
        (exception,timespan, count, context) =>
        {
            Console.WriteLine($"第{count}次异常,等待时间:{timespan.TotalSeconds},异常信息:{exception.Message}");
        });
    Console.WriteLine("开始执行");
    await policy.ExecuteAsync(() =>
    {
        throw new Exception("我异常了");
    });
}
catch (Exception ex)
{
    Console.WriteLine("进入最后的异常了");
}
View Code

熔断

try
{
    //如果10秒内异常达到2次,则触发熔断,10秒之内不会访问方法体,只会返回熔断异常,10秒之后才会请求方法体
    var policy = Policy.Handle<Exception>().CircuitBreakerAsync(2,TimeSpan.FromSeconds(10),
        (exception, timespan) => {
            Console.WriteLine($"开始等待:{timespan.TotalSeconds} s, 异常信息:{exception.Message}");
        },
        //如果等待10秒钟之后可以正常访问就会触发
        () =>
        {
            Console.WriteLine("熔断重置");
        },
        //每隔10秒钟触发
        () => {
            Console.WriteLine("正在打开或者关闭熔断");
        }
        );
    Console.WriteLine("开始执行");
    for (int i = 0; i < 20; i++)
    {
        Thread.Sleep(1000);
        try
        {
            await policy.ExecuteAsync(() =>
            {
                throw new Exception("我异常了");
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

}
catch (Exception ex)
{
    Console.WriteLine("进入最后的异常了");
}
View Code

降级

try
{
    //如果10秒内异常达到2次,则触发熔断,10秒之内不会访问方法体,只会返回熔断异常,10秒之后才会请求方法体
    var policy = Policy<string>.Handle<Exception>().FallbackAsync((context,token) => {
        return Task.FromResult("降级异常");
    }, (exception, context) => {
        return Task.FromResult("降级异常2");
    });
    Console.WriteLine("开始执行");
    var res =  await policy.ExecuteAsync(() =>
    {
        throw new Exception("我异常了");
    });
    Console.WriteLine(res);
}
catch (Exception ex)
{
    Console.WriteLine("不会进入这个异常");
}
View Code

请求限速

try
{
    var rateLimit = Policy.RateLimit(2, TimeSpan.FromSeconds(1),6);

    for (int a = 0; a < 10; a++)
    {
        Thread.Sleep(500);
        for (int i = 0; i < 500; i++)
        {
            rateLimit.Execute(() => {
                Console.WriteLine("执行");
            });
        }
    }

}
catch (RateLimitRejectedException ex)
{
    Console.WriteLine("策略异常" + ex.Message);
}
View Code

 

在HttpClient拓展

引用NuGet包:

Install-Package Polly
Install-Package Microsoft.Extensions.Http.Polly

 

// 1、自定义异常处理(用缓存处理)
var fallbackResponse = new HttpResponseMessage
{
    Content = new StringContent("系统正繁忙,请稍后重试"),// 内容,自定义内容
    StatusCode = HttpStatusCode.BadRequest // 定义返回的StatusCode
};

services.AddHttpClient("mrico")
    // 1.1 降级(捕获异常,进行自定义处理)
    .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().FallbackAsync(fallbackResponse, async b =>
                {
                    // 1、降级打印异常
                    Console.WriteLine($"开始降级,异常消息:{b.Exception.Message}");
                    // 2、降级后的数据
                    //Console.WriteLine($"降级内容响应:{}");
                    await Task.CompletedTask;
                }))
    // 1.2 熔断机制
    .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().CircuitBreakerAsync(3, TimeSpan.FromSeconds(10), (ex, ts) =>
                {
                    Console.WriteLine($"断路器开启,异常消息:{ex.Exception.Message}");
                    Console.WriteLine($"断路器开启时间:{ts.TotalSeconds}s");
                }, () =>
    {
        Console.WriteLine($"断路器重置");
    }, () =>
    {
        Console.WriteLine($"断路器半开启(一会开,一会关)");
    }))
     // 1.3 失败重试
     .AddPolicyHandler(Policy<HttpResponseMessage>
            .Handle<Exception>()
            .WaitAndRetryAsync(50, (trycount) =>
            {
                return TimeSpan.FromSeconds(2 * trycount); //每次等待的时间
            }))
    //1.4、超时
    .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic, (context, timespan, task) => {
            return Task.FromResult(fallbackResponse);
          }));
View Code

 

posted @ 2023-02-15 16:28  Joni是只狗  阅读(193)  评论(0编辑  收藏  举报