Теперь fallbackForCircuitBreaker вызывается только в случае сбоя всех повторных попыток и если последняя повторная попытка завершится неудачей с BrokenCircuitException.Какие изменения необходимо внести для того, чтобы fallbackForCircuitBreaker вызывался каждый раз, когда повторная попытка выполняется на разорванной цепи?
См. Документацию PolicyWrap , особенно диаграммы иописание операции .Политики в PolicyWrap действуют как последовательность вложенного промежуточного программного обеспечения вокруг вызова:
- самая внешняя (самая левая в порядке чтения) выполняет следующую внутреннюю часть, которая выполняет следующую внутреннюю часть и т. Д .;пока внутренняя политика не выполнит пользовательский делегат;
- выброшенное исключение пузырится назад (пока не будет обработано) через слои
Таким образом, чтобы (эквивалентный) fallbackForCircuitBreaker
вызывалсяпри попытке переместите его в политику повторных попыток.
Текущий fallbackForCircuitBreaker
, однако, заменяет выброшенное исключение возвращаемым значением false
, в то время как звучит так, как будто вы ищете резервный вариант на«войти, затем сделать следующую попытку».Техника для этого заключается в использовании отката в качестве log, а затем повторного выброса , чтобы ваша политика повторных попыток все еще могла реагировать на (повторно выброшенное) исключение.Итак:
var sharedBulkhead = /* as before */;
var retryPolicy = /* as before */;
var fallbackForCircuitBreaker = /* as before */;
var logCircuitBreakerBrokenPerTry = Policy<bool>
.Handle<BrokenCircuitException>()
.FallbackAsync(
fallbackValue: false,
onFallbackAsync: (outcome, context) =>
{
Log.Error($"Operation attempted on broken circuit => Policy Wrap: {context.PolicyWrapKey}, Policy: {context.PolicyKey}, Endpoint: {context.OperationKey}");
throw outcome.Exception;
}
);
var fallbackForAnyException = /* as before */;
var resilienceStrategy = Policy.WrapAsync(retryPolicy, logCircuitBreakerBrokenPerTry, circuitBreaker, sharedBulkhead);
var policyWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(resilienceStrategy));
Могу ли я изменить политику повторных попыток, чтобы обрабатывать также отклонение больших объемов?
Документация Переборка Polly заявляет, что политики выбрасывает BulkheadRejectedException
, поэтому:
var retryPolicy = Policy
.Handle<HttpRequestException>()
.Or<BrokenCircuitException>()
.Or<BulkheadRejectedException>()
/* etc */
Что в идеале должно быть сделано на onBulkheadRejectedAsync?
Вы можете войти.Вообще говоря, вы можете сбросить лишнюю нагрузку или использовать отклонение переборки в качестве триггера для горизонтального масштабирования для увеличения пропускной способности.Документация Polly обеспечивает более подробное обсуждение здесь и здесь .
Кроме того, я использую sharedBulkHead, который является полем экземпляра в службе и инициализируется вконструкторЭто хорошая практика?
Это зависит.Время жизни экземпляра политики перегородки должно быть долгоживущим по управляемым вызовам , а не по вызову, чтобы состояние экземпляра политики переборки определяло число одновременных вызовов.
- Если служба существует как долгоживущий одноэлементный, хранение политики переборки в поле экземпляра будет целесообразным, так как экземпляр политики переборки также будет долгоживущим.
- Если экземпляры класса обслуживания создаются как переходные / на запрос в контейнере DI, вам необходимо убедиться, что экземпляр политики переборки все еще является долгоживущим и используется совместно для одновременных запросов (например, делая его
static
), не по запросу. - Если экземпляры переборки настроены на HttpClient с помощью HttpClientFactory, следуйте указаниям по определения политики с сохранением состояния с помощью HttpClientFactory в документации Polly и HttpClientFactory .