.net core 如何在不执行请求的情况下获取polly断路器状态

.net core 如何在不执行请求的情况下获取polly断路器状态,.net-core,dotnet-httpclient,polly,circuit-breaker,.net Core,Dotnet Httpclient,Polly,Circuit Breaker,我知道我们可以使用电路状态来获取上下文中的当前状态。但是有没有一种方法可以在上下文之外获取电路状态。例如,如果我想得到控制器的电路状态,我该怎么做?现在我在策略中设置了一个静态变量,但是当电路断开时,它的上下文无法获取。这是我目前的设置 启动 public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.

我知道我们可以使用电路状态来获取上下文中的当前状态。但是有没有一种方法可以在上下文之外获取电路状态。例如,如果我想得到控制器的电路状态,我该怎么做?现在我在策略中设置了一个静态变量,但是当电路断开时,它的上下文无法获取。这是我目前的设置

启动

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddHttpClient<IIntCall, IntCall>().WrapResilientPolicies();
}
public void配置服务(IServiceCollection服务)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHttpClient().wrapResilientPolicys();
}
接口

public interface IIntCall
    {
        Task<bool> DoSomething();
    }
公共接口IIntCall
{
任务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;
}
}
公共类IntCall:IIntCall
{
私有只读HttpClient;
公共IntCall(HttpClient HttpClient)
{
this.client=httpClient;
}
公共异步任务DoSomething()
{
var response=wait client.GetAsync(“http://www.onegoogle.com");
var content=await response.content.ReadAsStringAsync();
返回false;
}
}
波利实现

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");
          }
      );
}
公共静态类扩展
{
公共静态无效WrapResilientPolicys(此IHttpClientBuilder生成器)
{
builder.AddPolicyHandler((服务、请求)=>
GetRetryPolicy().WrapAsync(GetCircuitBreakerPolicy());
}
私有静态IAsyncPolicy GetCircuitBreakerPolicy()
{
返回HttpPolicyExtensions.HandletTransientHttpError()
.CircuitBreakerAsync(3,TimeSpan.FromSeconds(30),(结果,重试尝试)=>
{
调试。写入线(“电路断路”);
},
() =>
{
调试写入线(“电路闭合”);
});
}
私有静态IAsyncPolicy GetRetryPolicy()
{
返回HttpPolicyExtensions.HandletTransientHttpError()
.或(e=>!(e是BrokenCircuiteException))
WaitandertryAsync先生(3,
RetryTest=>TimeSpan.From毫秒(500),
onRetry:(上下文,尝试)=>
{
Debug.WriteLine(“错误”);
}
);
}

}

策略实例实现的
ICIRcircuitBreaker
接口上提供了
CircuitState
属性:(更多信息请参见Polly和)

其中
breaker
是策略实例,即最初由
GetCircuitBreakerPolicy()
方法返回的策略


您可以通过DI将断路器策略传递给控制器。在启动期间,您可以执行以下操作:

var breaker = GetCircuitBreakerPolicy();
services.AddSingleton<ICircuitBreakerPolicy<HttpResponseMessage>>(breaker as ICircuitBreakerPolicy<HttpResponseMessage>);
然后,控制器可以通过构造函数注入接收断路器实例的副本:

public class MyController
{
    public MyController(ICircuitBreakerPolicy<HttpResponseMessage> breaker, /* etc */)
    {
    }
}
公共类MyController
{
公共MyController(ICIRucuitBreakerPolicy breaker,/*等*/)
{
}
}

如果应用程序仅使用单个断路器实例,则通过在DI容器(如上所示)上注册
ICircuitBreakerPolicy
将断路器传递给控制器效果良好

如果您有多个断路器策略实例,这些实例需要在应用程序的其他位置直接访问(例如通过控制器),请将它们存储在中,并通过DI将
IReadOnlyPolicyRegistry
传递给控制器。有用于从
PolicyRegistry
配置策略的
HttpClient

builder.AddPolicyHandler(GetRetryPolicy().WrapAsync(breaker));
public class MyController
{
    public MyController(ICircuitBreakerPolicy<HttpResponseMessage> breaker, /* etc */)
    {
    }
}