Polly is .NET a resilient and transient fault processing library under the platform, which allows developers to smooth and thread-safe way to express policies, such as retry, fuse, time-out, bulkheads and other isolation and rollback
Retry
Once retry
Retry()
No parameter indicates try again
private static async Task RetryOnce()
{
var policy = Policy.Handle<CustomException>()
.Retry(3);
await policy.Execute(() => FooFunction());
}
Results of the
Multiple retries
Retry(N)
N represents the execution of this retry
var policy = Policy.Handle<CustomException>()
.Retry(3);
await policy.Execute(() => FooFunction());
Results of the
It has been retried until it succeeds
Use
RetryForever()
keep retrying
private static async Task RetryForeverUntilSuccess()
{
var policy = Policy.Handle<CustomException>()
.RetryForever();
await policy.Execute(() => FooFunction());
}
Results of the
After waiting for a specified time to retry
Use
WaitAndRetry()
andWaitAndRetryAsync()
after a specified waiting time to retry
private static async Task RetryAfterWait()
{
var policy = Policy.Handle<CustomException>()
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(4)
});
await policy.ExecuteAsync(() => FooFunction());
}
After waiting for a specified time keep retrying until it succeeds
Use
WaitAndRetryForever()
orWaitAndRetryForeverAsync()
keep retrying after the specified actual, know success
private static async Task RetryForeverUntilSuccessAfterWait()
{
var policy = Policy.Handle<CustomException>()
.WaitAndRetryForeverAsync(retryAttempt =>
TimeSpan.FromSeconds(1));
await policy.ExecuteAsync(() => FooFunction());
}
Each custom logic before retry processing
Each time before retry, we can customize some logic processing, such as logging the like.
private static async Task RetryManyWithCustomLogic()
{
var policy = Policy.Handle<CustomException>()
.Retry(3, onRetry: (exception, retryCount) =>
{
Console.WriteLine($"{nameof(RetryManyWithCustomLogic)},第{retryCount}重试:{exception.Message}");
});
await policy.Execute(() => FooFunction());
}
Results of the
Fuse
Use
CircuitBreaker
of blown calls control
public static async Task CircuitBreaker()
{
// 熔断策略:如果连续3次出发了CustomException异常,将在2秒内终止所有请求
var policy = Policy.Handle<CustomException>()
.CircuitBreaker(3, TimeSpan.FromSeconds(2));
for (int i = 0; i < 10; i++) // 模拟10次调用
{
try
{
await policy.Execute(() => FooFunction());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
await Task.Delay(1000);
}
}
}
Results of the
Fallback (Fallback)
Fallback
It allows us to program when ye be some failures, provide backup operations (contingency plans)
public static void Fallback()
{
var policy = Policy.Handle<CustomException>()
.Fallback(async () => FunctionFallback());
policy.Execute(() => Function());
}
The above code omissions
- A defined error / fault
class CustomException : Exception
{
public CustomException(string message) : base(message){}
}
- Functions to be performed
static int ctr = 0;
static Task FooFunction()
{
ctr++;
if (ctr >= 11) // 假设重试10次执行成功
{
return default;
}
Console.WriteLine($"{DateTime.Now:HH:mm:ss fff} {nameof(FooFunction)}:第{ctr}次执行");
throw new CustomException($"{nameof(FooFunction)}发生异常");
}
static void Function()
{
try
{
throw new CustomException($"{nameof(Function)}发生异常");
}
catch (Exception ex)
{
Console.WriteLine($"执行{nameof(Function)}发生异常:{ex.Message}");
throw;
}
}
static void FunctionFallback()
{
Console.WriteLine($"执行{nameof(FunctionFallback)}");
}
- The main function
static async Task Main(string[] args)
{
Console.WriteLine("开始执行");
try
{
await RetryOnce();
}
catch (Exception ex)
{
Console.WriteLine($"{nameof(Main)}发生异常:{ex.Message}");
}
finally
{
Console.WriteLine("执行结束");
}
}
reference
ASP VNext open source service fault-tolerant processing using the document library Polly