Использование AddStandardResilienceHandler и AddStandardHedgingHandler в .NET 8 для обеспечения устойчивости

У меня есть API .NET 8, использующий Polly для обеспечения устойчивости к внешним службам, таким как Azure SQL и Microsoft Graph. Моя текущая реализация использует пользовательские политики повтора и автоматического выключателя, как показано ниже:

PollyExtensions.cs:

public static class PollyExtensions
{
    public static AsyncRetryPolicy CreateRetryPolicy(this ILogger logger, string infraService)
    {
        var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5);

        return Policy
            .Handle<SqlException>()
            .Or<Exception>()
            .Or<TimeoutException>()
            .WaitAndRetryAsync(delay,
                onRetry: (exception, timespan, retryAttempt, context) =>
                {
                    logger.LogWarning(exception, "Error talking to {infraService}, Error: {Message}, will retry after {timeSpan}. Retry attempt {retryCount} ",
                        infraService, exception.Message, timespan, retryAttempt);
                });
    }

    public static AsyncCircuitBreakerPolicy CreateCircuitBreakerPolicy()
    {
        return Policy
            .Handle<Exception>()
            .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 5,
                durationOfBreak: TimeSpan.FromMinutes(1)
            );
    }
}

Изучая новые функции .NET 8, я наткнулся на AddStandardResilienceHandler и AddStandardHedgingHandler для реализации устойчивости.

Использованная литература :

https://devblogs.microsoft.com/dotnet/building-resilient-cloud-services-with-dotnet-8/

https://juliocasal.com/blog/Building-Microservices-With-Dotnet-8

Может ли кто-нибудь предоставить примеры кода, демонстрирующие, как использовать AddStandardResilienceHandler и AddStandardHedgingHandler в контексте моего класса GraphSvcClient для вызовов внешних зависимостей?

Есть ли какие-либо особые соображения при использовании этих новых функций по сравнению с настраиваемыми политиками?

ГрафСвкклиент.cs

public sealed class GraphSvcClient(ICacheProvider cacheProvider,
    IAzureAuthTokenService azureAuthTokenService,    
    ILogger<GraphSvcClient> logger) : IGraphSvcClient
{
    private readonly ICacheProvider _cacheProvider = cacheProvider.IsNotNull();
    private readonly IAzureAuthTokenService _azureAuthTokenService = azureAuthTokenService.IsNotNull();
    private readonly ILogger<GraphSvcClient> _logger = logger.IsNotNull();
    
    /// <summary>
    /// Get Microsoft Graph graphClient
    /// </summary>
    /// <returns></returns>
    public async Task<GraphServiceClient> GetGraphServiceClientAsync()
    {
        var accessToken = await GetAccessTokenAsync();

        var retryPolicy = _logger.CreateRetryPolicy(infraService: "MicrosoftGraph");
        var circuitBreakerPolicy = PollyExtensions.CreateCircuitBreakerPolicy();

        var combinedPolicy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);

        var graphServiceClient = await combinedPolicy.ExecuteAsync(async () =>
        {
            var client = new GraphServiceClient(new DelegateAuthenticationProvider(async (req) =>
            {
                req.Headers.Authorization = new AuthenticationHeaderValue(JwtBearerDefaults.AuthenticationScheme, accessToken);
                await Task.CompletedTask;
            }));
            return client;
        });

        return graphServiceClient;
    }
}

Я рассматриваю возможность обновления Polly и связанных с ним пакетов nuget до последних совместимых версий, чтобы использовать новейшие функции .NET 8.

Список пакетов Nuget, использованных в проекте:

<PackageReference Include = "Polly" Version = "7.2.4" />
<PackageReference Include = "Polly.Contrib.WaitAndRetry" Version = "1.1.1" />
<PackageReference Include = "Microsoft.Extensions.Http.Polly" Version = "8.0.0" />
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
790
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я вижу некоторые недоразумения, поэтому позвольте мне попытаться прояснить ситуацию.

