在 .NET 中使用 HTTP/3(QUIC)


介紹

之前我給大家講過使用GitHub Actions 做CI/CD,今天看到一篇不錯的文章拿來翻譯下

源作者鏈接:https://www.meziantou.net/using-http-3-quic-in-dotnet.htm

正文

什么是 HTTP/3

HTTP/3 是 HTTP 的新版本。大多數現代瀏覽器和服務器都支持 HTTP/3 協議。此更新應主要為移動用戶或不可靠的連接帶來性能優勢。主要思想是用一個新的協議QUIC來代替TCP,它消除了TCP for HTTP的一些問題。因此,QUIC 具有以下優點(並非詳盡列表):

  • 通過結合 TCP 和 TLS 握手更快地建立連接
  • 通過更好地處理丟包恢復邏輯來減少線頭阻塞
  • 連接遷移,因此您在網絡之間移動時無需重新連接(握手)(例如 WIFI 到蜂窩)

如果您想詳細了解什么是 HTTP/3,可以閱讀以下文章:

.NET 6 支持客戶端(HttpClient包括 gRPC)和服務器(Kestrel)的 HTTP/3。此實現基於MsQuic,是IETF QUIC協議的 Microsoft 實現。請注意,在 .NET 6 中仍處於預覽狀態,因此您需要在 csproj 或代碼中顯式啟用它。目前,.NET 支持 HTTP/3:

  • Windows 11 和 Windows Server 2022
  • Linux(您可能需要msquic使用安裝apt install libmsquic)
  • 雖然msquic支持使用 OpenSSL 的 macOS,但 .NET 實現目前不支持它。事實上,.NET 團隊更喜歡依賴操作系統安全 API,而不是添加新的依賴項,SecureTransport比如 macOS。這避免了集成問題,例如證書管理。但是,SecureTransport不公開實現 QUIC 的方法。
服務端(Kestrel)

您首先需要在 csproj 中啟用預覽功能:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <EnablePreviewFeatures>true</EnablePreviewFeatures>
  </PropertyGroup>
</Project>

然后,您可以將 Kestrel 配置為偵聽 HTTP/1、HTTP/2 和 HTTP/3。支持舊協議很重要,因為並非所有客戶端都支持新協議。此外,HTTP/3 需要安全連接,因此您必須使用UseHttps.

using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, options) =>
{
    options.ListenAnyIP(5001, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
        listenOptions.UseHttps();
    });
});
var app = builder.Build();

app.MapGet("/", () => "hello world");
app.Run();

大多數瀏覽器不允許localhost地址使用 HTTP/3。但是,您可以通過查看響應標頭來驗證它是否有效。響應應包含具有值的alt-svc標頭h3:

圖片

您還可以通過啟用更詳細的日志記錄來檢查服務器使用 HTTP/3。appsettings.json您可以在或中更改配置appsettings.Development.json:

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.Hosting.Diagnostics":  "Information"
    }
  }
}

然后,您應該在日志中看到以下內容:

圖片

您還可以使用 W3C 日志記錄並檢查客戶端使用的協議版本:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddW3CLogging(logging =>
{
    logging.LoggingFields = W3CLoggingFields.All;
    logging.LogDirectory = @"C:\logs";
    logging.FlushInterval = TimeSpan.FromSeconds(2);
});

builder.WebHost.ConfigureKestrel((context, options) =>
{
    ...
});

var app = builder.Build();
app.UseW3CLogging();
app.MapGet("/", () => "hello world");
app.Run();

圖片

客戶端 (HttpClient)

有兩種方法可以啟用 HTTP/3 支持HttpClient:

  • 編輯 csproj 以添加運行時選項
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support"
                                    Value="true" />
  </ItemGroup>
</Project>
  • 在創建第一個之前設置以下開關 HttpClient
    System.AppContext.SetSwitch("System.Net.SocketsHttpHandler.Http3Support", true);

然后,您可以使用HttpClient向 HTTP/3 服務器發出請求:

using var client = new HttpClient();
client.DefaultRequestVersion = HttpVersion.Version30;

// The client falls back to HTTP2 or HTTP1 if HTTP3 is not supported
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;

// Will use HTTP3 if the server supports it
var data = await client.GetStringAsync("https://localhost:5001/");

您還可以為特定請求啟用 HTTP3:

using var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:5001/");
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;

using var response = await client.SendAsync(request);
var data = await response.Content.ReadAsStringAsync();

結語

聯系作者:加群:867095512 @MrChuJiu

公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM