当我使用 IHttpClientFactory
在
每个请求中创建命名 HTTP 客户端时,HTTP 策略实例是否共享?
我正在使用
IHttpClientFactory
为每个请求创建一个命名的 http 客户端:
var workloadHttpClient = _httpClientFactory.CreateClient(product.ToString());
var response = await workloadHttpClient.SendAsync(message);
我正在定义命名客户端,以及每个此类客户端的 Polly 断路器:
services
.AddSingleton<IProductProvider, XProvider>()
.AddHttpClient(Products.X.ToString())
.AddPolicyHandler(BuildCircuitBreakerPolicy());
services
.AddSingleton<IProductProvider, YProvider>()
.AddHttpClient(Products.Y.ToString())
.AddPolicyHandler(BuildCircuitBreakerPolicy());
有了这个定义,断路器还能工作吗?
所有创建的客户端名为“X”是否会使用相同的断路器策略实例,从而真正计算所有 XProvider 执行中的失败?
每当您使用
HttpClientFactory
时,底层 HttpClientHandler
(以及关联的 DelegatingHandler
)都会默认缓存 2 分钟。
这意味着每当您创建具有相同名称的新
HttpClient
时,都会使用缓存的 HttpClientHandler
。如果 2 分钟到期,则处理程序将被标记为待清理,并且每当请求具有相同名称的新 HttpClient
时,都会创建新的 HttpClientHandler
。
在这里您可以通过一个简化的演示来向您展示 CB 确实在第二个 HttpClient 实例上崩溃了:
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Polly;
public class Program
{
public static async Task Main()
{
var collection = new ServiceCollection();
collection.AddHttpClient();
collection.AddHttpClient("A")
.AddPolicyHandler(GetCircuitBreakerPolicy());
var sp = collection.BuildServiceProvider();
var factory = sp.GetRequiredService<IHttpClientFactory>();
for(int i=0; i < 10; i++)
{
var client = factory.CreateClient("A");
var res = await client.GetAsync("http://httpstat.us/500");
Console.WriteLine(res.StatusCode);
}
}
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
=> Policy<HttpResponseMessage>
.HandleResult(res => res.StatusCode == HttpStatusCode.InternalServerError)
.CircuitBreakerAsync(1, TimeSpan.FromSeconds(2));
}
如果您想更改 2 分钟缓存时间,请检查 HandlerLifetime
HttpClientFactoryOptions
。