.Net Core 使用弹性和瞬态故障处理库Polly
1、Polly介绍
1、Polly是一个基于.NET的弹性及瞬态故障处理库,允许开发人员以顺畅及线程安全的方式执行重试(Retry)、断路(Circuit Breaker)、超时(Timeout)、隔离(Bulkhead Isolation)和回退策略(Fallback ),polly的介绍中有个很关键的词是瞬态故障,这个词也很好的诠释了Polly使用的一个背景.瞬态故障,就是指我们的程序在运行当中可能会发生故障, 这些故障包含程序运行中的异常、返回结果不符等。弹性是指Polly在应对这些故障时具有灵活性,且其提供的策略也可以很灵活的组合在一起使用。
2、Polly的使用
1、在Nuget中下载Polly安装包,安装成功即可使用
2、我对此Polly稍微封装成个类供大家学习
public class PollyEngin { /// <summary> /// /// </summary> /// <typeparam name="TException">指定需要重试异常的类型</typeparam> /// <typeparam name="TResult">指定返回值类型</typeparam> /// <param name="action">需要执行的Action</param> /// <param name="timeSpans">执行的次数以及次数之间的间隔时间</param> /// <returns></returns> public static async Task<TResult> PollyResultWaitAndRetryAsync<TException, TResult>(Func<Task<TResult>> action, params TimeSpan[] timeSpans) where TException : Exception { var policy = Policy .Handle<TException>() .WaitAndRetryAsync(timeSpans, (e, tiempo, intento, contexto) => { Console.WriteLine($"{action.Method.Name}执行失败,{intento:00} (调用秒数: {tiempo.Seconds} 秒),异常来自:{e.ToString()}"); }); return await policy.ExecuteAsync(action); } /// <summary> /// /// </summary> /// <typeparam name="TException">指定需要重试异常的类型</typeparam> /// <param name="action">需要执行的Action</param> /// <param name="timeSpans">执行的次数以及次数之间的间隔时间</param> /// <returns></returns> public static async Task PollyResultWaitAndRetryAsync<TException>(Func<Task> action, params TimeSpan[] timeSpans) where TException : Exception { var policy = Policy .Handle<TException>() .WaitAndRetryAsync(timeSpans, (e, tiempo, intento, contexto) => { Console.WriteLine($"{action.Method.Name}执行失败,{intento:00} (调用秒数: {tiempo.Seconds} 秒),异常来自:{e.ToString()}"); }); await policy.ExecuteAsync(action); } /// <summary> /// /// </summary> /// <typeparam name="TException">指定需要重试异常的类型</typeparam> /// <param name="action">需要执行的Action</param> /// <param name="keyValues">需要执行的Action入参参数,格式使用key values</param> /// <param name="timeSpans">执行的次数以及次数之间的间隔时间</param> /// <returns></returns> public static async Task PollyResultWaitAndRetryAsync<TException>(Func<Context, Task> action, Context keyValues, params TimeSpan[] timeSpans) where TException : Exception { var policy = Policy .Handle<TException>() .WaitAndRetryAsync(timeSpans, (e, tiempo, intento, contexto) => { Console.WriteLine($"{action.Method.Name}执行失败,{intento:00} (调用秒数: {tiempo.Seconds} 秒),异常来自:{e.ToString()}"); }); await policy.ExecuteAsync(action, keyValues); } /// <summary> /// /// </summary> /// <typeparam name="TException">指定需要重试异常的类型</typeparam> /// <typeparam name="TResult">指定返回值类型</typeparam> /// <param name="action">需要执行的Action</param> /// <param name="keyValues">格式使用key values</param> /// <param name="timeSpans">执行的次数以及次数之间的间隔时间</param> /// <returns></returns> public static async Task PollyResultWaitAndRetryAsync<TException, TResult>(Func<Context, Task<TResult>> action, Context keyValues, params TimeSpan[] timeSpans) where TException : Exception { var policy = Policy .Handle<TException>() .WaitAndRetryAsync(timeSpans, (e, tiempo, intento, contexto) => { Console.WriteLine($"{action.Method.Name}执行失败,{intento:00} (调用秒数: {tiempo.Seconds} 秒),异常来自:{e.ToString()}"); if (keyValues.TryGetValue("retryCount", out object count)) keyValues.Remove("retryCount"); keyValues.Add("retryCount", intento); }); await policy.ExecuteAsync(action, keyValues); } }
3、PollyEngin使用方式
class Program { static void Main(string[] args) { var result = PollyEngin.PollyResultWaitAndRetryAsync<Exception>(task, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10)); Console.ReadLine(); } public async static Task task() { Console.WriteLine("任务开始"); await Task.Delay(TimeSpan.FromSeconds(1)); Console.WriteLine("任务结束"); throw new Exception(); } }
结果展示: