【微服务No.2】polly微服务故障处理库

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 熔断、降级: 熔断:熔断就是我们常说的“保险丝”,意为当服务出现某些状况时,切断服务,从而防止应用程序不断地常识执行可能会失败的操作造成系统的“雪崩”,或者大量的超时等待导致系统卡死等情况,很多地方也将其成为“过载保护”。

熔断、降级:

熔断:熔断就是我们常说的“保险丝”,意为当服务出现某些状况时,切断服务,从而防止应用程序不断地常识执行可能会失败的操作造成系统的“雪崩”,或者大量的超时等待导致系统卡死等情况,很多地方也将其成为“过载保护”。

降级:降级的目的就是当某个服务提供者发生故障的时候,向调用方返回一个替代响应或者错误响应。

介绍:

POLLY是一个.NET回弹和瞬态故障处理库,它允许开发人员以流畅和线程安全的方式表达诸如重试、断路器、超时、隔板隔离和回退等策略。github官方解释嘿嘿。

Polly以.NET Standard 1.1(覆盖范围:.NET Framework 4.5-4.6.1,.NET Core 1.0,Mono,Xamarin,UWP,WP8.1 +)

            .NET Standard 2.0+(覆盖范围:.NET Framework 4.6.1, .NET Core 2.0+以及后来的Mono,Xamarin和UWP目标)

安装:

首先当然是创建一个控制台项目,然后通过NuGet安装:

Install-Package Polly

出现以上界面就说明你已经安装了最新的版本到你的项目;

策略介绍:

polly通过官方介绍我们可以知道有7种恢复策略,先不管会不会,先列出来再说哈哈:

    重试策略(Retry):许多故障是短暂的,并且在短暂的延迟后可能会自我纠正。允许我们做的是能够自动配置重试机制

    断路器(Circuit-breaker):当一个系统严重挣扎时,快速失败优于让用户/呼叫者等待。 说白了就是应该优先直接返回失败,而不是一直让用户等待。保护故障系统免受过载可以帮助恢复。

    超时(Timeout):超时策略针对的前置条件是超过一定的等待时间,想要得到成功的结果是不可能的,保证调用者不必等待超时。

 

    隔板隔离(Bulkhead Isolation):隔板隔离针对的前置条件是当进程出现故障时,多个失败一直在主机中对资源(例如线程/ CPU)一直占用。下游系统故障也可能导致上游失败。这两个风险都将造成严重的后果。都说一粒老鼠子屎搅浑一锅粥,而Polly则将受管制的操作限制在固定的资源池中,免其他资源受其影响。

 

    缓存(Cache):就是一些请求,会把数据缓存起来,然后在持续一段时间内,直接从缓存中取。

 

    回退(Fallback):操作仍然会失败,也就是说当发生这样的事情时我们打算做什么。也就是说定义失败返回操作。我们在使用时就是所说的降级。

 

    策略包装(PolicyWrap):不同的故障需要不同的策略 弹性意味着使用组合。

使用步骤:

polly一般分为三步进行:

  • 定义条件: 定义你要处理的 错误异常/返回结果

  • 定义处理方式 : 重试,熔断,回退

  • 执行

定义条件:    

.Handle<ExceptionType>():限定条件的单个异常Policy;
.Handle<ExceptionType>(ex => ex.Number == 10):具有条件的单个异常类型。
.Handle<HttpRequestException>()
.Or<OperationCanceledException>():多个异常类型,当然他也可以变成具有条件的多个异常类型,类似于单个操作。

定义返回结果的条件:

.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound):用条件处理返回值,处理单个返回值。
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError) .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadGateway):处理多个返回值。 
 

 指定策略(重试):

