dotnet團隊官方博客發布了一篇HTTP3的文章:HTTP/3 support in .NET 6:https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-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,因此期待在預覽過程中得到更新的功能。
相關文章:
