我使用Azure,我有简单的尝试catch块 我现在正在做的是,当我们有任何错误时,我会通过电子邮件发送错误消息,我现在想要检测瞬态错误,只是忽略为他们发送电子邮件
private void SomeMethod()
{
try
{
// Do stuff
}
catch (Exception ex)
{
HandleError(ex);
return RedirectToAction("Index", "Error");
}
}
protected void HandleError(Exception ex)
{
//and here i want to check if the cause of exception is not a transient error then write a code to email the error details
}
答案 0 :(得分:1)
如果您使用的是Azure Client SDK(最新版本> = v4.3.0.0),则默认重试策略为指数重试。即使您没有专门定义任何重试策略,情况也是如此。客户端SDK指数重试策略具有基于几乎从Azure存储服务响应返回的HttpStatusCode来检测瞬态错误的逻辑。当您向azure存储发出请求时,所有这些重试都将透明地完成,如果该请求失败并且客户端sdk认为是错误的错误(几乎所有5xx Http状态代码)。
如果您想完全停止客户端SDK重试并在catch块中自行完全控制它,那么您可以将NoRetry策略作为[Table / Blob / Queue] RequestOptions的一部分传递,以关闭重试引擎盖下由客户端SDK完成。
然后在catch块中,您将需要捕获客户端SDK在失败的请求上抛出的StorageException,解析其中嵌入的HttpStatusCode,根据错误是否是瞬态做出决定并采取相应的措施行动。
当然不是所有的异常都是StorageException,你也可能会得到非存储异常,比如null ref等。你也可以为那些做同样的过程,它们通常都是非瞬态的。
如果你想走那条路,你应该确切地知道你在做什么,实际的客户端SDK在它自己的瞬态错误检测和重试机制中做了什么,以及完全关闭它的影响。我已经看到很多人在没有完全理解它的作用的情况下摆弄Azure存储RetryPolicies,并最终因为客户端SDK已经重试的不必要的重试而导致服务过载,或导致更多的延迟,更低的吞吐量等。
答案 1 :(得分:0)
根据您刚刚发布的链接以及提供的代码示例:
// Define your retry strategy: retry 3 times, 1 second apart.
var retryStrategy = new FixedInterval(3, TimeSpan.FromSeconds(1));
// Define your retry policy using the retry strategy and the Azure storage
// transient fault detection strategy.
var retryPolicy =
new RetryPolicy<StorageTransientErrorDetectionStrategy>(retryStrategy);
// Do some work that may result in a transient fault.
try
{
// Call a method that uses Azure storage and which may
// throw a transient exception.
retryPolicy.ExecuteAction(
() =>
{
this.queue.CreateIfNotExist();
});
}
catch (Exception)
{
// All of the retries failed.
}
根据该文档,不会引发异常直到它不再是您的重试策略定义的暂时性错误。实际上 - 利用瞬态故障处理应用程序块已经在你的问题中做了你正在问的事情。静默重试(无例外)重试,直到发生异常的时间点发生 - 当重试发生时超过重试策略。
以下不应被视为“良好代码”,它仅仅是TFHAB 如何确定瞬态错误的示例。
private void DoStuff()
{
try
{
this.DoSomethingThatCouldPotentiallyCauseTransientErrors(5);
}
catch (Exception ex)
{
// This would not be caught until the "retries" have occurred.
this.HandleException(ex);
return RedirectToAction("Index", "Error");
}
}
private void DoSomethingThatCouldPotentiallyCauseTransientErrors(int retryAttemptsBeforeExceptionThrown)
{
// Note that this will *always throw an exception*,
// I'm (attempting to) simply demonstrate my point of how the transient errors could be defined.
for (int i = 0; i < retryAttemptsBeforeExceptionThrown)
{
try
{
int x = 0;
int y = 0;
int result = x / y;
}
catch (Exception)
{
if (i < retryAttemptsBeforeExceptionThrown-1)
{
// Swallow/ignore the exception, and retry
// Note that anything hitting this block would be considered a "transient error",
// as we are not raising an exception
}
else
{
// Too many failed attempts have occurred, ***now*** we raise an exception to the caller
throw;
}
}
}
}
private void HandleException(Exception ex)
{
// Implementation
}
希望在“瞬态错误”的背景下向约翰回答你的问题
答案 2 :(得分:0)
您可以使用我的Apache许可Griffin.Framework
中的信号public class YourController
{
static Signal _errorsignal = Signal.Create("YourController.Error");
public ActionResult SomeAction()
{
try
{
//some logic
//logic succeeded, reset
_errorSignal.Reset();
}
catch (Exception ex)
{
//Raised for the first time, notify
if (_errorSignal.Raise(ex))
HandleError(ex);
return RedirectToAction("Index", "Error");
}
//[...]
}
它可以跟踪状态,还可以将状态更改(从所有信号)上传到HTTP服务器。
您可以将以下内容放在global.asax中,而不是在每个控制器中都有HandleError:
//put in the Init method
Signal.SignalRaised += OnGlobalHandling;
public void OnGlobalHandling(object sender, SignalRaisedEventArgs e)
{
var signal = (Signal)sender;
//send email
}