简体   繁体   English

如何通过普通 http 服务器在 C# Kestrel web 服务器中启用 http2?

[英]How do I enable http2 in C# Kestrel web server over plain http?

How do I (and is it possible) to enable http2 over plain http in the C# Kestrel web server?我如何(并且有可能)在 C# Kestrel web 服务器中的普通 http 上启用 http2? All Microsoft documentation indicates that https/TLS is required, but I have services that will be running behind a load-balancer or nginx and as such don't need a second layer of https.所有 Microsoft 文档都表明需要 https/TLS,但我的服务将在负载平衡器或 nginx 后面运行,因此不需要第二层 https。 The official http2 spec indicates that https is not required.官方 http2 规范表明 https 不是必需的。

Scenarios to use unencrypted http2 are load balancers, proxies, etc.使用未加密 http2 的场景是负载均衡器、代理等。

You must do three things to use http2 over unencrypted channel.您必须做三件事才能在未加密的通道上使用 http2。

Setup Kestrel to use http2 on your server:设置 Kestrel 在您的服务器上使用 http2:

builder.ConfigureWebHostDefaults((webBuilder) =>
{
    // this will keep your other end points settings such as --urls parameter
    webBuilder.ConfigureKestrel((options) =>
    {
        // trying to use Http1AndHttp2 causes http2 connections to fail with invalid protocol error
        // according to Microsoft dual http version mode not supported in unencrypted scenario: https://docs.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0
        options.ConfigureEndpointDefaults(lo => lo.Protocols = HttpProtocols.Http2);
    });
});

For .net 5+, create your HttpClient instance, then create a message and specify the version:对于 .net 5+,创建您的HttpClient实例,然后创建一条消息并指定版本:

var request = new HttpRequestMessage(HttpMethod.Get, uri)
{
    Version = HttpVersion.Version20,
    VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher
};

For .net core 3.1 and older, set a flag to enable http2 unencrypted.对于 .net 内核 3.1 及更早版本,设置一个标志以启用未加密的 http2。 Then, when you create an HttpClient , specify the version:然后,当您创建HttpClient时,指定版本:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var client = new HttpClient { BaseAddress = new Uri(baseUrl), DefaultRequestVersion = new Version(2, 0) };

If you need to support both http1 and http2 on a completely unencrypted host, then you will need to listen on two ports, one for each http version.如果您需要在完全未加密的主机上同时支持 http1 和 http2,则需要监听两个端口,每个 http 版本一个。 Then your load balancer or proxy would need to handle the http version and direct to the appropriate port.然后,您的负载均衡器或代理将需要处理 http 版本并直接连接到适当的端口。

You won't see http2 on your browser and will likely get a protocol error, so in those cases you can use an http1 protocol directive just for development environment.您不会在浏览器上看到 http2,并且可能会收到协议错误,因此在这些情况下,您可以将 http1 协议指令仅用于开发环境。 Not ideal, but it at least lets you test locally.不理想,但它至少可以让您在本地进行测试。

Make sure you are using Microsoft.AspNetCore.WebHost instead of the generic Microsoft.Extensions.Hosting.Host for the CreateDefaultBuilder as you will run into an annoying OpenSslCryptographicException when running dotnet core 3 grpc containers on docker linux instances.确保您使用Microsoft.AspNetCore.WebHost而不是通用的Microsoft.Extensions.Hosting.Host作为CreateDefaultBuilder ,因为在 docker linux 实例上运行 dotnet core 3 grpc 容器时会遇到烦人的OpenSslCryptographicException

Also, if you are using health checks, be sure to expose it on a different port as illustrated in the below Program.cs snippet:此外,如果您正在使用运行状况检查,请确保将其暴露在不同的端口上,如下面的Program.cs片段所示:

public static IWebHostBuilder CreateHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureKestrel(options => {
            //grpc port for http2 connections
            options.ListenAnyIP(xxxx, listenOptions => {
                listenOptions.Protocols = HttpProtocols.Http2;
            });
            //add health check on a separate port instead of Http1AndHttp2 on same port
            options.ListenAnyIP(xxxx, listenOptions => {
                listenOptions.Protocols = HttpProtocols.Http1;
            });
        })
        .UseStartup<Startup>();

The easiest way is to use configuration section for Kestrel in appSettings.json.最简单的方法是在 appSettings.json 中使用 Kestrel 的配置部分。

  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  },

To turn of SSL, you may want to remove app.UseHsts() , app.UseHttpsRedirections() options from Statup.cs Configure method and expose only Http url.要打开 SSL,您可能需要从 Statup.cs 配置方法中删除app.UseHsts()app.UseHttpsRedirections()选项并仅公开 Http Z572D4E421E5E6B9BC12D815E

You can also use Http1AndHttp2 to support both Http1 and Http2 together.您也可以使用Http1AndHttp2同时支持Http1Http2

In dotnet 5 AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);在 dotnet 5 AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); is no longer supported.不再支持。

To allow prior knowledge http/2 you need to configure your HttpRequestMessage:要允许先验知识 http/2,您需要配置 HttpRequestMessage:

var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost/something"))
            {
                Version = HttpVersion.Version20,
                VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher //This allows http/2 unencrypted,
            };

For reference: https://github.com/dotnet/runtime/issues/987供参考: https://github.com/dotnet/runtime/issues/987

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM