第一次接触 Polly 仍是在作某个微服务系统的时候,那时只会使用单一的超时策略与重试策略,更加高级的特性就没有再进行学习了。最近开为某个客户开发 PC 端的上位机的时候,客户有个需求,在发起请求以后若是 5 秒钟没有响应则进行重试,总共能够重试 3 次,若是 3 次请求都未返回数据,就视为请求失败。html
关于 Polly 的高级用法能够参考官方的 Wiki 文档便可,国内也有不少优秀的介绍文章,例如 这篇 和 这篇。git
查阅了 Polly 的官方文档以后,发现 Polly 提供了策略组合功能,每一个 Policy 实例均可以调用其 Wrap()
方法与另一个策略进行组合。github
或者是经过 Policy
静态类提供的 Warp()
静态方法来指定须要组合的两个策略。异步
根据需求描述来看,咱们须要用到超时策略和重试策略,只要将其组合便可。不过这里须要注意一个坑,即他们的组合顺序。async
正确的组合顺序应该是 重试策略.Warp(超时策略) ,而不是 超时策略.Warp(重试策略) 。这是由于在超时以后 Polly 会抛出 TimeoutRejectedException
异常,在重试策略捕获到该异常以后,就会开始重试操做,即后面组合策略的 ExecuteAsync()
方法接收的委托。微服务
首先咱们定义一个方法,该方法用于组合策略(超时+重试),由于我这里是传入的异步委托操做,因此返回的是 AsyncPolicy
对象。学习
private AsyncPolicyWrap BuildTimeoutRetryPolicy(string msg) { // 超时策略,执行目标委托超过 5 秒则视为超时,抛出异常。 var timeoutPolicy = Policy.TimeoutAsync(5); // 重试策略,重试 2 次,每次打印信息。 var retryPolicy = Policy.Handle<TimeoutRejectedException>().RetryAsync(2, (exception, i) => { Console.WriteLine("开始第 i 次重试..."); }); return retryPolicy.WrapAsync(timeoutPolicy); }
定义好策略以后,就是咱们的实际应用了。这里说明一下执行逻辑,当第一次请求的时候若是发生了超时的状况,则进入重试策略,重试两次,当最后一次仍然抛出 TimeoutRejectedException
异常,则重试策略再也不捕获,直接将异常抛出给调用者。ui
private async Task<string> GetResult(AsyncPolicyWrap policy) { try { return await policy.ExecuteAsync(() => SendDataAsync(sendProtocol)); } catch (TimeoutRejectedException) { return "超时"; } }