.NET微服务从0到1:服务容错(Polly)

Polly.NET 平台下的一个弹性和瞬态故障处理库,它允许开发人员以流畅和线程安全的方式表达策略,如重试、熔断器、超时、舱壁隔离和回退等

重试

进行一次重试

Retry() 无参数表示重试一次

private static async Task RetryOnce()
{
    var policy = Policy.Handle<CustomException>()
        .Retry(3);
    await policy.Execute(() => FooFunction());
}

执行结果
在这里插入图片描述

进行多次重试

Retry(N)表示执行N此重试

var policy = Policy.Handle<CustomException>()
    .Retry(3);
await policy.Execute(() => FooFunction());

执行结果
在这里插入图片描述

一直重试直到成功

使用RetryForever()不断重试

private static async Task RetryForeverUntilSuccess()
{
    var policy = Policy.Handle<CustomException>()
        .RetryForever();
    await policy.Execute(() => FooFunction());
}

执行结果
在这里插入图片描述

等待指定时间后重试

使用WaitAndRetry()WaitAndRetryAsync()在指定等待时间后重试

private static async Task RetryAfterWait()
{
    var policy = Policy.Handle<CustomException>()
        .WaitAndRetryAsync(new[]
        {
            TimeSpan.FromSeconds(1),
            TimeSpan.FromSeconds(2),
            TimeSpan.FromSeconds(4)
        });
    await policy.ExecuteAsync(() => FooFunction());
}

在这里插入图片描述

等待指定时间后不断重试直到成功

使用WaitAndRetryForever()WaitAndRetryForeverAsync()在等待指定实际后不断重试,知道成功

private static async Task RetryForeverUntilSuccessAfterWait()
{
    var policy = Policy.Handle<CustomException>()
        .WaitAndRetryForeverAsync(retryAttempt =>
        TimeSpan.FromSeconds(1));
    await policy.ExecuteAsync(() => FooFunction());
}

在这里插入图片描述

每一次重试前的自定义逻辑处理

每一次重试前,我们可以自定义一些逻辑处理,比如日志记录等。

private static async Task RetryManyWithCustomLogic()
{
    var policy = Policy.Handle<CustomException>()
        .Retry(3, onRetry: (exception, retryCount) =>
        {
            Console.WriteLine($"{nameof(RetryManyWithCustomLogic)},第{retryCount}重试:{exception.Message}");
        });
    await policy.Execute(() => FooFunction());
}

执行结果
在这里插入图片描述

熔断

使用CircuitBreaker对调用进行熔断控制

public static async Task CircuitBreaker()
{
    // 熔断策略:如果连续3次出发了CustomException异常,将在2秒内终止所有请求
    var policy = Policy.Handle<CustomException>()
        .CircuitBreaker(3, TimeSpan.FromSeconds(2));
    for (int i = 0; i < 10; i++)    // 模拟10次调用
    {
        try
        {
            await policy.Execute(() => FooFunction());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            await Task.Delay(1000);
        }
    }
}

执行结果
在这里插入图片描述

回退(Fallback)

Fallback可以让我们程序咋发生一些故障时,提供备份操作(应急计划)

public static void Fallback()
{
    var policy = Policy.Handle<CustomException>()
        .Fallback(async () => FunctionFallback());
    policy.Execute(() => Function());
}

在这里插入图片描述

上文中的一些省略的代码

  • 定义一个异常/故障
class CustomException : Exception
{
    public CustomException(string message) : base(message){}
}
  • 要执行的函数
static int ctr = 0;
static Task FooFunction()
{
    ctr++;
    if (ctr >= 11)  // 假设重试10次执行成功
    {
        return default;
    }
    Console.WriteLine($"{DateTime.Now:HH:mm:ss fff} {nameof(FooFunction)}:第{ctr}次执行");
    throw new CustomException($"{nameof(FooFunction)}发生异常");
}
static void Function()
{
    try
    {
        throw new CustomException($"{nameof(Function)}发生异常");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"执行{nameof(Function)}发生异常:{ex.Message}");
        throw;
    }
}

static void FunctionFallback()
{
    Console.WriteLine($"执行{nameof(FunctionFallback)}");
}
  • 主函数
static async Task Main(string[] args)
{
    Console.WriteLine("开始执行");
    try
    {
       await RetryOnce();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"{nameof(Main)}发生异常:{ex.Message}");
    }
    finally
    {
        Console.WriteLine("执行结束");
    }
}

参考

ASP VNext 开源服务容错处理库Polly使用文档

posted @ 2020-03-20 22:40  江浙沪柯蓝  阅读(356)  评论(0编辑  收藏  举报