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

    公众号

  • 相关阅读:
    ssh-keygen的使用方法(无密码访问)
    ubuntu solute two different terminals cmd
    ubuntu 查看系统是32位还是64位
    pyplot 绘图与可视化
    python 正则表达式的处理
    python&pandas 与mysql 连接
    Ubuntu 11.10 H3C iNode 客户端安装
    Vijos1055(极大子矩阵)
    Vijos1055(极大子矩阵)
    luoguP2701 [USACO5.3]巨大的牛棚Big Barn(极大子矩阵)
  • 原文地址:https://www.cnblogs.com/MrChuJiu/p/15842602.html
Copyright © 2020-2023  润新知