.Net弹性和瞬态故障处理库Polly介绍

Polly 是 .Net 下的一套瞬时故障处理及恢复的函式库,可让开发者以fluent及线程安全的方式来应用诸如RetryCircuit BreakerTimeoutBulkhead IsolationFallback等策略。

安装

可以通过Nuget实现快速安装:Install-Package Polly

基本用法

一个简单的示例如下:

var policy = Policy
    .Handle<DivideByZeroException>()    //定义所处理的故障
    .Retry();    //故障的处理方法

policy.Execute(() => DoSomething());    //应用策略

从上面的例子中我们可以看出,使用该策略一般包括三个步骤:

  • 定义所处理的故障
  • 定义故障的处理方法
  • 应用策略

上述代码在功能上和下面的代码等价:

for (int i = 0; i < 2; i++)
{
    try
    {
        DoSomething();
    }
    catch (DivideByZeroException)
    {
        if (i > 1)
            throw;
    }
}

虽然这个例子比较简单,带来的优越性并不明显,但它以一种比较规范的方式定义了异常的处理策略,一来带来了更好的体验,带来了更好的代码可读性,另外,随着异常策略的复杂,它所带来的对代码的简化就更加明显了。下面就稍微详细一点的深入介绍一下:

定义错误(故障)

常见故障定义方式是指定委托执行过程中出现的特定异常,Polly中支持异常处理方式如下:

// 处理指定异常
Policy.Handle<DivideByZeroException>();

// 处理有条件的指定异常
Policy.Handle<SqlException>(ex => ex.Number == 1205);

// 处理多种异常
Policy.Handle<DivideByZeroException>()
    .Or<ArgumentException>();

// 处理多种有条件的异常
Policy.Handle<SqlException>(ex => ex.Number == 1205)
    .Or<ArgumentException>(ex => ex.ParamName == "example");

也支持异常的聚合:

Policy.Handle<ArgumentException>()
    .Or<ArgumentException>();

另外,也支持通过返回值判断是否故障:

// 指定错误的返回值
Policy.HandleResult<int>(ret => ret <= 0);

故障处理策略:重试

常见的处理策略是重试,Polly库中内置了各种常用的重试策略:

// 重试1次
Policy.Handle<TimeoutException>().Retry();

// 重试多次
Policy.Handle<TimeoutException>().Retry(3);

// 无限重试
Policy.Handle<TimeoutException>().RetryForever();

也支持retry时增加一些额外的行为:

Policy.Handle<TimeoutException>().Retry(3, (err, countdown, context) =>
{
    // log retry
});

也支持等待并重试:

// 等待并重试
Policy.Handle<TimeoutException>().WaitAndRetry(3, _ => TimeSpan.FromSeconds(3));

故障处理策略:回退(Fallback)

Fallback策略是在遇到故障是指定一个默认的返回值,

Policy<int>.Handle<TimeoutException>().Fallback(3);
Policy<int>.Handle<TimeoutException>().Fallback(() => 3);

当然,遇到没有返回值的也可以指定故障时的处理方法,

Policy.Handle<TimeoutException>().Fallback(() => { });

使用Fallback时,异常被捕获,返回默认的返回结果。

PS: 带参数的Fallback处理方式貌似在5.0之后发生了变化,成了本文所示的方式,以前是Fallback<T>

故障处理策略:断路保护(Circuit Breaker)

Circuit Breaker也是一种比较常见的处理策略,它可以指定一定时间内最大的故障发生次数,当超过了该故障次数时,在该时间段内,不再执行Policy内的委托。下面以一个简单的示例演示下该策略的功能:

static void testPolicy()
{
    var circuitBreaker = Policy.Handle<TimeoutException>()
            .CircuitBreaker(3, TimeSpan.FromMinutes(1));
    for (int i = 0; i < 5; i++)
    {
        try
        {
            circuitBreaker.Execute(DoSomething);
        }

        catch (Polly.CircuitBreaker.BrokenCircuitException e)
        {
            Console.WriteLine(e.Message);
        }
        catch (TimeoutException)
        {
            Console.WriteLine("timeout");
        }
    }
}

static int index = 0;
static int DoSomething()
{
    Console.WriteLine($"DoSomething {index++}");
    throw new TimeoutException();
}

执行结果如下:

