C# IHttpClientFactory

1124 字
6 分钟
C# IHttpClientFactory

C# 中 IHttpClientFactory 的介绍和最佳实践#

在 .NET 应用程序中进行 HTTP 请求时,HttpClient 是最常用的类。然而,直接使用 HttpClient 可能会导致一些问题,如端口耗尽和 DNS 更新问题。IHttpClientFactory 是 .NET Core 2.1 引入的一个接口,旨在解决这些问题并提供更好的 HTTP 客户端管理。

1. 为什么需要 IHttpClientFactory?#

1.1 直接使用 HttpClient 的问题#

  1. 端口耗尽:每次创建新的 HttpClient 实例都会创建新的套接字连接,可能导致端口耗尽。
  2. DNS 更新问题HttpClient 默认会缓存 DNS 记录,即使 DNS 记录发生变化,也不会立即更新。
  3. 资源管理:需要手动管理 HttpClient 的生命周期,容易导致资源泄漏。

1.2 IHttpClientFactory 的优势#

  1. 集中管理:通过工厂模式集中管理 HttpClient 实例的创建和配置。
  2. 生命周期管理:自动管理底层 HttpMessageHandler 的生命周期,避免端口耗尽问题。
  3. 可配置性:支持命名客户端和类型化客户端,便于配置不同的 HTTP 客户端。
  4. 依赖注入友好:与 ASP.NET Core 的依赖注入系统无缝集成。
  5. 中间件支持:可以轻松添加日志、重试、熔断等中间件。

2. 配置 IHttpClientFactory#

2.1 在 ASP.NET Core 中配置#

Program.csStartup.cs 中添加服务:

// Program.cs (.NET 6+)
var builder = WebApplication.CreateBuilder(args);
// 添加 HttpClient 工厂服务
builder.Services.AddHttpClient();
var app = builder.Build();

2.2 在控制台应用中配置#

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddHttpClient();
})
.Build();

3. 使用 IHttpClientFactory#

3.1 基本用法#

通过依赖注入 IHttpClientFactory 并创建客户端:

public class MyService
{
private readonly IHttpClientFactory _httpClientFactory;
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> GetDataAsync()
{
var client = _httpClientFactory.CreateClient();
var response = await client.GetAsync("https://api.example.com/data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}

3.2 命名客户端#

为不同的服务配置不同的客户端:

// 配置服务
builder.Services.AddHttpClient("GitHub", client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});
// 使用命名客户端
public class GitHubService
{
private readonly IHttpClientFactory _httpClientFactory;
public GitHubService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> GetRepositoriesAsync()
{
var client = _httpClientFactory.CreateClient("GitHub");
var response = await client.GetAsync("repositories");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}

3.3 类型化客户端#

创建强类型的客户端类,这是推荐的方式:

// 定义类型化客户端
public class GitHubClient
{
private readonly HttpClient _httpClient;
public GitHubClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<List<Repository>> GetRepositoriesAsync()
{
var response = await _httpClient.GetAsync("repositories");
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<List<Repository>>(content);
}
}
// 配置类型化客户端
builder.Services.AddHttpClient<GitHubClient>(client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});
// 使用类型化客户端
public class MyController : ControllerBase
{
private readonly GitHubClient _gitHubClient;
public MyController(GitHubClient gitHubClient)
{
_gitHubClient = gitHubClient;
}
public async Task<IActionResult> GetRepositories()
{
var repositories = await _gitHubClient.GetRepositoriesAsync();
return Ok(repositories);
}
}

4. 最佳实践#

4.1 优先使用类型化客户端#

类型化客户端提供了以下优势:

  • 强类型支持,编译时检查
  • 代码更清晰,易于维护
  • 可以封装业务逻辑

4.2 正确配置 HttpClient#

builder.Services.AddHttpClient<GitHubClient>(client =>
{
// 设置合理的超时时间
client.Timeout = TimeSpan.FromSeconds(30);
// 设置基础地址
client.BaseAddress = new Uri("https://api.github.com/");
// 设置默认请求头
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
client.DefaultRequestHeaders.Add("User-Agent", "YourApp-Name");
});

4.2 避免反模式#

  1. 不要在每次请求时创建新的 HttpClient 实例
  2. 不要using 块中使用 HttpClient(除非使用 IHttpClientFactory
  3. 不要手动管理 HttpClient 的生命周期

5. 高级配置#

5.1 自定义消息处理程序#

创建自定义的 DelegatingHandler

public class LoggingHandler : DelegatingHandler
{
private readonly ILogger<LoggingHandler> _logger;
public LoggingHandler(ILogger<LoggingHandler> logger)
{
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
_logger.LogInformation($"Sending request to {request.RequestUri}");
var response = await base.SendAsync(request, cancellationToken);
_logger.LogInformation($"Response status: {response.StatusCode}");
return response;
}
}
// 注册处理程序
builder.Services.AddTransient<LoggingHandler>();
builder.Services.AddHttpClient<GitHubClient>(client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
})
.AddHttpMessageHandler<LoggingHandler>();

5.2 多个客户端配置#

为不同的服务配置不同的客户端:

// GitHub 客户端
builder.Services.AddHttpClient<GitHubClient>(client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
});
// 其他 API 客户端
builder.Services.AddHttpClient<PaymentService>(client =>
{
client.BaseAddress = new Uri("https://api.payment.com/");
client.Timeout = TimeSpan.FromSeconds(60);
});

6. 总结#

IHttpClientFactory 是 .NET 中管理 HttpClient 的最佳方式,它解决了直接使用 HttpClient 的各种问题,并提供了以下优势:

  1. 资源管理:自动管理 HttpMessageHandler 的生命周期,避免端口耗尽
  2. 配置灵活性:支持命名客户端和类型化客户端
  3. 依赖注入集成:与 ASP.NET Core 的 DI 系统无缝集成
  4. 中间件支持:可以轻松添加日志、重试、熔断等中间件
  5. 最佳实践:遵循 Microsoft 推荐的 HTTP 客户端使用模式

在开发新的 .NET 应用程序时,强烈建议使用 IHttpClientFactory 而不是直接创建 HttpClient 实例。这不仅提高了应用程序的可靠性,还使代码更易于维护和测试。

参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
C# IHttpClientFactory
https://firefly.cuteleaf.cn/posts/csharp-ihttpclientfactory/
作者
Shasnow
发布于
2026-05-16
许可协议
Unlicensed

评论区

Profile Image of the Author
Shasnow
Hello, I'm Shasnow.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
22
分类
4
标签
20
总字数
68,022
运行时长
0
最后活动
0 天前

文章目录