.Retry():重试一次。
.Retry(3):重试三次,修改数值即可定义自己想使用的次数。
.Retry(3, (exception, retryCount) => { // do something }):重试多次,在每次重试都执行一个操作,参数为:当前异常和重试计数。
.Retry(3, (exception, retryCount, context) => { // do something }):重试多次,在每次重试都执行一个操作,参数为:当前异常,重试计数和上下文
.RetryForever():永远重试直到成功,同时也也有重试的相同扩展,可以写参数。
.WaitAndRetry(new[]
  {
    TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }):等待并重试,就是在每个重试的时候需要等待指定的执行时间,同样有相同扩展,可以在每个重试调用一个操作。
.WaitAndRetryForever(retryAttempt => 
	TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) ):等待和重试永远(直到成功)

  指定策略(熔断):

.CircuitBreaker(2, TimeSpan.FromMinutes(1)):在指定数量的连续异常之后中断开。这里就不做过多解释了。

 指定策略(降级):回退

.Fallback<UserAvatar>(UserAvatar.Blank):如果执行错误,则提供替代值,就是出现错误,定义一个返回值给他
.Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar()) :定义一个方法给他,该方法代替提供值。

执行: 

.Execute(() => DoSomething()):执行一项方法
执行通过任意上下文数据的操作:
var policy = Policy
    .Handle<SomeExceptionType>()
    .Retry(3, (exception, retryCount, context) =>
    {
        var methodThatRaisedException = context["methodName"];
        Log(exception, methodThatRaisedException);
    });

policy.Execute(
    () => DoSomething(),
    new Dictionary<string, object>() {{ "methodName", "some method" }}
);

 使用示例:

降级的使用代码:

 #region 降级
        public static void Downgrade()
        {
            //降级处理程序
            ISyncPolicy policy = Policy.Handle<ArgumentException>()
            .Fallback(() =>
            {
                Console.WriteLine("降级给的返回值结果");
            });
            //运行程序
            policy.Execute(() =>
            {
                Console.WriteLine("任务开始");

                throw new ArgumentException("降级任务出错,马上要降级了");

                Console.WriteLine("任务结束");
            });
        }
        #endregion
View Code

运行结果:

重试机制的代码:

出错后重复3次。

 #region 重试机制
        public static void Retry()
        {
            //配置重试次数
            ISyncPolicy policy = Policy.Handle<Exception>().Retry(3);

            try
            {
                policy.Execute(() =>
                {
                    Console.WriteLine("任务开始");
                    if (DateTime.Now.Second % 10 != 0)
                    {
                        throw new Exception("任务出错了,开始重试");
                    }
                    Console.WriteLine("任务结束");
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine("异常结果 : " + ex.Message);
            }
        }
        #endregion
View Code

运行结果:

 熔断机制代码:

但出现错误连续三次后,等待20秒后进行

 #region 熔断机制
        public static void Fusing()
        {
           
            Action<Exception, TimeSpan> onBreak = (exception, timespan) =>
            {
                Console.WriteLine("1");
            };
            Action onReset = () =>
            {
                Console.WriteLine("2");
            };
            ISyncPolicy policy = Policy.Handle<Exception>().CircuitBreaker(3, TimeSpan.FromSeconds(20), onBreak, onReset);
            while (true)
            {
                try
                {

                    policy.Execute(() =>
                        {
                            Console.WriteLine("任务开始");

                            throw new Exception("出错了");

                            Console.WriteLine("任务结束");
                        });

                }
                catch (Exception ex)
                {
                    Console.WriteLine("---------------异常结果-------------- : " + ex.Message + "时间:" + DateTime.Now);
                }
                System.Threading.Thread.Sleep(5000);
            }
        }
        #endregion
View Code

运行结果:

混合示例(重试+降级)代码:

出错重试三次后第四次进行降级处理:主要是warp方法来实现的,特别说明warp方法是:最外面(在左边)到最里面(右边)的策略。也就是说从右向左执行方法;

 #region 重试+降级
        public static void RetryDowngrade()
        {
            try
            {
                //降级处理程序
                ISyncPolicy policy = Policy.Handle<Exception>()
                .Fallback(() =>
                {
                    Console.WriteLine("降级成功");
                });
                //配置重试次数
                ISyncPolicy policy2 = Policy.Handle<Exception>().Retry(3, (exception, retryCount, context) =>
                             {
                                 Console.WriteLine(retryCount);

                             });
                //合并
                ISyncPolicy mainPolicy = Policy.Wrap(policy, policy2);
                mainPolicy.Execute(() =>
                {
                    Console.WriteLine("任务开始");

                    throw new Exception("出错了");

                    Console.WriteLine("任务结束");
                });
            }
            catch (Exception ex)
            {

                Console.WriteLine("异常结果 : " + ex.Message);
            }
        }
        #endregion
View Code

运行结果:

 源码下载:PollyConsole.rar

系列目录

微服务系列文章主要介绍微服务所使用到的一些技术和一些技术示例:

作者:YanBigFeg —— 颜秉锋

出处:http://www.cnblogs.com/yanbigfeg

本文版权归作者和博客园共有,欢迎转载,转载请标明出处。如果您觉得本篇博文对您有所收获,觉得小弟还算用心,请点击右下角的 [推荐],谢谢!

目录
相关文章
|
6月前
|
域名解析 运维 网络协议
微服务常用故障处理机制
【2月更文挑战第11天】微服务系统可能出现故障的种类,主要有三种故障:集群故障、单 IDC 故障、单机故障。
|
Kubernetes Go 网络架构
Go微服务架构实战 中篇:3. 扩缩容、自愈和故障转移、滚动更新以及回退能力
Go微服务架构实战 中篇:3. 扩缩容、自愈和故障转移、滚动更新以及回退能力
|
JSON 自然语言处理 Java
39-微服务技术栈(高级):分布式搜索引擎ElasticSearch(索引库、文档操作)
在前面读者朋友们可以了解到ES承载着和MySQL一样的“存储-查询”功能,那么就类似的会有建表语句、表结构、表数据,有了这些才可以存储-查询数据。而这些对应的在ES中是:Mapping映射(表结构-建表语句)、索引库(表本身)、文档(表数据)。本节笔者将带领大家完整上述概念的创建、使用。
191 0
|
缓存 监控 负载均衡
【微服务架构】为故障设计微服务架构
【微服务架构】为故障设计微服务架构
|
缓存 运维 分布式计算
架构设计70-质量管理10-微服务故障
架构设计70-质量管理10-微服务故障
148 0
架构设计70-质量管理10-微服务故障
|
设计模式 Java Go
Kratos微服务与它的小伙伴系列 - 依赖注入库 - Wire
与其他依赖注入工具不同,比如 Uber 的 Dig 和 Facebook 的 Inject,这 2 个工具都是使用反射实现的依赖注入,而且是运行时注入(runtime dependency injection)。
867 0
|
存储 运维 监控
微服务架构谈(6):从监控到故障定位(下)
微服务架构谈(6):从监控到故障定位(下)
586 0
微服务架构谈(6):从监控到故障定位(下)
|
运维 监控 测试技术
微服务架构谈(6):从监控到故障定位(上)
微服务架构谈(6):从监控到故障定位(上)
296 0
微服务架构谈(6):从监控到故障定位(上)
|
前端开发 小程序 开发工具
Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(六):客户端基础库 TS 实战
Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(六):客户端基础库 TS 实战
175 0
|
缓存 负载均衡 监控
微服务架构如何避免大规模故障?
微服务架构通过一种良好的服务边界划分,能够有效地进行故障隔离。但就像其他分布式系统一样,在网络、硬件或者应用级别上容易出现问题的机率会更高。服务的依赖关系,导致在任何组件暂时不可用的情况下,就它们的消费者而言都是可以接受的。为了能够降低部分服务中断所带来的影响,我们需要构建一个容错服务,来优雅地应对特定类型的服务中断。
微服务架构如何避免大规模故障?