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
Policy
.Handle<SomeExceptionType>()
.Retry(3, onRetry: (exception, retryCount) =>
{
// Add logic to be executed before each retry, such as logging
});

但是每个地方我们都得这样写,个人还是不喜,

那么怎么简化呢?

当然是使用 Norns.Urd 这些AOP框架封装我们常用的东西做成 Attribute

如何实现简化呢?

我们来尝试将 Retry功能 做成 RetryAttribute

  1. 安装 AOP 框架

    自己写多累呀,用现成的多好呀
dotnet add package Norns.Urd
  1. 编写 Retry InterceptorAttribute
    public class RetryAttribute : AbstractInterceptorAttribute
{
private readonly int retryCount; public RetryAttribute(int retryCount)
{
this.retryCount = retryCount;
} public override async Task InvokeAsync(AspectContext context, AsyncAspectDelegate next)
{
await Policy.Handle<Exception>()
.RetryAsync(retryCount)
.ExecuteAsync(() => next(context));
}
}
  1. 考虑到 async 和 sync 在Polly 有差异,那么我们兼容一下吧
    public class RetryAttribute : AbstractInterceptorAttribute
{
private readonly int retryCount; public RetryAttribute(int retryCount)
{
this.retryCount = retryCount;
} public override void Invoke(AspectContext context, AspectDelegate next)
{
Policy.Handle<Exception>()
.Retry(retryCount)
.Execute(() => next(context));
} public override async Task InvokeAsync(AspectContext context, AsyncAspectDelegate next)
{
await Policy.Handle<Exception>()
.RetryAsync(retryCount)
.ExecuteAsync(() => next(context));
}
}
  1. 我们来做个测试吧
    public class RetryTest
{
public class DoRetryTest
{
public int Count { get; set; } [Retry(2)] // 使用 Retry
public virtual void Do()
{
if (Count < 50)
{
Count++; // 每调用一次就加1
throw new FieldAccessException();
}
}
} public DoRetryTest Mock()
{
return new ServiceCollection()
.AddTransient<DoRetryTest>()
.ConfigureAop()
.BuildServiceProvider()
.GetRequiredService<DoRetryTest>();
} [Fact]
public void RetryWhenSync()
{
var sut = Mock();
Assert.Throws<FieldAccessException>(() => sut.Do());
Assert.Equal(3, sut.Count); //我们期望调用总共 3 次
}
}

是的,就是这样,我们可以在任何地方使用 RetryAttribute

当然,一些常见的方法已经封装在了 Norns.Urd.Extensions.Polly

这里通过Norns.Urd将Polly的各种功能集成为更加方便使用的功能

如何启用 Norns.Urd + Polly, 只需使用EnablePolly()

如:

new ServiceCollection()
.AddTransient<DoTimeoutTest>()
.ConfigureAop(i => i.EnablePolly())

TimeoutAttribute

[Timeout(seconds: 1)]  // timeout 1 seconds, when timeout will throw TimeoutRejectedException
double Wait(double seconds); [Timeout(timeSpan: "00:00:00.100")] // timeout 100 milliseconds, only work on async method when no CancellationToken
async Task<double> WaitAsync(double seconds, CancellationToken cancellationToken = default); [Timeout(timeSpan: "00:00:01")] // timeout 1 seconds, but no work on async method when no CancellationToken
async Task<double> NoCancellationTokenWaitAsync(double seconds);

RetryAttribute

[Retry(retryCount: 2, ExceptionType = typeof(AccessViolationException))]  // retry 2 times when if throw Exception
void Do()

CircuitBreakerAttribute

[CircuitBreaker(exceptionsAllowedBeforeBreaking: 3, durationOfBreak: "00:00:01")]
//or
[AdvancedCircuitBreaker(failureThreshold: 0.1, samplingDuration: "00:00:01", minimumThroughput: 3, durationOfBreak: "00:00:01")]
void Do()

BulkheadAttribute

[Bulkhead(maxParallelization: 5, maxQueuingActions: 10)]
void Do()

有关 Norns.Urd, 大家可以查看 https://fs7744.github.io/Norns.Urd/zh-cn/index.html

