用户登录
用户注册

分享至

c# 如何更简单的使用Polly

  • 作者: 听说污的人颜值都很高
  • 来源: 51数据库
  • 2021-09-01

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的资料请关注其它相关文章!

软件
前端设计
程序设计
Java相关