HttpClient 应长期复用而非每次 new+using,否则导致端口耗尽;推荐使用 IHttpClientFactory 管理生命周期、连接池与重试;发 JSON 优先用 System.Net.Http.Json 扩展方法;需分类处理超时、DNS、状态码等异常。

HttpClient 不能 new 完就丢进 using 里
这是绝大多数人写错的第一步:每次请求都 new HttpClient() 再套 using。表面看“用了就释放”,实际会迅速耗尽本地端口,高并发下直接报 SocketException: Only one usage of each socket address... —— 不是代码逻辑错,是操作系统扛不住了。
- Windows 默认
TcpTimedWaitDelay是 240 秒,每个HttpClient实例关闭后,底层 socket 会在TIME_WAIT状态卡 4 分钟,无法复用 -
HttpClient本身线程安全,设计就是用来长期复用的,不是一次性的“请求工具类” - ASP.NET Core 项目里,
using写法在控制器里跑几轮压测就大概率触发连接池枯竭
IHttpClientFactory 是 ASP.NET Core 的标准解法
别自己 static 全局单例(容易忽略 DNS 更新、证书轮换等),交给框架管最稳。它内置连接池管理、生命周期控制、命名客户端隔离,还能自动处理失败重试和熔断(配合 Polly)。
- 注册时用
services.AddHttpClient("weather", c => { c.BaseAddress = new Uri("https://api.weather.com/"); }),名字可区分不同服务 - 注入到 Controller 或 Service 后,调用
_factory.CreateClient("weather")拿实例 —— 拿到的是轻量代理,不是新连接 - 支持配置
HttpMessageHandler,比如加SocketsHttpHandler.PooledConnectionLifetime控制连接最大存活时间
发 JSON 请求别手动拼字符串
用 System.Net.Http.Json 扩展方法,比手写 StringContent + JsonSerializer.Serialize 更简洁、更安全,还自动设好 Content-Type 和编码。
- GET 取数据:
client.GetFromJsonAsync("/v3/weather/forecast/daily/5day") - POST 提交:
await client.PostAsJsonAsync("/api/users", newUser),内部自动序列化+设 header - 注意:需安装
System.Net.Http.JsonNuGet 包,.NET 5+ 已内置但不默认引用 - 如果 API 返回非标准 JSON(比如带 BOM、字段名大小写混乱),得配
JsonSerializerOptions再传入扩展方法
超时、重试、异常处理不能只靠 try-catch
HttpRequestException 是常见错误入口,但它掩盖了真实原因:可能是 DNS 失败、连接超时、响应超时、HTTP 状态码非成功(如 401/503)—— 这些得分类应对,而不是统一 log 后吞掉。
-
HttpClient.Timeout控制整个请求生命周期上限,但不包括 DNS 解析;真要细粒度控,得用SocketsHttpHandler.ConnectTimeout - 状态码错误(如 404、500)不会抛异常,
response.EnsureSuccessStatusCode()才会触发 —— 别漏掉这句,否则静默失败 - 网络抖动场景下,建议用
Polly配合IHttpClientFactory做指数退避重试,而不是在业务层反复await client.GetAsync(...)
真正麻烦的从来不是“怎么发个请求”,而是“怎么让请求在流量高峰、DNS 变更、证书过期、上游抖动时依然可靠”。HttpClient 的坑不在语法,而在它背后那张你没看见的连接网。











