架构师_程序员

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 182|回复: 3

[框架] .NET弹性和瞬态故障处理Polly重试策略

[复制链接]
跳转到指定楼层
楼主
发表于 2019-5-28 23:54:53
zu
本帖最后由 空蝉如此世 于 2019-5-29 11:16 编辑

前言
在项目中,会因为不可控的原因,造成项目运行出现问题。比如 服务器故障,某个服务崩了,网络断了等等。遇到一些可重试的错误,我们可以使用 Polly —— .NET弹性和瞬态故障处理库。项目官网地址(https://github.com/App-vNext/Polly)。今天本篇将记录Polly 的错误重试策略。


环境&工具


>VS 2017
>Windows 10 系统


正文


1:新建控制台应用程序。

2:引用Polly . 可在 NuGet 程序包中下载

3:贴入代码

  1. using Polly;
  2. using System;

  3. namespace PollyTest
  4. {
  5.     class Program
  6.     {
  7.         static void Main(string[] args)
  8.         {
  9.             try
  10.             {
  11.                 var retryTwoTimesPolicy =
  12.                      Policy
  13.                          .Handle<DivideByZeroException>()
  14.                          .Retry(3, (ex, count) =>
  15.                          {
  16.                              Console.WriteLine("执行失败! 重试次数 {0}", count);
  17.                              Console.WriteLine("异常来自 {0}", ex.GetType().Name);
  18.                          });
  19.                 retryTwoTimesPolicy.Execute(() =>
  20.                 {
  21.                     Compute();
  22.                 });
  23.             }
  24.             catch (DivideByZeroException e)
  25.             {
  26.                 Console.WriteLine($"Excuted Failed,Message: ({e.Message})");
  27.             }
  28.             Console.WriteLine("重试结束!");
  29.             Console.ReadKey();
  30.         }

  31.         static int Compute()
  32.         {
  33.             var a = 0;
  34.             return 1 / a;
  35.         }
  36.     }
  37. }
复制代码


4:F6 生成。然后在 debug 文件夹下找到生成的 .exe 文件  ——> 双击运行。



可以看到输出信息:重试了三次。

F5 进行调试的时候,也可以看到 这个方法走了三次。


Polly 重试策略详解

1:异常类型
  1. var retryTwoTimesPolicy =
  2.                      Policy
  3.                          .Handle<DivideByZeroException>()
  4.                          .Retry(3, (ex, count) =>
  5.                          {
  6.                              Console.WriteLine("执行失败! 重试次数 {0}", count);
  7.                              Console.WriteLine("异常来自 {0}", ex.GetType().Name);
  8.                          });
  9.                 retryTwoTimesPolicy.Execute(() =>
  10.                 {
  11.                     Compute();
  12.                 });
复制代码


这段代码里面 :handle  里面是填 重试的异常类型。就是说,当执行的代码,产生特定的异常时,执行重试功能。反之,则不执行重试。因为有些异常没有重试的必要。

当然,我们可以在这里填写多种具体的异常类型去重试。

  1. Policy
  2.                     .Handle<SqlException>()
  3.                     .Or<SmtpException>()
  4.                     .Or<DivideByZeroException>()
复制代码


这里的 DivideByZeroException   表示尝试除以零 的异常。
SqlException   表示当Sql Server 返回错误或警告引发的异常。比如数据库连接失败,Sql 执行错误等。
SmtpException  表示邮件服务引发的异常。比如,发送失败,网络连接失败,邮件账号信息异常。

具体一些异常类型可参考微软官方文档:



2:重试类型

1) 第一种重试类型,是直接给定重试次数。下面这个代码是只 重试 3次。
  1. Policy
  2.                          .Handle<Exception>()
  3.                          .Retry(3);
复制代码

我们可以在重试的时候,调用每次重试进行的相关操作。如下面这段代码,在后面又传了一个委托。在执行重试的时候,打印出了重试次数和异常原因。

  1. Policy
  2.                          .Handle<Exception>()
  3.                          .Retry(3, (ex, count) =>
  4.                          {
  5.                              Console.WriteLine("执行失败! 重试次数 {0}", count);
  6.                              Console.WriteLine("异常来自 {0}", ex.GetType().Name);
  7.                          });
