Как получить состояние автоматического выключателя Polly без выполнения запросов - PullRequest
0 голосов
/ 25 января 2020

Я понимаю, что мы можем использовать состояние схемы для извлечения текущего состояния в контексте. но есть ли способ, которым я могу получить состояние схемы вне контекста. например, здесь ниже. Если я хочу получить состояние схемы на контроллере, как мне это сделать? сейчас я установил переменную stati c в политике, но когда цепь разорвана, ее контекст недоступен для извлечения. Вот мои текущие настройки.

Запуск

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddHttpClient<IIntCall, IntCall>().WrapResilientPolicies();
}

Интерфейс

public interface IIntCall
    {
        Task<bool> DoSomething();
    }

Реализация:

public class IntCall : IIntCall
    {
private readonly HttpClient client;

public IntCall(HttpClient httpClient)
{
    this.client = httpClient;
}

public async Task<bool> DoSomething()
{
    var response = await client.GetAsync("http://www.onegoogle.com");
    var content = await response.Content.ReadAsStringAsync();
    return false;
}
}

Реализация Polly

public static class CBExtensions
    {
    public static void WrapResilientPolicies(this IHttpClientBuilder builder)
    {
        builder.AddPolicyHandler((service, request) =>
        GetRetryPolicy().WrapAsync(GetCircuitBreakerPolicy()));
    }

private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions.HandleTransientHttpError()
        .CircuitBreakerAsync(3, TimeSpan.FromSeconds(30), (result, retryAttempt) =>
        {
            Debug.WriteLine("circuit broken");
        },
        () =>
        {
            Debug.WriteLine("circuit closed");
        });
}

private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions.HandleTransientHttpError()
        .Or<Exception>(e => !(e is BrokenCircuitException))
      .WaitAndRetryAsync(3,
          retryAttempt => TimeSpan.FromMilliseconds(500),
          onRetry: (context, attempt) =>
          {
              Debug.WriteLine("error");
          }
      );
}

}

1 Ответ

0 голосов
/ 25 января 2020

Свойство CircuitState доступно на интерфейсе ICircuitBreaker, выполняемом экземпляром политики: (подробнее в Polly readme и wiki )

CircuitState state = breaker.CircuitState;

/*
CircuitState.Closed
CircuitState.Open
CircuitState.HalfOpen
CircuitState.Isolated
*/

где breaker - это экземпляр политики, ie политика, первоначально возвращенная вашим методом GetCircuitBreakerPolicy().


Вы можете передать эту политику выключателя в контроллер через DI. Во время запуска вы можете сделать что-то вроде:

var breaker = GetCircuitBreakerPolicy();
services.AddSingleton<ICircuitBreakerPolicy<HttpResponseMessage>>(breaker as ICircuitBreakerPolicy<HttpResponseMessage>);

Конечно, вам нужно будет использовать этот тот же единственный экземпляр breaker при вызове .AddPolicyHandler(...), а не создавать новый / другой.

builder.AddPolicyHandler(GetRetryPolicy().WrapAsync(breaker));

Затем контроллер может получить копию экземпляра выключателя путем инжекции в конструктор:

public class MyController
{
    public MyController(ICircuitBreakerPolicy<HttpResponseMessage> breaker, /* etc */)
    {
    }
}

Передача выключателя в контроллер путем регистрации ICircuitBreakerPolicy<HttpResponseMessage> на Контейнер DI (как показано выше) хорошо работает, если приложение использует только один экземпляр выключателя.

Если у вас есть несколько экземпляров политики выключателя, которые должны быть непосредственно доступны в других местах приложения, например, контроллерами, сохраните их в PolicyRegistry и передайте IReadOnlyPolicyRegistry<string> к контроллеру по DI. Существуют .AddPolicyHandlerFromRegistry() перегрузок для настройки HttpClient с политиками из PolicyRegistry.

...