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. stm32串口的配置方案

    最近老板要我去做控制方面的内容,所以买了一块正点原子的开发板,现在是研究了一下usart.c,函数的代码如下: void USART1_IRQHandler(void) { u8 Res; #ifde ...

  2. phpmyadmin反序列化漏洞(WooYun-2016-199433)

    简介 环境复现:https://github.com/vulhub/vulhub 线上平台:榆林学院内可使用协会内部的网络安全实验平台 phpMyAdmin是一套开源的.基于Web的MySQL数据库管 ...

  3. ASP.NET Core 3 起架设在 Windows IIS 方式改变

    最近要升级 windows 服务器的 ASP.NET Core 2.1 专案到 3.1 版本,发现 Windows 架设在 IIS 上面的方式有所改变. 一. 除了反向代理外,从 ASP.NET Co ...

  4. kali linux与虚拟机Vmware安装vmware tools(主机与虚拟机的文件拖拽)

    一.打开虚拟机任务栏"虚拟机"-----点击安装Vmware tools 二.回到开启的kali linux系统中,找到vmware tools CD文件夹,拖拽出文件中的压缩文件 ...

  5. 【JAVA基础】数组练习案例一

    /* * * 输入5个学生成绩 * 计算出每个成绩与最高分的差距 * 根据差距分配等级 * * */ import java.util.Scanner; public class ArrayTask ...

  6. FL Studio中如何进行工具栏编辑

    菜单工具栏是我们使用FL Studio时经常需要使用的一个功能,那么,除了软件默认的菜单工具栏,我们应该如何编辑菜单工具栏呢? 图1:工具栏编辑 想要编辑更改默认菜单栏,我们只需要鼠标右键单击菜单工具 ...

  7. P3287 [SCOI2014]方伯伯的玉米田

    首先可以证明,一定存在一种最优解,每次选择的区间结尾都是 \(n\).因为如果某一个区间结尾不是 \(n\),将其替换成 \(n\) 仍然保持单调不下降.接着都按这个策略拔高玉米. 令 \(f_{i, ...

  8. LeetCode周赛#209

    1609. 奇偶树 #广搜 #二叉树的层次遍历 题目链接 题意 如果一棵二叉树满足下述几个条件,则可以称为奇偶树 : 二叉树根节点所在层下标为 0 ,根的子节点所在层下标为 1 ,根的孙节点所在层下标 ...

  9. 技巧:如何区分dll程序集的编译目标平台(同样适用于查看程序集的其它依赖)

    我们在进行net core迁移过程中,有时候需要区分一个dll是针对netstandard平台还是net framework. 本文提供一个技巧来快速区分:通过工具dnSpy打开目标dll,按照如下截 ...

  10. 安全的字符串拷贝strcpy_s的实现与理解

    在C标准库中提供了字符串拷贝函数strcpy,而微软则为为它提供了一个更安全的版本strcpy_s,其函数原型为 errno_t __cdecl strcpy_s( char* _Destinatio ...