c# 如何更简单的使用Polly

作者:victor.x.qu 时间:2022-10-24 11:27:46 

目录
  • 如何实现简化呢?

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

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

    • TimeoutAttribute

    • RetryAttribute

    • CircuitBreakerAttribute

    • BulkheadAttribute

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

2.编写 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));
}
}

3.考虑到 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));
}
}

4.我们来做个测试吧


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

来源:https://www.cnblogs.com/fs7744/p/14129076.html

标签:c#,Polly
0
投稿

猜你喜欢

  • java Long类型转为json后数据损失精度的处理方式

    2022-08-11 12:37:43
  • Java中抽象类和接口介绍

    2022-05-28 02:42:09
  • Spring注解@Scope原理及用法解析

    2023-12-06 14:08:17
  • 详解MyBatis日志如何做到兼容所有常用的日志框架

    2022-05-28 08:24:17
  • 不使用他人jar包情况下优雅的进行dubbo调用详解

    2022-04-20 11:43:46
  • C# WinForm实现自动更新程序之客户端的示例代码

    2022-03-28 03:26:24
  • C#网络爬虫代码分享 C#简单的爬取工具

    2023-10-12 15:03:41
  • Java Set集合去重的原理及实现

    2023-08-11 10:56:11
  • Netty组件NioEventLoopGroup创建线程执行器源码解析

    2022-03-07 00:36:17
  • 基于Java实现简单贪吃蛇游戏

    2022-08-07 02:09:44
  • Java 判断字符为中文实例代码(超管用)

    2021-08-24 13:18:31
  • springboot自定义starter方法及注解实例

    2022-11-02 10:52:08
  • MyBatis动态SQL中的trim标签的使用方法

    2022-08-30 21:38:13
  • Android实现图片上传蒙层进度条

    2022-05-06 04:35:43
  • 提升java开发效率工具lombok使用争议

    2022-06-22 03:08:18
  • spring Roo安装使用简介

    2023-04-10 09:31:50
  • Android ImageView绘制圆角效果

    2023-11-22 22:59:15
  • RedisTemplate中opsForValue和opsForList方法的使用详解

    2023-07-28 15:48:57
  • C#实现简单的字符串加密

    2022-12-28 17:09:29
  • C# 数组删除元素的实现示例

    2022-03-02 08:55:04
  • asp之家 软件编程 m.aspxhome.com