У меня проблемы с настройкой CircuitBreaker Полли в сочетании с HttpClient
.
В частности, CircuitBreaker
и HttpClient
используются для ASP.NET Core Web API Controller по ссылкам ниже:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests
https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory
Ниже приведено то, что я хочу
политика повторных попыток: повторите 3 раза для каждого запросаесли есть временная ошибка.
политика прерывателя цепей: вступает в силу, если по всем запросам возникают временные ошибки пятерок.
Проблема
Хотя политика повтора работает правильно, политика выключателя не работает.
CarController по-прежнему получает запрос после 5 исключений из _httpClient.SendAsync () и не останавливается в течение 30 секунд (запросы обрабатываются контроллером немедленно).
HandledEventsAllowedBeforeBreaking: 5
DurationOfBreakInSeconds: 30
Я что-то здесь упускаю?
ConfigureServices
НастроитьПолитики повторных попыток Polly и автоматического выключателя, а также пользовательский HttpClient, HttpClientService
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
services.AddHttpClient<IHttpClientService, HttpClientService>()
.AddPolicyHandler((service, request) =>
HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(3,
retryCount => TimeSpan.FromSeconds(Math.Pow(2, retryCount)),
onRetry: (outcome, timespan, retryCount, context) =>
{
service.GetService<ILog>().Error("Delaying for {delay}ms, then making retry {retry}.",
timespan.TotalMilliseconds, retryCount);
}
)
)
)
.AddPolicyHandler((service, request) =>
HttpPolicyExtensions.HandleTransientHttpError()
//Further external requests are blocked for 30 seconds if five failed attempts occur sequentially.
//Circuit breaker policies are stateful.All calls through this client share the same circuit state.
.CircuitBreakerAsync(5,
TimeSpan.FromSeconds(30),
(result, timeSpan, context)=>
service.GetService<ILog>().Error("CircuitBreaker onBreak for {delay}ms", timeSpan.TotalMilliseconds),
context =>
service.GetService<ILog>().Error("CircuitBreaker onReset")));
}
CarController
IHttpClientService
указывается в политике Polly в ConfigureServices
.HttpClientService
использует HttpClient
.
Автоматический выключатель не работает: даже после пяти кратковременных ошибок (например, HttpRequestException
) из _httpClient.SendAsync()
CarController все еще может принимать запрос и не останавливается на 30секунд.
[ApiVersion("1")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class CarController : ControllerBase
{
private readonly ILog _logger;
private readonly IHttpClientService _httpClientService;
private readonly IOptions<Config> _config;
public CarController(ILog logger, IHttpClientService httpClientService, IOptions<Config> config)
{
_logger = logger;
_httpClientService = httpClientService;
_config = config;
}
[HttpPost]
public async Task<ActionResult> Post()
{
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string body = reader.ReadToEnd();
var statusCode = await _httpClientService.PostAsync(
"url",
new Dictionary<string, string>
{
{"headerID", "Id"}
},
body);
return StatusCode((int)statusCode);
}
}
}
HttpClientService
Кажется, что HttpClient не отслеживает состояние между запросами.
Автоматический выключатель не работает: даже после пяти переходных ошибокпроисходит (например, HttpRequestException
) из _httpClient.SendAsync()
, CarController все еще может получать запрос и не останавливается на 30 секунд.
public class HttpClientService
{
private readonly HttpClient _httpClient;
public HttpClientService(HttpClient client)
{
_httpClient = client;
}
public async Task<HttpStatusCode> PostAsync(string url, Dictionary<string, string> headers, string body)
{
using (var content = new StringContent(body, Encoding.UTF8, "application/json"))
{
foreach (var keyValue in headers)
{
content.Headers.Add(keyValue.Key, keyValue.Value);
}
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return response.StatusCode;
}
}
ASP.NET Core API 2.2
Обновление Обновлен метод расширения SetWaitAndRetryPolicy для использования IServiceProvider.