在 .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

公众号

posted @ 2022-01-25 13:26  初久的私房菜  阅读(988)  评论(0编辑  收藏  举报
作者:初久的私房菜
好好学习,天天向上
返回顶部小火箭
好友榜:
如果愿意,把你的博客地址放这里
张弛:https://blog.zhangchi.fun/