zoukankan      html  css  js  c++  java
  • 如何更简单的使用Polly

    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

  • 相关阅读:
    DataGrid和GridView鼠标移动上面背景变色
    Javascript页面跳转常用代码(测试通过)
    设为首页,加入收藏夹
    Javascript实现金额千分位自动分位
    对用户输入内容进行字数提示功能
    Javascript网页刷新方法集锦(测试通过)
    asp.net 上传图片并作处理 水印 缩略图(测试OK)
    ASP.NET常用函数(参考用)
    Javascript弹出对话框 确定取消转到不同页面
    silverligth +wcf 下载文件
  • 原文地址:https://www.cnblogs.com/fs7744/p/14129076.html
Copyright © 2011-2022 走看看