如何更简单的使用Polly的更多相关文章

  1. 【热门技术】EventBus 3.0,让事件订阅更简单,从此告别组件消息传递烦恼~

    一.写在前面 还在为时间接收而烦恼吗?还在为各种组件间的消息传递烦恼吗?EventBus 3.0,专注于android的发布.订阅事件总线,让各组件间的消息传递更简单!完美替代Intent,Handl ...

  2. PostCSS一种更优雅、更简单的书写CSS方式

    Sass团队创建了Compass大大提升CSSer的工作效率,你无需考虑各种浏览器前缀兼,只需要按官方文档的书写方式去写,会得到加上浏览器前缀的代码,如下: .row { @include displ ...

  3. 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...

  4. [转]九个Console命令,让js调试更简单

    转自:九个Console命令,让js调试更简单 一.显示信息的命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!DOCTYPE html> <html ...

  5. gulp:更简单的自动化构建工具

    目前最流行的两种使用JavaScript开发的构建工具是Grunt和Gulp.为什么使用gulp?因为Gulp更简单.Grunt任务拥有大量的配置,会引用大量你实际上并不需要的对象属性,但是Gulp里 ...

  6. 使用hessian开发WebService,轻量级,更简单、快捷

    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...

  7. Rsession让Java调用R更简单

    Rsession让Java调用R更简单 R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大. R语言作为统计学一门语言,一直在小众领域闪耀着光芒. ...

  8. spring 第一篇(1-1):让java开发变得更简单(下)

    切面(aspects)应用 DI能够让你的软件组件间保持松耦合,而面向切面编程(AOP)能够让你捕获到在整个应用中可重用的组件功能.在软件系统中,AOP通常被定义为提升关注点分离的一个技术.系统由很多 ...

  9. spring 第一篇(1-1):让java开发变得更简单(下)转

    spring 第一篇(1-1):让java开发变得更简单(下) 这个波主虽然只发了几篇,但是写的很好 上面一篇文章写的很好,其中提及到了Spring的jdbcTemplate,templet方式我之前 ...

随机推荐

  1. 测试_QTP使用

    1.Qtp是什么? QTP是Quick Test Professional的简称,是一种自动测试工具.使用QTP的目的是想用它来执行重复的自动化测试,主要是用于回归测试和测试同一软件的新版本.(百度百 ...

  2. Python_爬虫_百度图片

    百度图片有些有编码问题,暂时不能爬取,多试几个 #思路:抓取图片地址,根据地址转存图片(注意名称):难点:转码 # -*- coding:utf-8 -*- from urllib import re ...

  3. SixLabors.ImageSharp 实践小结

    前言 之前写过一篇 Linux/Docker 中使用 System.Drawing.Common 踩坑小计, 当时主要是有一块图像处理的需要从 .net framework 迁移到 .net core ...

  4. mysql 不常用备忘

    # group_concat 函数语法: group_concat( [DISTINCT]  要连接的字段   [Order BY 排序字段 ASC/DESC]   [Separator '分隔符'] ...

  5. kali 系列学习08-安卓逆向

    可以轻松把安卓apk的源码逆向出来,逆向有什么用,比如手机apk木马,可以用于追踪黑客,详见  https://cloud.tencent.com/developer/news/179336 用2个工 ...

  6. 如何防范CSRF攻击

    上一篇文章了解了一下CSRF和XSS的区别,那么这次我们来看看怎么防范CSRF吧 首先,从上篇文章我们可以看得出,CSRF攻击是有着限制的,而我们可以使用这个限制来对他做相关的防范 方法1:后端在接收 ...

  7. 深度分析:Java 静态方法/变量,非静态方法/变量的区别,今天一并帮你解决!

    静态/非静态 方法/变量的写法 大家应该都明白静态方法/字段比普通方法/字段的写法要多一个static关键字,简单写下他们的写法吧,了解的可以直接略过 class Test{ // 静态变量 publ ...

  8. 02python开发之基本运算符

    02 python开发之基本运算符 目录 02 python开发之基本运算符 2 基本运算符 2.1 算数运算符 2.1.1 种类 2.1.2 用法 2.2 比较运算符 2.2.1 种类 2.2.2 ...

  9. 采集post传输的数据

    采集数据,网页上的数据是开发者通过ajax的post方式显示的,就得用到curl以及它的跨域方法 代码: $post_data------post传过去的参数 $ch = curl_init(); $ ...

  10. ?.可选链操作符( ?. ) 可选链运算符可防止抛出 TypeError: Cannot read property ’xxx' of undefined。

    可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效.?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null ...