【微软技术栈】C#.NET HttpClient 的使用准则

本文内容

  1. DNS 行为
  2. 共用连接
  3. 推荐使用
  4. 使用静态客户端的复原策略

System.Net.Http.HttpClient 类用于发送 HTTP 请求以及从 URI 所标识的资源接收 HTTP 响应。 HttpClient 实例是应用于该实例执行的所有请求的设置集合,每个实例使用自身的连接池,该池将其请求与其他请求隔离开来。 从 .NET Core 2.1 开始,SocketsHttpHandler 类提供实现,使行为在所有平台上保持一致。

1、DNS 行为

HttpClient 仅在创建连接时解析 DNS 条目。 它不跟踪 DNS 服务器指定的任何生存时间 (TTL)。 如果 DNS 条目定期更改(这可能在某些方案中发生),客户端将不会遵循这些更新。 要解决此问题,可以通过设置 PooledConnectionLifetime 属性来限制连接的生存期,以便在替换连接时重复执行 DNS 查找。 请考虑以下示例:

var handler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(15) // Recreate every 15 minutes
};
var sharedClient = new HttpClient(handler);

上述 HttpClient 配置为重复使用连接 15 分钟。 PooledConnectionLifetime 指定的时间范围过后,系统会关闭连接,然后创建一个新连接。

2、共用连接

HttpClient 的连接池链接到其基础 SocketsHttpHandler。 释放 HttpClient 实例时,它会释放池中的所有现有连接。 如果稍后向同一服务器发送请求,则必须重新创建一个新连接。 因此,创建不必要的连接会导致性能损失。 此外,TCP 端口不会在连接关闭后立即释放。 (有关这一点的详细信息,请参阅 RFC 9293 中的 TCP TIME-WAIT。)如果请求速率较高,则可用端口的操作系统限制可能会耗尽。 为了避免端口耗尽问题,建议将 HttpClient 实例重用于尽可能多的 HTTP 请求。

3、推荐使用

为了对建议的 HttpClient 在生存期管理方面的使用进行总结,应使用长期客户端,并设置 PooledConnectionLifetime(.NET Core 和 .NET 5+)或由 IHttpClientFactory 创建的短期客户端

  • 在 .NET Core 和 .NET 5+ 中:

    • 根据预期的 DNS 更改,使用 static 或 singletonHttpClient 实例,并将 PooledConnectionLifetime 设置为所需间隔(例如 2 分钟)。 这可以解决端口耗尽和 DNS 更改两个问题,而且不会增加 IHttpClientFactory 的开销。 如果需要模拟处理程序,可以单独注册它。

     提示

    如果只使用有限数量的 HttpClient 实例,这也是可接受的策略。 重要的是,它不是随每个请求一起创建和释放的,因为它们每一个都包含一个连接池。 对于具有多个代理的方案,或者要在不完全禁用 Cookie 处理的情况下分离 Cookie 容器,必须使用多个实例。

    • 使用 IHttpClientFactory,可以针对不同的用例使用多个以不同方式配置的客户端。 但请注意,工厂创建的客户端生存期较短,一旦创建客户端,工厂就不再可以控制它。

      工厂合并 HttpMessageHandler 实例,如果其生存期尚未过期,则当工厂创建新的 HttpClient 实例时,可以从池中重用处理程序。 这种重用避免了任何套接字耗尽问题。

      如果需要 IHttpClientFactory 提供的可配置性,我们建议使用类型化客户端方法

  • 在 .NET Framework 中,使用 IHttpClientFactory 管理 HttpClient 实例。 如果不使用工厂,而是改为自行为每个请求创建新的客户端实例,则可能耗尽可用的端口。

     提示

    如果应用需要 Cookie,请考虑禁用自动 Cookie 处理或避免使用 IHttpClientFactory。 共用 HttpMessageHandler 实例会导致共享 CookieContainer 对象。 意外的 CookieContainer 对象共享通常会导致错误的代码。

有关通过 IHttpClientFactory 管理 HttpClient 生存期的详细信息,请参阅 IHttpClientFactory 指南

4、使用静态客户端的复原策略

可以使用以下模式将 static 或单一实例客户端配置为使用任意数量的复原策略:

using System;
using System.Net.Http;
using Microsoft.Extensions.Http;
using Polly;
using Polly.Extensions.Http;

var retryPolicy = HttpPolicyExtensions
    .HandleTransientHttpError()
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

var socketHandler = new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(15) };
var pollyHandler = new PolicyHttpMessageHandler(retryPolicy)
{
    InnerHandler = socketHandler,
};

var httpClient = new HttpClient(pollyHandler);

前面的代码:

  • 依赖于 Microsoft.Extensions.Http.Polly NuGet 包,以及传递性地依赖于 Polly.Extensions.Http NuGet 包,用于 HttpPolicyExtensions 类型。
  • 指定一个暂时性 HTTP 错误处理程序,该处理程序配置了重试策略,每次尝试都会指数退避延迟间隔。
  • 定义 socketHandler 的入池连接生存期为 15 分钟。
  • 使用重试逻辑将 socketHandler 传递给 policyHandler
  • 根据 policyHandler 实例化 HttpClient
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉特思米(gitusme)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值