我有以下政策:
var sharedBulkhead = Policy.BulkheadAsync(
maxParallelization: maxParallelizations,
maxQueuingActions: maxQueuingActions,
onBulkheadRejectedAsync: (context) =>
{
Log.Info($"Bulk head rejected => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
return TaskHelper.EmptyTask;
}
);
var retryPolicy = Policy.Handle<Exception>(e => (e is HttpRequestException)).WaitAndRetryAsync(
retryCount: maxRetryCount,
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
onRetryAsync: (exception, calculatedWaitDuration, retryCount, context) =>
{
Log.Error($"Retry => Count: {retryCount}, Wait duration: {calculatedWaitDuration}, Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}, Exception: {exception}.");
return TaskHelper.EmptyTask;
});
var circuitBreaker = Policy.Handle<Exception>(e => (e is HttpRequestException)).CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: maxExceptionsBeforeBreaking,
durationOfBreak: TimeSpan.FromSeconds(circuitBreakDurationSeconds),
onBreak: (exception, timespan, context) =>
{
Log.Error($"Circuit broken => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}, Exception: {exception}");
},
onReset: (context) =>
{
Log.Info($"Circuit reset => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
}
);
var fallbackForCircuitBreaker = Policy<bool>
.Handle<BrokenCircuitException>()
.FallbackAsync(
fallbackValue: false,
onFallbackAsync: (b, context) =>
{
Log.Error($"Operation attempted on broken circuit => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
return TaskHelper.EmptyTask;
}
);
var fallbackForAnyException = Policy<bool>
.Handle<Exception>()
.FallbackAsync(
fallbackAction: (ct, context) => { return Task.FromResult(false); },
onFallbackAsync: (e, context) =>
{
Log.Error($"An unexpected error occured => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
return TaskHelper.EmptyTask;
}
);
var resilienceStrategy = Policy.WrapAsync(retryPolicy, circuitBreaker, sharedBulkhead);
var policyWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(resilienceStrategy));
我这样执行政策:
Task.Run(() =>
{
foreach (var changeMessage in changeMessages)
{
policyWrap.ExecuteAsync((context) => CallApi(changeMessage), new Context(endPoint));
}
});
在首次调用fallbackForCircuitBreaker之后没有重试。我希望重试按等待时间进行,而不管电路处于什么状态。为什么这不起作用?
答案 0 :(得分:2)
在首次调用fallbackForCircuitBreaker之后没有重试。我希望按照等待时间重试,而不管电路处于什么状态。
重试策略未配置为仅BrokenCircuitException
处理HttpRequestException
。
要使BrokenCircuitException
的重试策略也重试,请配置策略:
var retryPolicy = Policy
.Handle<HttpRequestException>()
.Or<BrokenCircuitException>()
.WaitAndRetryAsync( /* etc */ );
注意:如果仅进行了上述更改,则会在问题中发布的PolicyWrap
中对策略进行排序:
.., fallbackForCircuitBreaker, retryPolicy, circuitBreaker, sharedBulkhead
表示fallbackForCircuitBreaker
仅在所有重试均失败且最后一次重试失败且BrokenCircuitException
时才被调用。参见PolicyWrap documentation。