书籍Release It!中的断路器模式可保护远程服务在发生故障(或恢复)时免受请求的影响,并帮助客户端管理重复的远程服务故障。我喜欢Davy Brion’s stateful circuit breaker而Ayende’s lazy timeout fix非常干净。
但是,我没有看到很多过滤的实现,这些异常会导致断路器的故障数量增加。
不要担心显示锁定,除非您的实现特别依赖于聪明的锁定。仅供参考,Phil Haack似乎有latest version of TimedLock,用于Davy Brion的文章。
答案 0 :(得分:3)
predicate可以提供扩展标准和过滤逻辑。
public void AttemptCall(Action action, Predicate<Exception> match)
{
try
{
action();
}
catch(Exception e)
{
if(match(e))
state.ActUponException(e);
throw;
}
}
例如,您可能只想在超时引起的WebException
上增加断路器。
circuitBreaker.AttemptCall(() => service.DoWork(), e =>
{
WebException local = e as WebException;
if(local == null)
return false;
return local.Status == WebExceptionStatus.Timeout;
});
答案 1 :(得分:1)
您首先想到的是使用通用try... catch
块构造泛型方法调用。但是,由于a .NET bug,以下内容无效,请参阅these questions了解详情。
public void AttemptCall<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch(TException e)
{
state.ActUponExcpetion(e);
throw;
}
}
您需要捕获所有异常并调查类型。
public void AttemptCall<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch(TException e)
{
if(e is TException)
state.ActUponExcpetion(e);
throw;
}
}
答案 2 :(得分:1)
private readonly List<Exception> ignored = new List<Exception>();
public void Ignore<TException>()
where TException : Exception
{
Type type = typeof(TException);
if(ignored.Contains(type))
return;
ignored.Add(type);
}
public void AttemptCall(Action action)
{
try
{
action();
}
catch(Exception e)
{
if(!ignore.Contains(e.GetType()))
state.ActUponException(e);
throw;
}
}