c#:从Polly库看ocelot的熔断机制

环境:

  • window 10 x64 企业版
  • vs2019 企业版 16.7.5
  • Polly 7.2.1
  • Ocelot.Provider.Polly 16.0.1

说明:

在上一篇《c#:Ocelot熔断机制体验》,我实验了Ocelot的熔断机制,但在我试验的过程中,发现后台服务报500异常并不会被ocelot计入熔断的触发条件,这引起了我的好奇。
于是,我找到Ocelot.Provider.Polly的源码以及Polly的介绍,出了这篇文章。

参照:.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制

一、Polly的介绍和功能实验

Polly是一种开源的.NET弹性和瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如行重试,断路,超时,故障恢复等策略。

Polly的github地址:https://github.com/App-vNext/Polly

下面先实验Polly的功能,然后再看Ocelot.Provider.Polly的源码。
首先我们新建一个.net core控制台工程,然后引入Polly

<ItemGroup>
  <PackageReference Include="Polly" Version="7.2.1" />
</ItemGroup>

1.1 Polly中的降级

所谓降级就是,当我们指定的代码处理失败时就执行我们备选的代码。

看下面实例:

/// <summary>
/// 降级
/// </summary>
public static void Case1()
{
    ISyncPolicy policy = Policy.Handle<ArgumentException>()
        .Fallback(() =>
        {
            Console.WriteLine("Error occured");
        });

    policy.Execute(() =>
    {
        Console.WriteLine("Job Start");

        throw new ArgumentException("Hello Polly!");

        Console.WriteLine("Job End");
    });
}

运行这个方法,我们将得到下图:
在这里插入图片描述
这个很好理解。

1.2 Polly中的重试

所谓重试就是当我们指定的代码运行失败后,我们再让他重复运行几次。

看下面实例:

 /// <summary>
 /// 重试
 /// </summary>
 public static void Case2()
 {
     ISyncPolicy policy = Policy.Handle<Exception>().Retry(3);

     try
     {
         policy.Execute(() =>
         {
             Console.WriteLine("Job Start");
             throw new Exception("Special error occured");
             Console.WriteLine("Job End");
         });
     }
     catch (Exception ex)
     {
         Console.WriteLine("There's one unhandled exception : " + ex.Message);
     }
 }

运行后如下图所示:
在这里插入图片描述
上面的也很好理解,我们先运行一次,失败后运行我们指定的重试次数(3),然后又失败了,抛出异常结束。

1.3 Polly中的熔断

所谓熔断就是:我们指定的代码连续运行多次都失败,那么就让这块代码进入熔断状态并持续一会,之后所有再次尝试调用这块代码都将直接抛出异常。当这块代码度过熔断状态后,会立刻进入半熔断状态,之后这块代码运行的第一次会被特殊观察,如果运行成功则进入正常状态,否则重新触发熔断。

看下面实例:

/// <summary>
 /// 熔断
 /// </summary>
 public static void Case3()
 {
     // Stop for 3s after retry 3 times
     ISyncPolicy policy = Policy.Handle<Exception>()
         .CircuitBreaker(3, TimeSpan.FromSeconds(3));

     while (true)
     {
         try
         {
             policy.Execute(() =>
             {
                 Console.WriteLine("Job Start");
                 throw new Exception("Special error occured");
                 Console.WriteLine("Job End");
             });
         }
         catch (Exception ex)
         {
             Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\tThere's one unhandled exception : " + ex.Message);
         }

         Thread.Sleep(500);
     }
 }

运行上面代码,输出如下:
在这里插入图片描述
可以看到,一开始连续运行了三次都失败后触发熔断,经过3秒后,再运行一次,发现失败后就立刻触发熔断,经过3秒后,。。。

1.4 Polly中的超时

所谓超时,就是我们指定一段代码的最大运行时间,如果超过这段时间还没有完成,就直接抛出异常。
这里判断超时有两种策略:一个是悲观策略(Pessimistic),一个是乐观策略(Optimistic)。一般我们用悲观策略。需要注意的是,虽然超时抛除了异常,但这段代码的运行并没有停止!

看下面实例代码:

/// <summary>
/// 超时
/// </summary>
public static void Case4()
{
    try
    {
        ISyncPolicy policyTimeout = Policy.Timeout(3, Polly.Timeout.TimeoutStrategy.Pessimistic);
        policyTimeout.Execute(() =>
        {
            Console.WriteLine("Job Start...");
            Thread.Sleep(5000);
            Console.WriteLine("Job End...");
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Unhandled exception : {ex.GetType()} : {ex.Message}");
    }
}

运行后输出如下:
在这里插入图片描述
这个不难理解。

1.5 Polly中组合超时和降级

所谓组合超时和降级就是Polly发现代码超时后就运行我们指定的备选代码。

直接看下面代码:

/// <summary>
/// 超时后降级
/// </summary>
public static void Case5()
{
    try
    {
        ISyncPolicy policyException = Policy.Handle<TimeoutRejectedException>()
            .Fallback(() =>
            {
                Console.WriteLine("Fallback");
            });
        ISyncPolicy policyTimeout = Policy.Timeout(3, Polly.Timeout.TimeoutStrategy.Pessimistic);
        ISyncPolicy mainPolicy = Policy.Wrap(policyException, policyTimeout);
        mainPolicy.Execute(() =>
        {
            Console.WriteLine("Job Start...");
            Thread.Sleep(5000);
            Console.WriteLine("Job End...");
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Unhandled exception : {ex.GetType()} : {ex.Message}");
    }
}

运行后输出如下:
在这里插入图片描述
这个也很好理解。

1.6 Polly中组合超时和熔断

所谓组合超时和熔断就是指定的代码连续运行超时后抛出异常,被熔断捕捉后达到阈值,从而触发熔断。

直接看下面代码:

/// <summary>
/// 超时后熔断
/// </summary>
public static void Case6()
{
    ISyncPolicy policyTimeout = Policy.Timeout(3, Polly.Timeout.TimeoutStrategy.Pessimistic);
    ISyncPolicy policyCircuitBreaker = Policy.Handle<Exception>()
    .CircuitBreaker(3, TimeSpan.FromSeconds(3));
    ISyncPolicy mainPolicy = Policy.Wrap(policyCircuitBreaker, policyTimeout);
    while (true)
    {
        try
        {
            mainPolicy.Execute(() =>
            {
                Console.WriteLine("Job Start...");
                Thread.Sleep(5000);
                //Console.WriteLine("Job End...");
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Unhandled exception : {ex.GetType()} : {ex.Message}");
        }
        Thread.Sleep(500);
    }
}

运行后输出如下:
在这里插入图片描述
这个也不难理解。

二、分析Ocelot.Provider.Polly中的熔断机制

Ocelot.Provider.Polly中的熔断机制其实就是用Polly组合超时和熔断实现的。
可以看下源代码:
在这里插入图片描述
里面的代码不多,我们看关键的PollyQoSProvider.cs
在这里插入图片描述
这下,我们应该清楚的知道熔断的原理了!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackletter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值