HttpClientFactory未应用配置:如何让创建的客户端生效默认配置?
问题描述
我配置了以下代码:
services.AddHttpClient<IMyManagerFactory, MyManagerFactory>(c => { c.Timeout = TimeSpan.FromMinutes(5); }) .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync([ TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) ]));
internal class MyManagerFactory : IMyManagerFactory { private readonly IHttpClientFactory _httpClientFactory; private readonly IMySettings _settings; // ... 构造函数省略 public IMyManager Get(string key) { var client = _httpClientFactory.CreateClient(); var queryString = new Dictionary<string, string?> { {"tenantId", settings.TenantId }, {"locationId", settings.LocationId } }; var uri = QueryHelpers.AddQueryString(settings.BaseUrl, queryString); client.BaseAddress = new Uri(uri); client.DefaultRequestHeaders.Add("X-Token", settings.ApiToken); return new KiyohCustomerReviewManager(client); } }
客户端可以正常工作,但DI中配置的超时和错误策略并未生效。如何让调用CreateClient()时,客户端工厂应用我的默认配置?
补充结构:
public class BgJob { private IMyManagerFactory _fac; // ... 构造函数省略 public Run() { foreach(var d in domains) { var manager = _fac.Get(d.key); var data = manager.Get(...); } } }
MyManagerFactory负责提供带有正确BaseAddress和认证信息的客户端/管理器。
解决方案
问题根源:你调用IHttpClientFactory.CreateClient()无参方法时,获取的是默认未配置的HttpClient实例;而AddHttpClient<IMyManagerFactory, MyManagerFactory>的作用是给MyManagerFactory的构造函数注入一个预配置的HttpClient,并非给IHttpClientFactory设置全局默认配置,因此之前的策略和超时不会生效。
下面提供两种可行方案:
方案一:直接注入预配置的HttpClient
修改MyManagerFactory的构造函数,注入DI中配置好的HttpClient,再基于它创建自定义实例(继承原有配置):
internal class MyManagerFactory : IMyManagerFactory { private readonly HttpClient _configuredHttpClient; private readonly IMySettings _settings; // 注入预配置的HttpClient public MyManagerFactory(HttpClient configuredHttpClient, IMySettings settings) { _configuredHttpClient = configuredHttpClient; _settings = settings; } public IMyManager Get(string key) { // 克隆HttpClient实例,避免修改原实例影响其他调用 var client = new HttpClient(_configuredHttpClient) { BaseAddress = new Uri(QueryHelpers.AddQueryString(_settings.BaseUrl, new Dictionary<string, string?> { {"tenantId", _settings.TenantId }, {"locationId", _settings.LocationId } })) }; client.DefaultRequestHeaders.Add("X-Token", _settings.ApiToken); return new KiyohCustomerReviewManager(client); } }
这种方式下,克隆的HttpClient会继承原实例的超时设置和错误重试策略(策略配置在共享的HttpMessageHandler中)。
方案二:使用命名客户端
将超时和策略配置到特定命名的客户端上,在Get方法中创建该命名客户端:
第一步:修改DI配置
// 配置命名客户端(示例名称:MyConfiguredClient) services.AddHttpClient("MyConfiguredClient", c => { c.Timeout = TimeSpan.FromMinutes(5); }) .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync([ TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) ])); // 单独注册MyManagerFactory services.AddTransient<IMyManagerFactory, MyManagerFactory>();
第二步:修改MyManagerFactory的Get方法
public IMyManager Get(string key) { // 创建命名客户端,获取预配置实例 var client = _httpClientFactory.CreateClient("MyConfiguredClient"); var queryString = new Dictionary<string, string?> { {"tenantId", _settings.TenantId }, {"locationId", _settings.LocationId } }; var uri = QueryHelpers.AddQueryString(_settings.BaseUrl, queryString); client.BaseAddress = new Uri(uri); client.DefaultRequestHeaders.Add("X-Token", _settings.ApiToken); return new KiyohCustomerReviewManager(client); }
这样创建的客户端会自动应用你配置的超时和错误重试策略。
内容的提问来源于stack exchange,提问作者sommmen
相关产品推荐
相关产品推荐

