Используя 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
});
Кто-нибудь знает, как этого добиться?
Спасибо, Питер, хотя это SO было полезно прочитать, оно касается немного другого сценария.
Я обновил свой ответ, чтобы внести ясность.
В идеале это должно быть так просто:
.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();
test
.AttemptTimeout
с 10 секунд (по умолчанию) на 11.IOptionsMonitor
из DI.HttpStandardResilienceOptions
, который назван в test-standard
$"{httpClientName}-{pipelineIdentifier}"
pipelineIdentifier
- это стандартПечатный результат составит 11 секунд, см. соответствующую скрипт dotnet
То же самое должно работать и со свойством RateLimiter
.
Будет ли этот метод применять все значения по умолчанию, используемые AddStandardResilienceHandler
, и просто переопределять значения по умолчанию RateLimiter
с помощью моих переопределений? У меня сложилось впечатление, что это не так, и мне придется вручную добавить все остальные параметры, чтобы получить лучшие практики, которые AddStandardResilienceHandler
предоставляет по умолчанию.
@Gavin Вы можете переопределить параметры (более или менее) независимо. Если вы хотите переопределить AttemptTimeout
, как в примере, остальные параметры останутся нетронутыми. Я сказал более или менее независимо, потому что, например, вы не можете установить AttemptTimeout
на 20 секунд, потому что он выдаст OptionsValidationException
из-за несовпадения с параметрами автоматического выключателя.
Спасибо, Питер, очень ценю. Я думаю, вы правы, и моя трудность заключается в том, чтобы понять, как установить RateLimiterStrategyOptions
.RateLimiter` в SlidingWindowRateLimiter
. Сейчас я экспериментирую, чтобы попытаться выяснить это.
Суть моей проблемы заключалась в том, что я не понимал, как переопределить опцию 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)
};
});
Да, именно так вам следует указать собственный ограничитель скорости (как мы задокументировали здесь).
Вы проверили эту ТАК-тему: stackoverflow.com/questions/77662135 ?