接着上一篇说, 正好也是最近项目里用到了, 正好拿过来整理一下, 园子里也有一些文章介绍比我详细.
简单介绍一下绍轻量的故障处理库 https://github.com/App-vNext/Polly https://github.com/App-vNext/Polly 是一个. NET 弹性和瞬态故障处理库
允许我们以非常顺畅和线程安全的方式来执行诸如重试, 断路器, 超时, 隔离, 缓存, 后退等策略, 能为我们在微服务架构提供更稳定的服务. 当然, 目前的 Service Mesh 显得更高大上, 而且更强大, 它更偏向从运维层面解决以上问题, 不过这还是的看具体项目中怎么去使用和决定了.
在微服务架构下, 我们可能会遇到类似以下问题:
某些接口异常, 最终造成应用程序池奔溃;
某些接口不稳定, 偶尔超时, 数据获取异常;
某些服务不稳定, 调用方连接不上;
某些服务异常, 最终主服务挂掉 (雪崩效应);
当然在实际情况下, 我们可能只需要确保提供给用户的服务是可用状态, 不出现 "Service Unavailable" 这样的画面就好. 至于接口偶尔异常, 可能对某些类型的项目来说并不太关键, 用户可能通过重新请求, 刷新页面就可以解决, 当然我们还可以在代码层面做兼容, 满满的 try/catch,for/while 循环解决重试来保证更高的可靠性.
这个时候 Polly 就能很好的起来作用, Polly 的使用相对比较简单, 当然还是得看项目结构. 我们的主项目在调用微服务接口时使用了 AOP, 类似这种情况下, 所以调用微服务的接口都是统一入口, 所以我们只需要在 AOP 内加上 Polly 的一些策略, 其他代码不用做任何修改, 就可以解决一些问题了.
安装
Install-Package Polly
使用步骤说明
定义策略
执行方法
可以看一下代码, 我们项目主要使用的是 Grpc 这个框架, 其他的微服务框架, 使用起来大致差不多
- public void Intercept(IInvocation invocation)
- {
- // some code
- try
- {
- // 创建一个策略, 如果 invocation.Proceed 的执行出现 Grpc.Core.RpcException 异常, 并且 StatusCode == Grpc.Core.StatusCode.Unavailable, 则重试一次
- var policy = Policy
- .Handle<Grpc.Core.RpcException>(t => t.Status.StatusCode == Grpc.Core.StatusCode.Unavailable)
- .Retry(); // 默认一次
- // 将策略应用到 invocation.Proceed 方法上
- policy.Execute(invocation.Proceed);
- }
- catch (Exception ex)
- {
- // some code
- Console.WriteLine($"{ ex.Message},{ex.StackTrace}");
- }
- }
- https://github.com/App-vNext/Polly
策略条件定义
策略的执行需要依赖于条件, Polly 支持对异常与结果进行策略条件定义.
异常
- // 指定某个异常
- Policy
- .Handle<SomeExceptionType>();
- // 指定某个异常条件
- Policy
- .Handle<SomeExceptionType>(ex => ex.xxx == "xxx")
- // 指定多个异常
- Policy
- .Handle<SomeExceptionType1>()
- .Or<SomeExceptionType2>()
- // 指定多个可能异常条件
- Policy
- .Handle<SomeExceptionType1>(ex => ex.xxx1 == "xxx")
- .Or<SomeExceptionType2>(ex => ex.xxx2 == "xxx")
返回结果
- // 指定某个结果
- Policy
- .HandleResult<ResponseMessage>(r => r.xxx == "xxx")
- // 指定多个可能的结果
- Policy
- .HandleResult<ResponseMessage>(r => r.xxx1 == "xxx")
- .OrResult<ResponseMessage>(r => r.xxx2 == "xxx")
重试策略 (Retry )
- // 指定异常下重试一次
- Policy
- .Handle<SomeExceptionType>()
- .Retry();
- // 指定异常下重试 3 次
- Policy
- .Handle<SomeExceptionType>()
- .Retry(3);
- // 指定异常下无限重试
- Policy
- .Handle<SomeExceptionType>()
- .RetryForever();
- // 每次重试之间等待指定的时间间隔
- Policy
- .Handle<SomeExceptionType>()
- .WaitAndRetry(new[]
- {
- TimeSpan.FromSeconds(1),
- TimeSpan.FromSeconds(3),
- TimeSpan.FromSeconds(7)
- });
Retry 可以指定一个要执行的 Action.Action 参数: exception 当前异常信息, retryCount 当前执行第几次, context 当前执行上下文信息.
测试一下:
- private static int times = 0;
- public static void TestPolicy()
- {
- var policy = Policy
- .Handle<Exception>()
- .Retry(3, (exception, retryCount, context) => // 出异常会执行以下代码
- {
- Console.WriteLine($"exception:{ exception.Message}, retryCount:{retryCount}, id:{context["id"]}, name:{context["name"]}");
- });
- try
- {
- // 通过 new Context 传递上下文信息
- var result = policy.Execute(Test, new Context("data", new Dictionary<string, object>() { { "id", "1" }, { "name", "beck" } }));
- Console.WriteLine($"result:{result}");
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- private static string Test()
- {
- // 每执行一次加 1
- times++;
- // 前 2 次都抛异常
- if (times < 3)
- {
- throw new Exception("exception message");
- }
- return "success";
- }
测试结果:
可以看到得到了咱们想要的效果, 具体项目可以具体去实施, 下一篇咱们接着说 https://github.com/App-vNext/Polly 的熔断策略. 感兴趣可以自行搜索 Polly 的相关文档看看.
参考链接
- https://github.com/App-vNext/Polly
- Polly Project http://www.thepollyproject.org/
- https://github.com/beckjin/PollySamples
没有彩蛋
来源: https://www.cnblogs.com/DanielYao/p/11086574.html