C# 如何使用dotnet core和Polly添加动态重试策略
我有一个DotnetCore(2.1)控制台应用程序,我正在使用Polly用重试策略包装我的代码段。这适用于下面所示的简单用例:C# 如何使用dotnet core和Polly添加动态重试策略,c#,exception-handling,.net-core,polly,retrypolicy,C#,Exception Handling,.net Core,Polly,Retrypolicy,我有一个DotnetCore(2.1)控制台应用程序,我正在使用Polly用重试策略包装我的代码段。这适用于下面所示的简单用例: private void ProcessRun() { var policy = Policy.Handle<SocketException>().WaitAndRetryAsync( retryCount: 3 sleepDurationProvider: attempt =&
private void ProcessRun()
{
var policy = Policy.Handle<SocketException>().WaitAndRetryAsync(
retryCount: 3
sleepDurationProvider: attempt => TimeSpan.FromSeconds(10),
onRetry: (exception, calculatedWaitDuration) =>
{
Console.WriteLine($"Retry policy executed for type SocketException");
});
try
{
CancellationTokenSource _cts = new CancellationTokenSource()
PollyRetryWaitPolicy.ExecuteAsync(async token => {
MyOperation(token);
}, _cts.Token)
.ContinueWith(p => {
if (p.IsFaulted || p.Status == TaskStatus.Canceled)
{
Console.WriteLine("faulted or was cancelled");
}
})
.ConfigureAwait(false);
}
catch (Exception ex) {
Console.WriteLine($"Exception has occurred: {ex.Message}");
}
}
执行代码时,将按预期捕获套接字异常
我正在寻找一种灵活的方法,用多个策略而不是一个策略来包装代码。我修改了代码,动态地添加了许多包装的Polly重试策略,以允许捕获多个错误类型,并轻松地更改我正在查找的异常。我将代码更改为:
internal PolicyWrap PollyRetryWaitPolicy;
public void AddRetryWaitPolicy<T>(int waitTimeInSeconds, int retryAttempts)
where T: Exception
{
// Setup the polly policy that will be added to the executing code.
var policy = Policy.Handle<T>().WaitAndRetryAsync(
retryCount: retryAttempts,
sleepDurationProvider: attempt => TimeSpan.FromSeconds(waitTimeInSeconds),
onRetry: (exception, calculatedWaitDuration) =>
{
Console.WriteLine($"Retry policy executed for type {typeof(T).Name}");
});
if (host.PollyRetryWaitPolicy == null)
{
// NOTE: Only add this timeout policy as it seems to need at least one
// policy before it can wrap! (suppose that makes sense).
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromSeconds(waitTimeInSeconds), TimeoutStrategy.Pessimistic);
PollyRetryWaitPolicy = policy.WrapAsync(timeoutPolicy);
}
else
{
PollyRetryWaitPolicy.WrapAsync(policy);
}
}
private void ProcessRun()
{
AddRetryWaitPolicy<SocketException>(10, 5);
AddRetryWaitPolicy<InvalidOperationException>(5, 2);
try
{
Console.WriteLine($"Calling HostedProcess.Run() method. AwaitResult: {awaitResult}");
CancellationTokenSource _cts = new CancellationTokenSource()
PollyRetryWaitPolicy.ExecuteAsync(async token => {
MyOperation(token);
}, _cts.Token)
.ContinueWith(p => {
if (p.IsFaulted || p.Status == TaskStatus.Canceled)
{
Console.WriteLine("Process has faulted or was cancelled");
}
})
.ConfigureAwait(false);
}
catch (Exception ex) {
Console.WriteLine($"Exception has occurred: {ex.Message}");
}
}
但当我尝试以下操作时,它不会按预期重试2次(根本不会重试):
我做错了什么?以上所有内容的要点是根据需要动态地执行多个策略。除了暴政,还有更好的办法吗
提前感谢您的指点 这里:
if (host.PollyRetryWaitPolicy == null)
{
// NOTE: Only add this timeout policy as it seems to need at least one
// policy before it can wrap! (suppose that makes sense).
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromSeconds(waitTimeInSeconds), TimeoutStrategy.Pessimistic);
PollyRetryWaitPolicy = policy.WrapAsync(timeoutPolicy);
}
else
{
PollyRetryWaitPolicy.WrapAsync(policy);
}
在wrap中,if
分支和else
分支对重试策略和超时策略的排序方法不一致
- 在
分支中,超时策略包装在重试策略中。因此,超时将作为每次尝试的超时if
- 在
分支中,任何现有的重试和超时策略都被包装在新的重试策略之外。因此,超时策略在新的重试策略之外。else
- 新的重试策略设置为在
之后重试;但是超时策略也设置为在waitTimeInSeconds
之后执行超时。因此,一旦发生第一次重试(对于第二次或后续配置的重试策略),超时将中止整个执行。因此,正如您所观察到的,重试从未发生waitTimeInSeconds
- 新的重试策略设置为在
else
分支更改为:
PollyRetryWaitPolicy = policy.WrapAsync(PollyRetryWaitPolicy);
背景:请参阅。根据您是将
TimeoutPolicy
放置在RetryPolicy
内部还是外部,TimeoutPolicy
作为每次尝试的超时(内部时),还是作为所有尝试的总超时(外部时)
private void MyOperation()
{
Thread.Sleep(2000);
throw new InvalidOperationException();
}
if (host.PollyRetryWaitPolicy == null)
{
// NOTE: Only add this timeout policy as it seems to need at least one
// policy before it can wrap! (suppose that makes sense).
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromSeconds(waitTimeInSeconds), TimeoutStrategy.Pessimistic);
PollyRetryWaitPolicy = policy.WrapAsync(timeoutPolicy);
}
else
{
PollyRetryWaitPolicy.WrapAsync(policy);
}
PollyRetryWaitPolicy = policy.WrapAsync(PollyRetryWaitPolicy);