在 .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,可以阅读以下文章:
- https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/
- https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/
- https://www.smashingmagazine.com/2021/09/http3-practical-deployment-options-part3/
- https://blog.cloudflare.com/http-3-vs-http-2/
- https://techcommunity.microsoft.com/t5/networking-blog/deploying-http-3-on-windows-server-at-scale/ba-p/2839394?WT.mc_id=DT-MVP-5003978
- https://eng.snap.com/quic-at-snap/
.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