软件编程
位置:首页>> 软件编程>> C#编程>> c# 如何更简单的使用Polly

c# 如何更简单的使用Polly

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

标签:c#,Polly
目录
  • 如何实现简化呢?

  • 当然,一些常见的方法已经封装在了 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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com