【问题标题】:Circuit breaker based on the condition in request基于请求条件的断路器
【发布时间】:2021-08-28 13:39:24
【问题描述】:

我需要设置断路策略,以便它仅对某些特定请求进行断路。

我有一种网关 A 调用 API B,后者又调用 CD。我正在 A 中设置断路器策略。到达 A 的初始请求有一个参数,稍后用于决定是调用 C 还是 D,比如说 @ 987654323@。我想以这样的方式配置断路器,该电路可以为 CD 单独打开。我的意思是,如果 D 失败,使用 usageParam=D 的调用应该会立即失败,但 usageParam=C 应该仍然可以正常运行,反之亦然。

【问题讨论】:

    标签: asp.net-core asp.net-core-3.1 polly circuit-breaker


    【解决方案1】:

    简单地说,断路器只能有一个状态。其中之一:ClosedOpenHalf-Open

    您应该将 CB 视为代理。如果下游系统被认为是健康的,它允许每个请求通过它。如果 CB 检测到瞬时故障(通过检查响应(如果有)),那么它将通过拒绝所有请求来缩短执行。


    因此,如果您想区分 CD 下游系统的健康状况,那么您需要两个 CB(每个一个)。这允许您分别允许或拒绝针对不同子系统的传出请求。

    选项 A

    您可以将两个 CB 放置在服务 A 中。在这里你可以注册两个命名的HttpClients,它们用不同的断路器装饰:

    private IAsyncPolicy<HttpResponseMessage> GetCBPolicy()
        => HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(2, TimeSpan.FromSeconds(1));
    
    ...
    services.AddHttpClient("CService", c => { 
                c.BaseAddress = new Uri(BServiceBasePath);
                ... 
             })
            .AddPolicyHandler(GetCBPolicy());
    services.AddHttpClient("DService" c => { 
                c.BaseAddress = new Uri(BServiceBasePath);
                ... 
             })
            .AddPolicyHandler(GetCBPolicy());
    

    但是您必须手动进行路由,如下所示:

    if(!Context.Request.Query.TryGetValue("usageParam", out var usage))
       return;
    
    HttpClient client = usage switch
    {
        "C" => _clientFactory.CreateClient("CService"),
        "D" => _clientFactory.CreateClient("DService"),
        _ => throw new NotSupportedException("..."),
    };
    

    选项 B

    您可以将两个 CB 放置在服务 B 中。在这里您可以注册两个类型化的 HttpClient,它们用不同的断路器装饰:

    private IAsyncPolicy<HttpResponseMessage> GetCBPolicy()
        => HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(2, TimeSpan.FromSeconds(1));
    
    ...
    services.AddHttpClient<ICService, CService>()
            .AddPolicyHandler(GetCBPolicy());
    services.AddHttpClient<IDService, DService>()
            .AddPolicyHandler(GetCBPolicy());    
    

    【讨论】:

    • 是的,我想过有 2 个不同的 httpClients,但看起来不是一个优雅的解决方案。我希望有一些基于 AddPolicyHandler 中的 HttpRequestMessage 参数的条件:public static IHttpClientBuilder AddPolicyHandler(this IHttpClientBuilder builder, Func&lt;IServiceProvider, HttpRequestMessage, IAsyncPolicy&lt;HttpResponseMessage&gt;&gt; policySelector);
    • @gator88 根本问题与 HttpClient 无关。您可以对任何事物使用断路器。因为单个 CB 只能维护一个状态,所以您需要两个单独的实例。
    • @gator88 您需要进一步澄清吗?
    • 不,我明白你的意思,我同意。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    相关资源
    最近更新 更多