【发布时间】:2018-12-20 16:16:39
【问题描述】:
我有以下政策:
var retryPolicy = Policy.Handle<Exception>(e => (e is HttpRequestException || e.InnerException is HttpRequestException)).WaitAndRetry(
retryCount: maxRetryCount,
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
onRetry: (exception, calculatedWaitDuration, retryCount, context) =>
{
Log.Error($"Retry => Count: {retryCount}, Wait duration: {calculatedWaitDuration}, Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}, Exception: {exception}.");
});
var circuitBreaker = Policy.Handle<Exception>(e => (e is HttpRequestException || e.InnerException is HttpRequestException)).CircuitBreaker(maxExceptionsBeforeBreaking, TimeSpan.FromSeconds(circuitBreakDurationSeconds), onBreak, onReset);
var sharedBulkhead = Policy.Bulkhead(maxParallelizations, maxQueuingActions, onBulkheadRejected);
var fallbackForCircuitBreaker = Policy<bool>
.Handle<BrokenCircuitException>()
.Fallback(
fallbackValue: false,
onFallback: (b, context) =>
{
Log.Error($"Operation attempted on broken circuit => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
}
);
var fallbackForAnyException = Policy<bool>
.Handle<Exception>()
.Fallback(
fallbackAction: (context) => { return false; },
onFallback: (e, context) =>
{
Log.Error($"An unexpected error occured => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
}
);
var resilienceStrategy = Policy.Wrap(retryPolicy, circuitBreaker, sharedBulkhead);
var policyWrap = fallbackForAnyException.Wrap(fallbackForCircuitBreaker.Wrap(resilienceStrategy));
public bool CallApi(ChangeMapModel changeMessage)
{
var httpClient = new HttpClient();
var endPoint = changeMessage.EndPoint;
var headers = endPoint.Headers;
if (headers != null)
{
foreach (var header in headers)
{
if (header.Contains(':'))
{
var splitHeader = header.Split(':');
httpClient.DefaultRequestHeaders.Add(splitHeader[0], splitHeader[1]);
}
}
}
var res = httpClient.PostAsync(endPoint.Uri, null);
var response = res.Result;
response.EnsureSuccessStatusCode();
return true;
}
我这样执行策略:
policyWrap.Execute((context) => CallApi(changeMessage), new Context(endPoint));
问题是当在开路上执行操作时,我在 CircuitBreaker 回调中没有受到打击。
我希望通过策略进行 API 调用,要处理的异常类型为 HttpRequestException。政策定义有问题吗?为什么不调用断路器回退?
【问题讨论】:
-
你能显示
CallApi(...)方法的内容吗?或者提供一个存根/替换CallApi(...)方法将整个事情变成一个可验证的例子? *.com/help/mcve 。这里example code proving FallbackPolicy can handle BrokenCircuitException;也可以作为runnable dotnetfiddle 。 -
我在答案中添加了
CallApi的代码。我特别怀疑我的策略定义,尤其是重试策略和断路器策略处理的异常组合。 -
感谢您发布
CallApi()方法。我能够根据发布的代码创建评论 *.com/help/mcve。您的确切原因可能取决于您选择的特定配置参数,但希望完整注释的示例提供了足够的探索途径。