• 第四节:Polly基于控制台和Web端用法(熔断、降级、重试、超时处理等)


    一. 简介

    1. Polly是什么?

      Polly是 .Net Core 中有一个被.Net 基金会认可的库 ,可以用来简化熔断降级的处理。主要功能:失败处理-即降级(FallBack)、断路器-即熔断(CircuitBreaker)、重试(Retry)、超时检测(Timeout)、缓存(Cache)。java中的同类框架是著名的Hystrix。

    2. 相关地址

     (1). 官网:http://www.thepollyproject.org/

     (2). GitHub:https://github.com/App-vNext/Polly

     (3). 两个程序集:

       官方的:【Polly  7.2.1】

       微软封装的:【Microsoft.Extensions.Http.Polly  3.1.4】

    3. 如何理解熔断和降级

     调用端:指发送请求的端. 服务(Server)端:指提供Api接口的端。

     首先我们要明确的是熔断和降级都是作用在调用端上的,与Server端没关系。

     (1).熔断:是指当Server端出现宕机或超时情况,调用端所采用的一种策略应对机制,从而防止调用端不断地长时间执行可能会失败的操作,从而造成系统的“雪崩”, 或者大量的超时等待导致系统卡死等情况,很多地方也将其称为“过载保护”。

     PS:在Polly中熔断指 CircuitBreaker,即连续n次失败,就熔断一段时间,在这段时间内,不发送请求,走的是polly抛出的异常(报错:The circuit is now open and is not allowing calls.)。

     (2).降级:是指当Server端发生故障,调用端这里返回一个替代方案或者错误响应。比如:短信服务,假设最佳的是调用联通接口,但联通调用失败,我们退而求其次,降级调用移动的,移动的也失败,那么我们就返回失败响应了.

     PS:在Polly中降级指FallBack,走fallback中的业务,原策略业务 抛异常处 后面的代码不再执行了。

      

    二. 基于控制台用法

    前提:通过Nuget安装 【polly 7.2.1】

    1.降级(Fallback)

    {
                    Policy policy = Policy.Handle<ArgumentException>()  //故障1
                                      .Or<ArgumentOutOfRangeException>()  //故障2
                                      .Or<IndexOutOfRangeException>()     //故障3
                                      .Fallback(() =>
                                      {
                                          //降级执行的动作
                                          Console.WriteLine("我是降级后的执行的操作");
                                      });
    
                    policy.Execute(() =>
                    {
                        //执行业务代码
                        Console.WriteLine("开始任务");
                        throw new ArgumentException("类型转换失败");
                        Console.WriteLine("结束任务");
                    });
     }

    运行结果:

    2.降级-获取异常

                {
                    Policy policy = Policy.Handle<ArgumentException>()  //故障1
                                           .Or<ArgumentOutOfRangeException>()  //故障2
                                           .Or<IndexOutOfRangeException>()     //故障3
                                           .Fallback(() =>
                                           {
                                               //降级执行的动作
                                               Console.WriteLine("我是降级后的执行的操作");
                                           }, ex =>
                                           {
                                               Console.WriteLine($"业务报错信息为:{ex.Message}");
                                           });
    
                    policy.Execute(() =>
                    {
                        //执行业务代码
                        Console.WriteLine("开始任务");
                        throw new ArgumentException("类型转换失败");
                        Console.WriteLine("结束任务");
                    });
                }

    运行结果:

    3.降级-获取返回值

                {
                    Policy<string> policy = Policy<string>.Handle<ArgumentException>()  //故障
                                      .Fallback(() =>
                                      {
                                          //降级执行的动作
                                          Console.WriteLine("我是降级后的执行的操作");
                                          return "我是降级业务中的返回值";
                                      });
                    string value = policy.Execute(() =>
                      {
                          //执行业务代码
                          Console.WriteLine("开始任务");
                          throw new ArgumentException("类型转换失败");
                          Console.WriteLine("结束任务");
                          return "我是正常业务中的返回值";
                      });
                    Console.WriteLine($"最终结果为:{value}");
                }

    运行结果:

     

    4.熔断机制

                //下面设置的是连续出错3次之后熔断10秒,意思是:连续出错3次后,熔断10s,在这10s内,再次访问,不再执行Execute中的代码,直接报错,
                //10s熔断时间过后,继续访问,如果还是出错(出一次即可),直接熔断10s, 再次重复这个过程
                {
                    Policy policy = Policy
                     .Handle<Exception>()
                     .CircuitBreaker(3, TimeSpan.FromSeconds(10));    //连续出错3次之后熔断10秒(不会再去尝试执行业务代码)。 
    
                    while (true)
                    {
                        Console.WriteLine("开始Execute");
                        try
                        {
                            policy.Execute(() =>
                            {
                                Console.WriteLine("-------------------------------------开始任务---------------------------------------");
                                throw new Exception();
                                Console.WriteLine("完成任务");
                            });
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("execute出错" + ex.Message);
                        }
                        Thread.Sleep(2000);
                    }
                }

    运行结果:

     

    5.重试机制

     指业务执行出错后,重新执行n次(总共执行了n+1次),这期间如果成功了,则后面不再执行,如果不成功,重试n次后,会把异常抛出来. 或者一直重复,直到成功。

     (1).Retry:出错后重新执行n次,期间成功则停止后续重试; 期间不成功,最后可以捕获异常.

     (2).RetryForever:出错后一直重试,直到成功才停止.

     (3).WaitAndRetry:出错后重新执行n次,每次间隔m秒.

     {
                    try
                    {
                        Policy policy = Policy
                        .Handle<Exception>()
                        .Retry(3); //出错后,连续执行3次
                        //.RetryForever();//出错后,连续执行,直到成功为止
                        //.WaitAndRetry(5, i => TimeSpan.FromSeconds(2));  //重试5次,每次间隔2s
                        int g = 0;
                        policy.Execute(() =>
                        {
                            Console.WriteLine($"开始任务,g={g}");
                            if (g < 10)
                            {
                                g++;
                                throw new Exception("业务出错了");
                            }
    
                            Console.WriteLine("完成任务");
                        });
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"捕获异常:{ex.Message}");
                    }
    }

    运行结果

    6.组合机制

     使用Wrap包裹,eg:policy6=Policy.Wrap(policy1, policy2)

     注意:Wrap是有包裹顺序的,内层的故障如果没有被处理则会抛出到外层.

    (1).超时3秒降级:超时相关的 Policy.Timeout(3, TimeoutStrategy.Pessimistic);

     {
                    //1.1 超时3秒
                    Policy policytimeout = Policy.Timeout(3, TimeoutStrategy.Pessimistic);
                    //1.2 降级
                    Policy policyFallBack = Policy.Handle<TimeoutRejectedException>()
                       .Fallback(() =>
                       {
                           //降级执行的动作
                           Console.WriteLine("我是降级后的执行的操作");
                       }, ex =>
                       {
                           //捕获业务中的出错信息
                           Console.WriteLine(ex.Message);
                       });
                    //1.3 将超时和降级操作进行组合
                    Policy policy = policyFallBack.Wrap(policytimeout);
                    //1.4 执行业务代码
                    policy.Execute(() =>
                    {
                        Console.WriteLine("开始任务");
                        Thread.Sleep(5000);
                        Console.WriteLine("完成任务");
                    });
    }

    运行结果:

    (2).重试+降级:重试3次,期间成功,则继续执行后面业务;期间失败,则走外层的降级操作

                {
                    //2.1 遇到异常重试3次
                    Policy policyRetry = Policy.Handle<Exception>().Retry(3);
                    //2.2 降级操作
                    Policy policyFallback = Policy.Handle<Exception>()
                                                  .Fallback(() =>
                                                  {
                                                      //降级执行的动作
                                                      Console.WriteLine("我是降级后的执行的操作");
                                                  }, ex =>
                                                  {
                                                      //捕获业务中的出错信息
                                                      Console.WriteLine(ex.Message);
                                                  });
                    //Wrap:包裹。policyRetry在里面,policyFallback在外面,如果里面出现了故障,则把故障抛出来给外面
                    //2.3 进行包裹(出现错误,先重试3次,期间成功,则继续执行后面业务;期间失败,则走外层的降级操作)
                    Policy policy = policyFallback.Wrap(policyRetry);
                    int g = 0;
                    //2.4 执行业务代码
                    policy.Execute(() =>
                    {
                        Console.WriteLine($"开始任务,g={g}");
                        if (g < 10)
                        {
                            g++;
                            throw new Exception("业务出错了");
                        }
    
                        Console.WriteLine("完成任务");
                    });
                }

    运行结果:

    (3).熔断+降级:Execute执行业务代码无须再用Try-catch包裹,否则不抛异常,则无法降级,我们这里演示的是降级,并在降级中拿到业务代码的异常信息

                {
                    //3.1 熔断
                    Policy policyCBreaker = Policy.Handle<Exception>()
                                            .CircuitBreaker(3, TimeSpan.FromSeconds(10));    //连续出错3次之后熔断10秒(不会再去尝试执行业务代码)。 
                    //3.2 降级
                    Policy policyFallback = Policy.Handle<Exception>()
                                           .Fallback(() =>
                                           {
                                               //降级执行的动作
                                               Console.WriteLine("我是降级后的执行的操作");
                                           }, ex =>
                                           {
                                               //这里是捕获业务代码中的错误,业务代码中就不要再写try-catch,否则不抛异常,则无法降级
                                               Console.WriteLine($"业务报错信息为:{ex.Message}");
                                           });
                    //3.4 包裹
                    Policy policy = policyFallback.Wrap(policyCBreaker);
    
                    //3.4 执行业务
                    while (true)
                    {
                        Console.WriteLine("开始Execute");
                        //try
                        //{
                        policy.Execute(() =>
                        {
                            Console.WriteLine("-------------------------------------开始任务---------------------------------------");
                            throw new Exception();
                            Console.WriteLine("完成任务");
                        });
                        //}
                        // 不要再写try-catch,否则不抛异常,则无法降级
                        //catch (Exception ex)
                        //{
                        //    Console.WriteLine("execute出错" + ex.Message);
                        //}
                        Thread.Sleep(2000);
                    }
                }

    运行结果:

     

    三. 基于Web端用法

    四. 其它

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    C#中的int?和X??
    验证码识别技术导论
    Jquery focus blur给文本框加选中离开效果
    Asp.Net 用户验证(自定义IPrincipal和IIdentity)
    FCKeditor介绍
    char varchar 有什么区别
    jquery无刷新载入其他页面的内容
    ASP.NET 安全认证
    程序员不是一般人
    [转]Asp.net中基于Forms验证的角色验证授权
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/12961058.html
Copyright © 2020-2023  润新知