DoSomething 0
timeout
DoSomething 1
timeout
DoSomething 2
timeout
The circuit is now open and is not allowing calls.
The circuit is now open and is not allowing calls.

可以看到,前面3次都能执行委托DoSomething,但出错次数到达3次后,已经进入断路保护章台,后面两次调用直接返回BrokenCircuitException。直到达到保护时间超时后,对策略的调用才会再次执行DoSomething委托。

这种策略在调用远程服务时非常实用,当一定时间内的调用都出错时,往往可以认为服务提供者已经不可用,后续调用完全可以直接失败,以避免重试的开销。直到一定时间后才需要再次重试。

相对其它处理策略,CircuitBreaker是一个比较复杂的策略,它是有状态的,可以通过CircuitState属性获取:

var state = circuitBreaker.CircuitState;

它有四种状态:

  • CircuitState.Closed - 常态,可执行actions。
  • CircuitState.Open - 自动控制器已断开电路,不允许执行actions。
  • CircuitState.HalfOpen - 在自动断路时间到时,从断开的状态复原。可执行actions,后续的action/s或控制的完成,会让状态转至Open或Closed。
  • CircuitState.Isolated - 在电路开路的状态时手动hold住,不允许执行actions。

除了超时和策略执行失败的这种自动方式外,也可以手动控制它的状态:

// 手动打开(且保持)一个断路器–例如手动隔离downstream的服务
circuitBreaker.Isolate();

// 重置一个断路器回closed的状态,可再次接受actions的执行
circuitBreaker.Reset();

更多的介绍可以参看官方文档:Circuit Breaker

故障封装策略(PolicyWrap)

我们可以通过PolicyWrap的方式,封装出一个更加强大的策略:

var fallback = Policy<int>.Handle<TimeoutException>().Fallback(100);
var retry = Policy<int>.Handle<TimeoutException>().Retry(2);

var retryAndFallback = fallback.Wrap(retry);

这个策略就是将Retry和Fallback组合起来,形成一个retry and fallback的策略,也可以写成如下形式:

Policy.Wrap(fallback, retry);

当执行这个新策略时:

retryAndFallback.Execute(DoSomething);

等价于执行:

fallback.Execute(()=> retry.Execute(DoSomething));

封装策略本身是属于弹性策略的范畴,这里只是提及一下,以演示Polly模块强大的功能,关于弹性策略更多内容在下文中再做更详细的介绍。

