我考虑使用Polly来创建记录异常和重新抛出的策略。 我没有找到允许开箱即用的现有方法,但我看到的一些选项是
后备
// Specify a substitute value or func, calling an action (eg for logging) if the fallback is invoked.
Policy.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>
{ _logger.Log(exception, context);
throw exception;
});
问题:可以从Fallback抛出异常吗?
超时
Policy.Timeout(1, T30meoutStrategy.Pessimistic, (context, timespan, task) =>
{ task.ContinueWith(t =>
{ // ContinueWith important!: the abandoned task may very well still be executing, when the caller times out on waiting for it!
if (t.IsFaulted )
{
logger.Error(context,t.Exception);
throw exception;
} );
或重试
Policy.Handle<DivideByZeroException>().Retry(0, (exception, retryCount) =>
{ logger.Error(context,exception);
throw exception;
} );
问题:是否支持0次重试?
或者KISS并自己写点简单的try / catch 。
哪种方法更好? 你有什么建议?
答案 0 :(得分:11)
如果你还没有混合使用Polly,那么尝试/ catch似乎最简单。
如果您已经混合使用Polly,FallbackPolicy
可以按照您的建议安全地重新使用。 onFallback
委托和后备操作或值are not governed by the .Handle<>()
clauses of the Policy,因此您可以安全地从onFallback
代理中重新抛出异常。
Policy<UserAvatar>.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>
{ _logger.Log(exception, context);
throw exception;
});
你的问题用TimeoutPolicy
概述的方法只能捕获调用者之前由于超时而离开的代理抛出的异常,并且仅在TimeoutMode.Pessimistic
中;并非所有例外情况。
您的问题概述.Retry(0, ...)
的方法不起作用。如果未指定重试,则不会调用onRetry
委托。
为了避免重新调整FallbackPolicy
的不整洁,您还可以在Polly的结构中编写自己的LogThenRethrowPolicy
代码。 This commit(添加了简单的NoOpPolicy
)举例说明了添加新政策所需的最低要求。您可以添加类似于NoOpPolicy
但只有try { } catch { /* log; rethrow */ }
编辑2019年1月:Polly.Contrib现在还包含Polly.Contrib.LoggingPolicy,可以为此提供帮助。
答案 1 :(得分:-1)
https://github.com/App-vNext/Polly-Samples/blob/master/PollyDemos/Async/AsyncDemo02_WaitAndRetryNTimes.cs显示您至少可以对WaitAndRetryAsync使用onRetry:
选项。我还没有看其他人。
HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) // exponential back-off: 2, 4, 8 etc
+ TimeSpan.FromMilliseconds(Jitterer.Next(0, 1000)), // plus some jitter: up to 1 second
onRetry: (response, calculatedWaitDuration) =>
{
logger.LogError($"Failed attempt. Waited for {calculatedWaitDuration}. Retrying. {response.Exception.Message} - {response.Exception.StackTrace}");
}
);