Я реализую шаблоны прерывателя и повторных попыток через Polly в .NET Framework 4.5.2.
Я хочу посмотреть, правильно ли мое понимание.
Вопрос 1. Если произошел сбой в сети, и автоматический выключатель достиг номера ExceptionAllowedBeforeBreaking, перешел в открытое состояние и ждал период durationOfBreak, канал будет открыт для новых запросов, но те, которые были отправлены, будут выбрасывать исключение?
Вопрос 2: Если желаемое поведение относится к тем запросам, для которых были повторены исключения, а не к прерывателю, выдавшему исключение, то в дополнение к политике автоматического выключателя должна быть реализована политика повторных попыток. Насколько я понимаю, такое поведение будет иметь место в вопросе 1, а затем будет предпринята попытка повторения.
A. Если произошел сбой сети или служба не работает, и желаемое поведение заключается в повторной попытке запроса, как только сеть будет восстановлена или служба снова будет работать, потребуется выполнить RetryForever. Есть ли лучший способ сделать это? Эффективно будет много блокировок, верно?
С точки зрения кода, мои политики в настоящее время определены как:
const int maxRetryAttempts = 3;
const int exceptionsAllowedBeforeBreaking = 2;
const int pauseBetweenFailures = 2;
readonly Policy retryPolicy = Policy
.Handle<Exception>()
.RetryAsync(maxRetryAttempts, (exception, retryCount) => System.Diagnostics.Debug.WriteLine($"Retry {retryCount}"));
readonly Policy circuitBreakerPolicy = Policy
.Handle<Exception>()
.CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: exceptionsAllowedBeforeBreaking,
durationOfBreak: TimeSpan.FromSeconds(pauseBetweenFailures),
onBreak: (e, span) => System.Diagnostics.Debug.WriteLine("Breaking circuit for " + span.TotalMilliseconds + "ms due to " + e.Message),
onReset: () => System.Diagnostics.Debug.WriteLine("Trial call succeeded: circuit closing again."),
onHalfOpen: () => System.Diagnostics.Debug.WriteLine("Circuit break time elapsed. Circuit now half open: permitting a trial call."));
Мой код вызова сделан так:
var response = await retryPolicy.WrapAsync(circuitBreakerPolicy).ExecuteAsync(() => this.client.SendAsync<TData, JObject>(message, cancel, jsonSerializer));
Я заметил, что если я отключаю сеть по прошествии времени, необходимого для запуска всех повторных попыток на автоматическом выключателе, для CancellationToken устанавливается значение отмены, и в этот момент все запросы не выполняются. Если сеть восстанавливается до того, как это произойдет, то запросы повторяются.