zoukankan      html  css  js  c++  java
  • 第四节: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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    mysqldump 导出数据库为DBname的表名为Tname的表结构 导出数据库的所有表的表结构
    mysqldump 备份某张表 Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions,
    nfs missing codepage or helper program, or other error
    date 增加一个小时 减少一个小时
    mysqldump 备份单个数据库
    mysql删除账户
    怎么删除某个用户的所有帖子?
    mongodb删除重复数据
    ReSharper2018破解详细方法
    激活windows和office
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/12961058.html
Copyright © 2011-2022 走看看