如何执行多个策略(或将它们合并为一个策略)?
例如,我有:
var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(5));
var policy2 = Policy.Handle<StackOverflowException>().RetryForever();
如何同时将它们应用于一个方法?如何执行多个策略(或将它们合并为一个策略)?
例如,我有:
var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(5));
var policy2 = Policy.Handle<StackOverflowException>().RetryForever();
如何同时将它们应用于一个方法?从 Polly v5.0 开始,新增了一个名为 PolicyWrap 的类,可以让您组合多个策略。
var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(3, i => TimeSpan.FromSeconds(1));
var policy2 = Policy.Handle<StackOverflowException>().RetryForever();
PolicyWrap policyWrap = Policy.Wrap(policy1, policy2);
policyWrap.Execute(someGreatAction);
有几种方法可以结合两个策略。为了完整起见,让我列出所有不同的选项。我会针对每个选项进行推荐:何时使用它以及何时避免使用它
ExceptionDispatchInfo edi = null;
int retryCounter = 0;
var combinedPolicy = Policy
.Handle<DivideByZeroException>()
.Or<StackOverflowException>()
.WaitAndRetry(CalculateSleep());
combinedPolicy.Execute(() => {
try
{
//User code...
throw new DivideByZeroException();
}
catch (Exception ex)
{
edi = ExceptionDispatchInfo.Capture(ex);
edi.Throw();
}
});
IEnumerable<TimeSpan> CalculateSleep()
{
while (true)
{
var wasItADivideByZero = edi.SourceException is DivideByZeroException;
var attempt = retryCounter++;
if (wasItADivideByZero)
{
if (attempt > 3) break;
yield return TimeSpan.FromSeconds(1);
}
yield return TimeSpan.FromSeconds(0);
}
}
WaitAndRetry
没有不需要指定retryCount
但可以在sleepDurations
中访问抛出的异常的重载retryCount
+sleepDurationProvider
(从中可以访问异常),或使用sleepDurations
ExceptionDispatchInfo
来捕获抛出的异常并在自定义的CalculateSleep
方法中访问它var combinedPolicy = Policy
.Handle<DivideByZeroException>()
.Or<StackOverflowException>()
.WaitAndRetry(3,
(_, ex, __) => TimeSpan.FromSeconds(ex is DivideByZeroException ? 1 : 2),
(_, __, ___, ____) => { });
policy1.Execute(() =>
{
policy2.Execute(() =>
{
//User code
});
});
或者
policy2.Execute(() =>
{
policy1.Execute(() =>
{
//User code
});
});
policy1.Execute(policy2.Execute(UserCode()));
Wrap
实例方法var combinedPolicy = policy1.Wrap(policy2);
combinedPolicy.Execute(UserCode());
或者
var combinedPolicy = policy2.Wrap(policy1);
combinedPolicy.Execute(UserCode());
combinedPolicy
的类型是PolicyWrap
,它也实现了ISyncPolicy
接口var combinedPolicy = globalTimeout.Wrap(retry).Wrap(circuitBreaker).Wrap(localTimeout);
void
和另一个针对TResult
的策略,那么系统会尝试智能处理。combinedPolicy
的类型现在是PolicyWrap<string>
。var policy1 = Policy.Handle<DivideByZeroException>().WaitAndRetry(3, i => TimeSpan.FromSeconds(1));
var policy2 = Policy<string>.Handle<StackOverflowException>().RetryForever();
var combinedPolicy = policy1.Wrap(policy2);
string? result = combinedPolicy.Execute(() => "dummy response");
Wrap
静态方法var combinedPolicy = Policy.Wrap(policy2, policy1);
或者
var combinedPolicy = Policy.Wrap(policy2, policy1);
ISyncPolicy
或 ISyncPolicy<TResult>
策略。ISyncPolicy
和 ISyncPolicy<string>
策略,因为所有策略都应该具有相同的类型。var combinedPolicy = Policy.Wrap<HttpResponseMessage>(globalTimeout,retry,circuitBreaker,localTimeout);
TResult
和一个或多个void
TResult
和一个或多个void
TResult1
和TResult2
的两个策略