Используйте определенный тайм-аут, связанный с повторной политикой

Я создаю политику повтора следующим образом:

var policy = Policy.Handle<Exception>().WaitAndRetryAsync...

Как настроить тайм-аут для повторной политики, описанной выше? Policy.TimeoutAsync возвращает TimeoutPolicy, поэтому я не могу сделать что-то вроде

var policy = Policy.TimeoutAsync(30).Handle<Exception>().WaitAndRetryAsync....

Стало ли тайм-аут обычным параметром для всех моих политик повтора?


person Johan    schedule 04.04.2017    source источник


Ответы (1)


Чтобы объединить политики, вы создаете каждую политику отдельно, а затем объединяете их с помощью PolicyWrap.

Чтобы создать общий тайм-аут, который применяется ко всем повторным попыткам в целом (то есть ко всей операции):

var overallTimeoutPolicy = Policy.TimeoutAsync(60); 
var waitAndRetryPolicy = Policy
    .Handle<WhateverException>()
    .WaitAndRetryAsync(/* your wait-and-retry specification*/);
var combinedPolicy = overallTimeoutPolicy.WrapAsync(waitAndRetryPolicy);

await combinedPolicy.ExecuteAsync(cancellationToken => ...)

Чтобы установить тайм-аут для каждой конкретной попытки, оберните политики повтора и тайм-аута в другом порядке:

var timeoutPerTry = Policy.TimeoutAsync(10); 
var waitAndRetryPolicy = Policy
    .Handle<WhateverException>()
    .WaitAndRetryAsync(/* your wait-and-retry specification*/);
var combinedPolicy = waitAndRetryPolicy.WrapAsync(timeoutPerTry);

await combinedPolicy.ExecuteAsync(cancellationToken => ...);

Или даже используйте оба вида тайм-аута (на попытку, на общую операцию):

var overallTimeout = Policy.TimeoutAsync(60); 
var timeoutPerTry = Policy.TimeoutAsync(10); 
var waitAndRetryPolicy = Policy
    .Handle<WhateverException>()
    .WaitAndRetryAsync(/* your wait-and-retry specification*/);

var combinedPolicy = Policy
    .WrapAsync(overallTimeout, waitAndRetryPolicy, timeoutPerTry); // demonstrates alternative PolicyWrap syntax

await combinedPolicy.ExecuteAsync(cancellationToken => ...);

PolicyWrap wiki предоставляет полную информацию о синтаксисе, а совет о влиянии различных порядков при объединении политик в оболочке.


Отвечать:

Стало ли тайм-аут обычным параметром для всех моих политик повтора?

Политики применяются везде, где вы их используете (независимо от того, используются ли они по отдельности или как часть PolicyWrap).

Вы можете потокобезопасно использовать любой TimeoutPolicy экземпляр вы настроили на нескольких сайтах вызова. Итак, чтобы применить этот тайм-аут как общий параметр для всех ваших политик повтора, просто включите тот же экземпляр TimeoutPolicy в PolicyWrap для каждого сайта вызова. При желании единственный экземпляр TimeoutPolicy можно безопасно обернуть разными экземплярами политики повтора.

Если и ваша спецификация ожидания и повтора, и спецификация тайм-аута являются общими для всех сайтов вызова, просто создайте один PolicyWrap экземпляр, охватывающий оба (согласно приведенным выше примерам кода), и повторно используйте этот PolicyWrap экземпляр везде. Опять же - потокобезопасный.

person mountain traveller    schedule 04.04.2017
comment
Спасибо за подробный ответ - очень признательны! - person Johan; 04.04.2017
comment
Привет, Аджиан, на основании твоего комментария, разве это не должно работать? pastebin.com/E6RaTWCn Политика тайм-аута в одну секунду для двухсекундной задачи. Я ожидаю увидеть в журнале ошибку: timeoutexception. Кроме того, я заметил, что вы не советуете ExecuteAndCapture использовать обертки политик. Что произойдет, если последняя попытка вызовет исключение, если я переключусь на Execute? - person Johan; 05.04.2017
comment
Привет. См. документ о тайм-ауте Полли. TimeoutStrategy.Optimistic (по умолчанию) работает с помощью совместной отмены через CancellationToken. TimeoutStrategy.Pessimistic нет: он «уходит» даже от неотменяемого исполнения. Thread.Sleep(...) в вашем pastebin нельзя отменить. Измените Sleep () на Task.Delay(...) и используйте перегрузку ExecuteAsync(), взяв CancellationToken, в моих примерах: ExecuteAsync(ct => Task.Delay(TimeSpan.FromSeconds(2), ct), someCancellationToken). - person mountain traveller; 05.04.2017
comment
ИЛИ, придерживайтесь Thread.Sleep(...) и докажите себе, что TimeoutPolicy withTimeoutStrategy.Pessimistic успешно истекает по времени, то есть заставляет вызывающего абонента «уйти» от ожидания неотменяемого Thread.Sleep(...). Отменяемые задачи и TimeoutStrategy.Optimistic предпочтительны и более удобны для ресурсов - см. Вики. - person mountain traveller; 05.04.2017
comment
Re Что произойдет, если последняя попытка вызовет исключение, если я переключусь на «Выполнить»? - ›Политика позволит этому исключению распространяться. Предположительно вы хотите перехватить это исключение, и ваш код должен решить, как действовать дальше. Возникающее повторно исключение указывает на то, что операция не завершилась успешно в рамках настроенных попыток повторения. - person mountain traveller; 05.04.2017
comment
Пример, показывающий TimeoutStrategy.Pessimistic: dotnetfiddle.net/xREDBf. (Я уменьшил задержки и количество попыток, только чтобы уместиться в границах выполнения dotnetfiddle) - person mountain traveller; 05.04.2017
comment
Пример, показывающий TimeoutStrategy.Optimistic: dotnetfiddle.net/pnMdSQ. Множество других примеров можно найти в тестах тоже. - person mountain traveller; 05.04.2017
comment
Последующий вопрос, если у вас есть время: в моем реальном коде я использую синхронный вызов веб-службы вместо тайм-аута. Поскольку это синхронная, то есть не ожидаемая задача, я полагаю, уместна пессимистическая стратегия тайм-аута? - person Johan; 06.04.2017
comment
Все равно проверьте, есть ли тайм-аут. В противном случае пессимистичный тайм-аут позволяет вызывающему абоненту уйти после тайм-аута. Но обратите внимание, что это именно то, что он делает. Вызывающий может уйти, но это не отменяет тайм-аут вызова волшебным образом. Все нюансы обсуждаются в wiki и отличный статья Стивена Туба, на которую я указываю. HTH - person mountain traveller; 06.04.2017
comment
Вам нужно добавить .Or<TimeoutRejectedException>() в обработчик, если вы хотите повторить попытку истечения времени ожидания. - person carlin.scott; 20.10.2020
comment
github.com/Polly-Contrib/Polly.Contrib.WaitAndRetry var retryWithBackoff = Политика .Handle ‹FooException› () .WaitAndRetryAsync (Backoff.ExponentialBackoff (TimeSpan.FromSeconds (1), retryCount: 5)); var timeout = Policy.Timeout (TimeSpan.FromSeconds (45)); var retryWithBackoffAndO GeneralTimeout = timeout.Wrap (retryWithBackoff); Когда общее время, затрачиваемое на выполнение попыток и ожидание между ними, превышает 45 секунд, будет вызвана TimeoutPolicy, и текущая попытка и последующие попытки будут отменены. - person Ayushmati; 27.01.2021