到此这篇关于.Net弹性和瞬态故障处理库Polly的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • .Net弹性和瞬态故障处理库Polly实现执行策略

    执行策略 执行策略的常见方式是调用策略的Execute函数 var policy = Policy.Handle<TimeoutException>().Retry(); policy.Execute(DoSomething); 返回值: 如果有返回值,它也是可以获取其返回值的: var result = policy.Execute(DoSomething); 捕获异常: 如果在策略的执行过程中出现了异常,也会在该函数中同步抛出来,和直接执行该委托行为一致.可以直接通过try-catch处理

  • .Net弹性和瞬态故障处理库Polly实现弹性策略

    和故障处理策略不同的是,弹性策略并不是针对委托执行过程中的异常进行处理,而是改变委托本身的行为,因此弹性策略并没有故障定义这一过程,它的处理流程为: 定义策略 应用策略 Polly对弹性策略也做了不少支持,本文这里就简单的介绍一下. 弹性策略:超时(Timeout) 超时策略用于控制委托的运行时间,如果达到指定时间还没有运行,则触发超时异常. Policy.Timeout(TimeSpan.FromSeconds(3), TimeoutStrategy.Pessimistic); 超时策略常见的

  • c# 如何更简单的使用Polly

    Polly是一个C#实现的弹性瞬时错误处理库 它可以帮助我们做一些容错模式处理,比如: 超时与重试(Timeout and Retry) 熔断器(Circuit Breaker) 舱壁隔离(Bulkhead Isolation) 回退(Fallback) 使用也是非常简单的,比如: // Retry multiple times, calling an action on each retry // with the current exception and retry count Polic

  • .NET 开源项目Polly的简单介绍

    目录 Polly 介绍 官方对 Polly 的介绍是这样的: Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. 翻译

  • .Net弹性和瞬态故障处理库Polly介绍

    Polly 是 .Net 下的一套瞬时故障处理及恢复的函式库,可让开发者以fluent及线程安全的方式来应用诸如Retry.Circuit Breaker.Timeout.Bulkhead Isolation及Fallback等策略. 安装 可以通过Nuget实现快速安装:Install-Package Polly 基本用法 一个简单的示例如下: var policy = Policy .Handle<DivideByZeroException>() //定义所处理的故障 .Retry();

  • IOS 打包静态库详细介绍

    IOS 打包静态库详细介绍 一.前言 前段时间看的一本书上说:"隔着一段距离看,很多有趣的知识看起来都很唬人."比如说这篇我要总结的"静态库知识",在我初出茅庐的时候着实觉得那些后缀名为".frameworke".".a".".dylib"的文件很神秘,很高冷.那时我虽然知道只要导入一个库就能引用库里面很多封装好的东西,但对这个"库"究竟是什么"鬼",一直都是云里雾里

  • 聊聊python的gin库的介绍和使用

    1.简介 由于现在很多机器学习的实验需要设置繁琐的参数,在多次实验中,有些参数是一样的,为了方便设置参数,Gin库出现了.它允许函数或类被注释为@gin.configurable,这使得能够使用清晰而强大的语法通过简单的配置文件来设置它们的参数.这种方法减少了配置维护,同时使实验配置透明且易于重复. 简单理解,gin像一个封装了参数配置的类,使用这个类将使得大量的参数配置变得简单清晰 安装 pip install gin-config 2.@gin.configurable 任何函数和类都可以使

  • Go语言中log日志库的介绍

    一.标准库log介绍 Go语言内置的log包实现了简单的日志服务. 1.使用Logger log包定义了Logger类型,该类型提供了一些格式化输出的方法. log包也提供了一个预定义的"标准"logger,可以通过调用函数Print系列(Print|Printf|Println).Fatal系列(Fatal|Fatalf|Fatalln).和Panic系列(Panic|Panicf|Panicln)来使用,比自行创建一个logger对象更容易使用. logger会打印每条日志信息的日

  • Python爬虫之requests库基本介绍

    目录 一.说明 二.基本用法: 总结 一.说明 requests是一个很实用的Python HTTP客户端库,爬虫和测试服务器响应数据时经常会用到,requests是Python语言的第三方的库,专门用于发送HTTP请求,使用起来比urllib简洁很多. Requests 有这些功能: 1.Keep-Alive & 连接池2.国际化域名和 URL3.带持久 Cookie 的会话4.浏览器式的 SSL 认证5.自动内容解码6.基本/摘要式的身份认证7.优雅的 key/value Cookie8.自

  • MYSQL 增加从库方式介绍

    目录 一.MySQL主从复制 实现细节 二.增加一个slave 一.MySQL主从复制 常见的主从架构: 一主一从:一个 Master,一个 Slave 一主多从:一个 Master,多个 Slave 具体,参考下图: 实现细节 MySQL 在主从同步时,其底层实现细节又是什么?为此后分析主从延迟原因以及优化方案,做好理论准备. 总结来说,MySQL 的主从复制:异步单线程. Master上 1 个IO线程,负责向Slave传输 binary log(binlog) Slave上 2 个线程:I

  • C++ Boost Flyweight库使用介绍

    目录 一.说明 二.库Boost.Flyweight 炼习 一.说明 以下库用于设计模式. Boost.Flyweight 有助于在程序中使用许多相同的对象并且需要减少内存消耗的情况. Boost.Signals2 使得使用观察者设计模式变得容易.这个库被称为 Boost.Signals2 因为它实现了信号/槽的概念. Boost.MetaStateMachine 使得将状态机从 UML 转移到 C++ 成为可能. 本节内容 66. Boost.Flyweight 67. Boost.Signa

  • 关于Python网络爬虫requests库的介绍

    1. 什么是网络爬虫 简单来说,就是构建一个程序,以自动化的方式从网络上下载.解析和组织数据. 就像我们浏览网页的时候,对于我们感兴趣的内容我们会复制粘贴到自己的笔记本中,方便下次阅读浏览——网络爬虫帮我们自动完成这些内容 当然如果遇到一些无法复制粘贴的网站——网络爬虫就更能显示它的力量了 为什么需要网络爬虫 当我们需要做一些数据分析的时候——而很多时候这些数据存储在网页中,手动下载需要花费的时间太长,这时候我们就需要网络爬虫帮助我们自动爬取这些数据来(当然我们会过滤掉网页上那些没用的东西) 网

随机推荐