Microsoft.Extensions.Http.XYZ пакеты

Polly по своей конструкции не зависит от предметной области. Другими словами, его можно использовать для обработки временных ошибок, связанных с HTTP-вызовами, а также для математических расчетов. Политики (в случае V7) достаточно универсальны, чтобы их можно было использовать в самых разных случаях.

Одним из распространенных вариантов использования является сетевое общение на основе HttpClient. Из-за его популярности сначала сообщество Polly, а затем Microsoft выпустило несколько вспомогательных структур и методов, упрощающих интеграцию и использование Polly с помощью HttpClient.

Для API V7 Microsoft выпустила Microsoft.Extensions.Http.Polly, который помогает вам оборудовать все HttpClient вызовы произвольными политиками устойчивости с помощью метода расширения AddPolicyHandler.

Для API V8 Microsoft выпустила пакет Microsoft.Extensions.Http.Resilience, который помогает вам украшать все вызовы HttpClient либо предопределенными конвейерами устойчивости, либо любыми произвольными стратегиями устойчивости. Первое можно сделать с помощью методов расширения AddStandardResilienceHandler, AddStandardHedgingHandler, а второе — с помощью AddResilienceHandler.

Перенос вашего кода на V8

Повторить попытку

Вашу стратегию повторных попыток можно легко перенести в V8. К счастью, алгоритм экспоненциальной отсрочки поддерживается изначально. Это означает, что вам не нужно полагаться на какую-то зависимость от вклада.

return new ResiliencePipelineBuilder().AddRetry(new()
{
    ShouldHandle = new PredicateBuilder()
        .Handle<SqlException>()
        .Handle<TimeoutException>()
        .Handle<Exception>(),
    BackoffType = DelayBackoffType.Exponential,
    UseJitter = true,
    MaxRetryAttempts = 5,
    Delay = TimeSpan.FromSeconds(1),
    OnRetry = args =>
    {
        logger...
        return default;
    }
})
.Build();

Обратите внимание: если у вас есть предложение Handle<Exception>/Or<Exception> в случае V7 или предложение Handle<Exception> в случае V8, то все остальные предложения Handle/Or не обязательны.

Автоматический выключатель

В настоящее время API V8 не поддерживает эту стандартную/классическую модель автоматического выключателя , основанную на последовательном подсчете отказов. V8 поддерживает модель, основанную на выборке, которая аналогична усовершенствованному автоматическому выключателю V7.

Короче говоря, вы не можете перенести это как есть. Вам необходимо использовать подход, основанный на выборке , если вы хотите использовать API V8.

Политика.Обертка

Объединение нескольких политик в API V7 можно выполнить несколькими способами, но предложенным решением было использование Policy.Wrap{Async}.

В случае с V8 вам нужно использовать ResiliencePipelineBuilder, чтобы добавить несколько стратегий в свой конвейер.

ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
    .AddRetry(new()
    {
        ...
    })
    .AddCircuitBreaker(new()
    {
        ...
    })
    .Build();

В случае V8 порядок регистрации также важен, как и в случае с V7.

Ваш графический сервис

Ваши исходные политики не были связаны с HTTP. Ваши стратегии V8 также не обязательно должны быть связаны с HTTP. Это означает, что использование AddStandardResilienceHandler или AddStandardHedgingHandler не требуется.

Основываясь на общем фрагменте кода, я не могу сказать, является ли GraphServiceClient типизированным HttpClient или нет (но я предполагаю, что это не так). Итак, вам просто нужно перенести политики повторных попыток и прерывания цепи в V8, чтобы иметь возможность использовать все преимущества V8.

Большое спасибо @Peter Csala за ваш ответ. Я очень ценю детали, представленные здесь, которые мне очень помогут.

santosh kumar patro 25.04.2024 09:14

Другие вопросы по теме