复制代码


我们还可以让这个代码一直重试下去,直到执行成功。

  1. Policy
  2.                          .Handle<Exception>()
  3.                          .RetryForever();
复制代码


2)第二种重试类型,是以时间间隔来进行重试。下面这段代码是指,隔2秒,7秒,10秒重试一次。重试到10秒的时候。还没执行成功,就结束重试。

  1. Policy
  2.                     .Handle<Exception>()
  3.                     .WaitAndRetry(new[]
  4.                                     {
  5.                                         TimeSpan.FromSeconds(2),
  6.                                         TimeSpan.FromSeconds(7),
  7.                                         TimeSpan.FromSeconds(10)
  8.                                     });
复制代码


我们也可以用时间间隔重试,一直到重试成功为止。这个就需要一个函数的计算。

  1. Policy
  2.                     .Handle<Exception>()
  3.                     .WaitAndRetryForever(retryAttempt =>
  4.                         TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
  5.                      );
复制代码


上面这段代码,是指 间接2的幂次方重试。比如,执行失败,第一次间隔2秒重试,第二次间隔4秒重试,第三次间隔8秒重试.........依此类推。直到执行成功为止。



尾声


注意:上面的代码 Handle 里面的异常类型,要根据自己实际项目中的实际情况来填写。不是所有的异常都需要重试。

Exception 异常类型是所有异常的基类。在Handle 里面最好不要填写这个,要不然,会产生很严重的后果。














上一篇:.Net集成paypal IPN 返回值一直是 INVALID
下一篇:c# yield关键字的用法
帖子永久地址: 

架构师_程序员 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与架构师_程序员享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和架构师_程序员的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、架构师_程序员管理员和版主有权不事先通知发贴者而删除本文

码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
沙发
发表于 2019-5-29 09:17:54
我在aop中自己实现了重试机制,最后,才发现Polly这个类库可以满足我的需求,但是,自己功能已经实现了,引用第三方类库,里面可能会有一些无用的代码,并不能优化我的系统,所以暂时没用。

附上我的代码:

  1. public class AopService : IInterceptor
  2.     {
  3.         public void Intercept(IInvocation invocation)
  4.         {
  5.             var isSucceeded = false;
  6.             var retries = 3;
  7.             while (!isSucceeded)
  8.             {
  9.                 try
  10.                 {
  11.                     ......
  12.                     isSucceeded = true;
  13.                 }
  14.                 catch (Exception ex)
  15.                 {
  16.                     Common.LogHelper.WriteLog("ef", ex);
  17.                     if (retries >= 0)
  18.                     {
  19.                         //Console.WriteLine("重试中...");
  20.                         retries--;
  21.                     }
  22.                     else
  23.                     {
  24.                         throw;
  25.                     }
  26.                 }

  27.             }
  28.         }
  29.     }
复制代码


有空,我也要研究一下Polly
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
板凳
发表于 2019-5-29 09:22:01
小渣渣 发表于 2019-5-29 09:17
我在aop中自己实现了重试机制,最后,才发现Polly这个类库可以满足我的需求,但是,自己功能已经实现了,引 ...

像这种小的需求  自己完成没有什么问题
而且 你这个 重试是不是应该等待下时间
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
地板
发表于 2019-5-29 09:29:22
winds 发表于 2019-5-29 09:22
像这种小的需求  自己完成没有什么问题
而且 你这个 重试是不是应该等待下时间 ...

不需要,异常肯定是并发,数据插入、更新、删除冲突造成的,但是肯定有一个会执行成功,我.......省略的代码,包裹了事务,异常的会自动回滚。第二次重试的时候,冲突就没了,所以我没有设置等待时间。
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

Mail To:help@itsvse.com

QQ|Archiver|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2019-7-17 11:28

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表