将 HTTP/3 与 HttpClient 结合使用

HTTP/3 是 HTTP 的第三个也是最近标准化的主版本。 HTTP/3 使用与 HTTP/1.1 和 HTTP/2 相同的语义:相同的请求方法、状态代码和消息字段适用于所有版本。 差异在于基础传输。 HTTP/1.1 和 HTTP/2 都将 TCP 用作其传输协议。 HTTP/3 使用的是与 HTTP/3 同时开发的一种传输技术,称为 QUIC

与 HTTP/1.1 和 HTTP/2 相比,HTTP/3 和 QUIC 具有很多优势:

  • 第一个请求的响应时间更短。 QUIC 和 HTTP/3 在客户端和服务器之间以较少的往返次数协商连接。 第一个请求会更快地到达服务器。
  • 改进了发生连接数据包丢失时的体验。 HTTP/2 通过一个 TCP 连接多路复用多个请求。 如果在连接时发生数据包丢失,会影响所有请求。 这个问题称为“队头阻塞”。 由于 QUIC 提供本机多路复用,因此丢失的数据包只会影响已丢失数据的请求。
  • 支持在网络之间转换。 此功能对于移动设备非常有用,因为在移动设备更改位置时,在 WIFI 和移动电话网络之间切换是很常见的。 目前,在切换网络时,HTTP/1.1 和 HTTP/2 连接会失败并提示错误。 应用或 Web 浏览器必须重试任何失败的 HTTP 请求。 HTTP/3 让应用或 Web 浏览器在网络发生更改时可以无缝地继续。 HttpClient 和 Kestrel 不支持 .NET 7 中的网络转换。 它可能在未来版本中可用。

重要

配置为利用 HTTP/3 的应用应设计为也支持 HTTP/1.1 和 HTTP/2。 如果在 HTTP/3 中标识了问题,建议禁用 HTTP/3,直到问题在 .NET 的未来版本中得到解决。

HttpClient 设置

可以通过将 HttpRequestMessage.Version 设置为 3.0 来配置 HTTP 版本。 但是,由于并非所有路由器、防火墙和代理都能正确地支持 HTTP/3,建议将 HTTP/3 与 HTTP/1.1 和 HTTP/2 一起配置。 在 HttpClient 中,可以通过指定以下内容来实现此目的:

平台依赖项

HTTP/3 将 QUIC 用作其传输协议。 HTTP/3 的 .NET 实现使用 MsQuic 来提供 QUIC 功能。 因此,.NET 对 HTTP/3 的支持取决于 MsQuic 平台要求。 有关如何安装 MsQuic 的详细信息,请参阅 QUIC 平台依赖项。 如果运行 HttpClient 的平台不满足 HTTP/3 的所有要求,则会将它禁用。

使用 HttpClient

以下代码示例使用顶级语句,演示如何在请求中指定 HTTP3:

// See https://aka.ms/new-console-template for more information
using System.Net;

using var client = new HttpClient
{
    DefaultRequestVersion =  HttpVersion.Version30,
    DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact
};

Console.WriteLine("--- localhost:5001 ---");

HttpResponseMessage resp = await client.GetAsync("https://localhost:5001/");
string body = await resp.Content.ReadAsStringAsync();

Console.WriteLine(
    $"status: {resp.StatusCode}, version: {resp.Version}, " +
    $"body: {body.Substring(0, Math.Min(100, body.Length))}");

.NET 6 中的 HTTP/3 支持

在 .NET 6 中,HTTP/3 作为预览功能提供,因为 HTTP/3 规范尚未完成。 在 .NET 6 中使用 HTTP/3 时可能存在行为或性能问题。 有关预览功能的详细信息,请参阅预览功能规范

若要在 .NET 6 中启用 HTTP/3 支持,请将 RuntimeHostConfigurationOption 节点添加到项目文件中,以便将 HTTP/3 与 HttpClient 结合使用:

<ItemGroup>
    <RuntimeHostConfigurationOption Value="true"
        Include="System.Net.SocketsHttpHandler.Http3Support" />
</ItemGroup>

或者,可以从应用代码调用 System.AppContext.SetSwitch,或将 DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORT 环境变量设置为 true。 有关详细信息,请参阅 .NET 环境变量:DOTNET_SYSTEM_NET_HTTP_*

需要为 HTTP/3 设置配置标志的原因是为了防止将来在使用版本策略 RequestVersionOrHigher 时应用发生中断。 调用当前使用 HTTP/1.1 和 HTTP/2 的服务器时,如果服务器随后升级到 HTTP/3,则客户端会尝试使用 HTTP/3 并且有可能不兼容,因为标准并不是最终版本,因此在 . NET 6 发布后可能会更改。

.NET 6 仅与 libmsquic 的 1.9.x 版本兼容。 由于库的中断性变更,Libmsquic 2.x 与 .NET 6 不兼容。 如果需要,Libmsquic 会接收对 1.9.x 的更新,以合并安全修补程序。

HTTP/3 服务器

HTTP/3 由 ASP.NET 和 Kestrel 服务器提供支持,在 .NET 6 中作为预览版功能提供,在 .NET 7 中完全受支持。 有关详细信息,请参阅对 ASP.NET Core Kestrel Web 服务器使用 HTTP/3

公测服务器

Cloudflare 托管了一个可用于在 https://cloudflare-quic.com 上测试客户端的 HTTP/3 站点。

另请参阅