Microsoft.Extensions.Http.Resilience: использование параметров AddStandardResilienceHandler с SlidingWindowRateLimiter

Используя Microsoft.Extensions.Http.Resilience, можно использовать точные параметры RateLimiter, например SlidingWindowRateLimiter, с AddStandardResilienceHandler. Альтернативно применить значения по умолчанию из AddStandardResilienceHandler к пользовательскому определению AddResilienceHandler для всего остального, кроме части RateLimiter?

В идеале я хотел бы использовать лучшие практические настройки по умолчанию, встроенные в библиотеку устойчивости, но переопределить часть RateLimiter для конкретных ограничений, налагаемых API.

Например, я хотел бы объединить:

builder.AddStandardResilienceHandler(static options => {
    // Either apply RateLimiter options from below
});

с RateLimiter опциями, такими как:

services.AddHttpClient(Constants.StarshipitHttpClient)
    .AddResilienceHandler(Constants.StarshipitHttpClient, static builder =>
    {
        builder.AddRateLimiter(new SlidingWindowRateLimiter(
            new SlidingWindowRateLimiterOptions
            {
                PermitLimit = 2,
                Window = TimeSpan.FromSeconds(1),
                QueueLimit = int.MaxValue,
            }
        ));

        // Or add other default resiliency options from AddStandardResilienceHandler above  
    });

Кто-нибудь знает, как этого добиться?

Вы проверили эту ТАК-тему: stackoverflow.com/questions/77662135 ?

Peter Csala 02.07.2024 15:54

Спасибо, Питер, хотя это SO было полезно прочитать, оно касается немного другого сценария.

Gavin 04.07.2024 01:13

Я обновил свой ответ, чтобы внести ясность.

Peter Csala 04.07.2024 12:01
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
133
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

В идеале это должно быть так просто:

.AddStandardRResilienceHandler(options => 
{ 
   options.RateLimiter = yourRateLimiterOptions; 
})

Но, насколько я вижу, сообщенная проблема с изменением значений по умолчанию еще не устранена на момент написания этого ответа.


Для имени HttpClient это работает следующим образом.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http.Resilience;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;

var builder = Host.CreateApplicationBuilder(args);
builder.Services
    .AddHttpClient("test")
    .AddStandardResilienceHandler(options =>
    {
        options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(11);
    });

var serviceProvider = builder.Services.BuildServiceProvider();
var monitor = serviceProvider.GetRequiredService<IOptionsMonitor<HttpStandardResilienceOptions>>();
var options = monitor.Get("test-standard");
Console.WriteLine(options.AttemptTimeout.Timeout);

using var host = builder.Build();
  • Он регистрирует именованный HttpClient с именем test.
  • Он добавляет к нему стандартный обработчик устойчивости.
  • Он переопределяет AttemptTimeout с 10 секунд (по умолчанию) на 11.
  • Он получает IOptionsMonitor из DI.
  • Он извлекает тот HttpStandardResilienceOptions, который назван в test-standard

Печатный результат составит 11 секунд, см. соответствующую скрипт dotnet

То же самое должно работать и со свойством RateLimiter.

Будет ли этот метод применять все значения по умолчанию, используемые AddStandardResilienceHandler, и просто переопределять значения по умолчанию RateLimiter с помощью моих переопределений? У меня сложилось впечатление, что это не так, и мне придется вручную добавить все остальные параметры, чтобы получить лучшие практики, которые AddStandardResilienceHandler предоставляет по умолчанию.

Gavin 03.07.2024 22:50

@Gavin Вы можете переопределить параметры (более или менее) независимо. Если вы хотите переопределить AttemptTimeout, как в примере, остальные параметры останутся нетронутыми. Я сказал более или менее независимо, потому что, например, вы не можете установить AttemptTimeout на 20 секунд, потому что он выдаст OptionsValidationException из-за несовпадения с параметрами автоматического выключателя.

Peter Csala 04.07.2024 11:59

Спасибо, Питер, очень ценю. Я думаю, вы правы, и моя трудность заключается в том, чтобы понять, как установить RateLimiterStrategyOptions.RateLimiter` в SlidingWindowRateLimiter. Сейчас я экспериментирую, чтобы попытаться выяснить это.

Gavin 04.07.2024 23:35

Суть моей проблемы заключалась в том, что я не понимал, как переопределить опцию RateLimiter для AddStandardResilienceHandler.

После ответов Питера Чалы я почувствовал, что мои первоначальные неудачные попытки, вероятно, были ошибкой пользователя, поэтому я исследовал и экспериментировал дальше, обнаружив необходимость использовать AcquireAsync для выполнения необходимого переопределения:

var rateLimiter = new FixedWindowRateLimiter(
    new FixedWindowRateLimiterOptions
    {
        PermitLimit = 2,
        Window = TimeSpan.FromSeconds(1),
        QueueLimit = int.MaxValue,
    }
);

services.AddHttpClient(name)
    .AddStandardResilienceHandler(options =>
    {
        options.RateLimiter = new HttpRateLimiterStrategyOptions
        {
            Name = $"{name}-{nameof(HttpStandardResilienceOptions.RateLimiter)}",
            RateLimiter = args => rateLimiter.AcquireAsync(cancellationToken: args.Context.CancellationToken)
        };
    });

Да, именно так вам следует указать собственный ограничитель скорости (как мы задокументировали здесь).

Peter Csala 05.07.2024 09:58

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