zoukankan      html  css  js  c++  java
  • 基于.NET的弹性及瞬间错误处理库Polly

    本文基本是官方说明的翻译和总结(https://github.com/App-vNext/Polly)

    什么是Polly?

    Polly是一款基于.NET的弹性及瞬间错误处理库, 它允许开发人员以顺畅及线程安全的方式执行重试(Retry),断路器(Circuit),超时(Timeout),隔板隔离(Bulkhead Isolation)及后背策略(Fallback)。

    Polly适用于.NET 4.0, .NET 4.5及.NET Standard 1.1(覆盖.NET Core, Mono, Xamarin.IOS, Xamarin.Android, UWP, WP 8.1+)。

    安装Polly

    .NET 4.0版本

    Install-Package Polly.Net40Async

    .NET 4.5及以上版本, .Net Standard 1.1

    Install-Package Polly

    弹性策略

    Polly提供多种弹性策略。

    重试策略

    前提

    程序会产生许多瞬时故障,但是在一定时间延迟之后,程序会自动纠正故障。

    实现效果

    允许配置自动重试。

    断路器策略

    前提

    当系统发生严重故障时,快速响应请求失败比让用户等待要好。
    避免故障系统过载有助于恢复系统。

    实现效果

    当系统错误超过预配置的数量,系统将断路一段时间。

    超时策略

    前提

    超出一定时间的等待,想要得到正确的结果是不太可能的。

    实现效果

    保证调用者不需要等待超时。

    隔板隔离

    前提

    当进程出现故障,多个失败的请求很容易占满服务器资源(线程/CPU)。
    一个处于故障状态的下游系统,也会导致其上游系统故障。

    实现效果

    将严格管控故障进程,使其使用固定大小的资源池,隔离他们对其他进程的潜在影响

    缓存策略

    前提

    一定比例的请求可能是相似的。

    实现效果

    从缓存中提供已知的响应。
    当第一次读取的时候,将响应自动缓存起来。

    后备策略

    前提

    当故障依然存在的时候,你打算做什么。

    实现效果

    当程序依然发生故障时,执行指定操作。

    包装策略

    前提

    不同的故障需要不同的策略。包装策略即组合策略。

    实现效果

    允许灵活的将以上任意几种策略组合在一起。

    如何使用Polly进行故障/异常处理?

    Polly处理故障/异常有以下几个步骤。

    1. 指定处理的异常/故障类型
    2. [可选] 指定处理的异常返回值
    3. 指定处理策略
    4. 执行策略

    指定处理异常/故障的类型

    Polly使用Policy类的泛型方法Handle指定Polly需要处理异常/故障的类型。

    指定单个异常类型

    Policy.Handle<DivideByZeroException>()
    

    指定带条件的异常类型

    Policy.Handle<SqlException>(ex => ex.Number == 1205)
    

    Polly也支持指定多种异常/故障类型, 这里需要使用Or方法

    Policy.Handle<DivideByZeroException>().Or<ArgumentException>()
    

    指定多个带条件的异常类型

    Policy
       .Handle<SqlException>(ex =ex.Number == 1205)
       .Or<ArgumentException>(ex =ex.ParamName == "example")
    

    Polly也支持指定内部异常

    Policy
    	.HandleInner<HttpResponseException>()
    	.OrInner<OperationCanceledException>(ex => ex.CancellationToken == myToken)
    

    指定处理的异常返回值

    Polly除了支持处理异常/故障类型,还支持处理异常返回值。所谓的处理异常结果,就是当Polly监控的方法,返回某些特定结果时, Polly会触发异常/故障处理策略。

    Polly使用Policy类的泛型方法HandleResult制定Polly需要处理的异常结果.

    指定触发异常/故障处理策略的返回值

    例如:当某个方法的返回值类型是HttpResposneMessage, 并且返回值的StatusCode是NotFound时,触发异常/故障处理策略。

    Policy
    .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound)
    

    指定多个返回值

    Policy
        .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
        .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadGateway)
    

    同时指定异常类型和返回值

    HttpStatusCode[] httpStatusCodesWorthRetrying = {
    	HttpStatusCode.RequestTimeout, // 408
    	HttpStatusCode.InternalServerError, // 500
    	HttpStatusCode.BadGateway, // 502
    	HttpStatusCode.ServiceUnavailable, // 503
    	HttpStatusCode.GatewayTimeout // 504
    }; 
    HttpResponseMessage result = Policy
    	.Handle<HttpResponseException>()
    	.OrResult<HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode))
    

    指定异常处理策略

    重试策略

    重试一次

    Policy
    	.Handle<DivideByZeroException>()
    	.Retry()
    

    重试多次

    Policy
    	.Handle<DivideByZeroException>()
    	.Retry(3)
    

    重试多次,每次重试触发一个行为

    Policy
    	.Handle<DivideByZeroException>()
    	.Retry(3, (exception, retryCount) =>
    	{
        	// do something 
    	});
    

    永久重试(直到成功)

    永久重试

    Policy
    	.Handle<DivideByZeroException>()
    	.RetryForever()
    

    永久重试,每次重试触发一个行为

    Policy
    	.Handle<DivideByZeroException>()
    	.RetryForever(exception =>
    	{
        		// do something       
    	});
    

    等待并重试

    指定每个重试的间隔时间

    Policy
    	.Handle<DivideByZeroException>()
    	.WaitAndRetry(new[]
    	{
    		TimeSpan.FromSeconds(1),
    		TimeSpan.FromSeconds(2),
    		TimeSpan.FromSeconds(3)
    	});
    

    在这个例子如果第一次出现异常,会在1秒后重试,如果依然出现异常,会在再次出现异常后2秒继续重试,以此类推,下次异常后3秒继续重试

    每次重试,触发一个行为

    Policy
        .Handle<DivideByZeroException>()
        .WaitAndRetry(new[]
        {
          TimeSpan.FromSeconds(1),
          TimeSpan.FromSeconds(2),
          TimeSpan.FromSeconds(3)
        }, (exception, timeSpan) => {
          // do something    
        }); 
    

    断路器策略

    在发生指定次数的异常/故障之后,断开回路

    Policy
    	.Handle<DivideByZeroException>()
    	.CircuitBreaker(2, TimeSpan.FromMinutes(1));
    

    发生2次异常之后,断开回路1分钟

    Action<Exception, TimeSpan> onBreak = (exception, timespan) => { ... };
    Action onReset = () => { ... };
    CircuitBreakerPolicy breaker = Policy
    	.Handle<DivideByZeroException>()
    	.CircuitBreaker(2, TimeSpan.FromMinutes(1), onBreak, onReset);
    

    发生2次异常之后,断开回路1分钟, 在触发断路时触发onBreak方法,当重置断路器时,触发onReset方法

    后备策略

    Policy
        .Handle<Whatever>()
        .Fallback<UserAvatar>(UserAvatar.Blank)
    

    当程序触发异常/故障后,返回一个备用值

    Policy
        .Handle<Whatever>()
        .Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar())
    

    当程序触发异常/故障后,使用一个方法返回一个备用值

    Policy
       .Handle<Whatever>()
       .Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) => 
        {
            // do something
        });
    

    当程序触发异常/故障后,返回一个备用值,并触发一个方法

    Policy
       .Handle<Whatever>()
       .Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) => 
        {
            // do something
        });
    

    执行策略

    Polly将监控DoSomething方法,如果发生DivideByZeroException异常,就使用重试策略

    var policy = Policy
                  .Handle<DivideByZeroException>()
                  .Retry();
    
    policy.Execute(() => DoSomething());
    

    向Polly上下文中传递任意值

    var policy = Policy
        .Handle<DivideByZeroException>()
        .Retry(3, (exception, retryCount, context) =>
        {
            var methodThatRaisedException = context["methodName"];
    		Log(exception, methodThatRaisedException);
    });
    
    policy.Execute(
    	() => DoSomething(),
    	new Dictionary<string, object>() {{ "methodName", "some method" }}
    );
  • 相关阅读:
    Kotlin 实现类似 C# 的 Event 事件代码
    nim 语言实现迭代器
    nim 语言使用 concept 实现 c# 的interface
    如何在 asp.net core mvc 项目中管理前端插件的引用
    遇到一个在 WPF 中使用 MessageBox 弹出但在打开后却立即自动关闭的问题
    如何在项目生成成功后,自动构建 nuget 包并复制或发布到指定位置
    在类库开发中,如何设定多个 .net 框架目标
    如何在 IIS 中重定向 http 请求至 https
    在 docker 中部署 phpmyadmin 使用 nginx 代理 https 时出现错误无法登录
    禅道中配置电子邮件发信遇到 SMTP 错误:无法连接到 SMTP 主机,点击重试可以成功
  • 原文地址:https://www.cnblogs.com/lwqlun/p/8119856.html
Copyright © 2011-2022 走看看