dotnet團隊官方部落格釋出了一篇HTTP3的文章:HTTP/3 support in .NET 6。文章介紹了.NET 6 將預覽支援HTTP3,.NET 7正式支援HTTP3,原因主要是HTTP/3 的 RFC 尚未最終確定,因此仍然可以更改,並且在 .NET 6 中,HTTP/3 可能存在行為或效能問題。將 HTTP/3 包含在 .NET 6 中,可以開始嘗試它。

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 在客戶端和伺服器之間以較少的往返次數協商連線。 第一個請求更快地到達伺服器,QUIC 使用 UDP 並內建 TLS,因此,當 TLS 握手作為連線的一部分發生時,建立連線會更快。
  • 改進了發生連線資料包丟失時的體驗。 HTTP/2 通過一個 TCP 連線多路複用多個請求。 如果在連線時發生資料包丟失,會影響所有請求。 這個問題稱為“隊頭阻塞”。 由於 QUIC 提供本機多路複用,因此丟失的資料包只會影響已丟失資料的請求,因此在資料包丟失的情況下,它不再具有隊頭阻塞。
  • 支援在網路之間轉換。 此功能對於移動裝置非常有用,因為在移動裝置更改位置時,在 WIFI 和行動電話網路之間切換是很常見的。 目前,在切換網路時,HTTP/1.1 和 HTTP/2 連線會失敗並提示錯誤。 應用或 Web 瀏覽器必須重試任何失敗的 HTTP 請求。 HTTP/3 讓應用或 Web 瀏覽器在網路發生更改時可以無縫地繼續。不過 Kestrel 並不支援 .NET 6 中的網路轉換。 它可能在未來版本中可用。

.NET的QUIC 支援

QUIC被設計為 HTTP/3 的基礎傳輸層,但它也可用於其他協議。它設計為適用於具有處理網路更改能力的移動裝置,並在發生資料包丟失時具有良好的恢復能力。 在. NET 6 中並沒有公開.NET QUIC API,目標是在.NET 7 中公開它們。QUIC 可以像 TCP Socket 一樣使用,並不是特定於 HTTP/3,因此我們預計隨著時間的推移,其他協議將建立在 QUIC 上,例如QUIC 上的 SMB。

.NET 6 的 HTTP/3 支援

HTTP/3 支援處於預覽版狀態,因此預設情況下沒有啟用。由於並非所有路由器、防火牆和代理都能正確地支援 HTTP/3,建議將 HTTP/3 與 HTTP/1.1 和 HTTP/2 一起配置。 可通過將 HttpProtocols.Http1AndHttp2AndHttp3 指定為終結點支援的協議來完成此操作。HTTP/3 將 QUIC 用作其傳輸協議。 HTTP/3 的 .NET 實現使用 MsQuic 來提供 QUIC 功能。 MSQuic 包含在 Windows 的特定版本中,並作為 Linux 的一個庫。 如果 Kestrel 所執行的平臺沒有滿足 HTTP/3 的所有要求,則它會被禁用。

例如,HttpProtocols.Http1AndHttp2AndHttp3 允許 Kestrel 在支援 HTTP/3 的環境中啟用 HTTP/3,並對 HTTP/1.1 和 HTTP/2 進行回退。

Windows

  • Windows 11 內部版本 22000 或更高版本和Server 2022 RTM。
  • TLS 1.3 或更高版本的連線。

上述 Windows 11 內部版本可能需要使用 Windows 預覽體驗成員內部版本

Linux

在 Linux 上,libmsquic 是通過 Microsoft 官方 Linux 包儲存庫 packages.microsoft.com 釋出的。 為了使用它,必須手動新增。 請參閱 Microsoft 產品的 Linux 軟體儲存庫。 新增 libmsquic 後,可以通過發行版的包管理器安裝它,例如,對於 Ubuntu:

sudo apt install libmsquic

macOS

HTTP/3 目前在 macOS 上不受支援,主要是因為缺少與 QUIC 相容的 TLS API。它可能在未來版本中可用。

Alt-svc

HTTP/3 是通過 alt-svc 標頭作為從 HTTP/1.1 或 HTTP/2 的升級發現的。 這意味著,在切換到 HTTP/3 之前,第一個請求通常使用 HTTP/1.1 或 HTTP/2。 如果啟用了 HTTP/3,則 Kestrel 會自動新增 alt-svc 標頭。

入門

HTTP/3 是在應用啟動時配置的。 下面的程式碼:

  • WebHost 配置為 UseQuic
  • 配置埠 5001 以使用 HttpProtocols.Http1AndHttp2AndHttp3
首先要啟用預覽版特性,新增下列專案屬性
<PropertyGroup>
<EnablePreviewFeatures>True</EnablePreviewFeatures>
</PropertyGroup>

public static async Task Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, options) =>
{
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
// Use HTTP/3
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps();
});
});
}

HTTP/3 Client

HttpClient 已更新,以包括對 HTTP/3 的支援,但它需要啟用執行時標記。在專案檔案中包括以下內容,以便 HTTP/3 與 HttpClient 配合使用:

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

使用 HttpClient 進行 HTTP/3 請求時,需要額外的配置:

  • HttpClient .DefaultRequestVersion 設定為 3.0,或者
  • HttpClient .DefaultVersionPolicy 設定為 HttpVersionPolicy.RequestVersionExact
// See https://aka.ms/new-console-template for more information
using System.Net; var client = new HttpClient();
client.DefaultRequestVersion = HttpVersion.Version30;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact; var resp = await client.GetAsync("https://localhost:5001/");
var body = await resp.Content.ReadAsStringAsync(); Console.WriteLine($"status: {resp.StatusCode}, version: {resp.Version}, body: {body.Substring(0, Math.Min(100, body.Length))}");

gRpc over HTTP3

gRPC 通常使用 HTTP/2 作為傳輸工具。HTTP/3 使用相同的語義,因此幾乎不需要任何更改就能使其工作。由 .NET 團隊提出 HTTP/3 的 gRPC 尚未成為標準:https://github.com/grpc/proposal/pull/256

.NET 團隊將在.NET 7 中進一步開發 QUIC 和 HTTP/3,因此期待在預覽過程中得到更新的功能。