欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c# 如何更简单的使用Polly

程序员文章站 2022-03-06 11:01:02
polly是一个c#实现的弹性瞬时错误处理库它可以帮助我们做一些容错模式处理,比如: 超时与重试(timeout and retry) 熔断器(circuit breaker) 舱壁隔离(bul...

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

以上就是c# 如何更简单的使用polly的详细内容,更多关于c# 使用polly的资料请关注其它相关文章!

相关标签: c# Polly