我如何(是否有可能)在 C# Kestrel Web 服务器中通过普通 http 启用 http2?所有 Microsoft 文档都表明需要 https/TLS,但我有将在负载平衡器或 nginx 后面运行的服务,因此不需要第二层 https。官方 http2 规范表明不需要 https。
jjx*_*tra 10
使用未加密 http2 的场景是负载均衡器、代理等。
您必须做三件事才能在未加密的通道上使用 http2。
设置 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);
});
});
Run Code Online (Sandbox Code Playgroud)
对于 .net 5+,创建您的HttpClient实例,然后创建一条消息并指定版本:
var request = new HttpRequestMessage(HttpMethod.Get, uri)
{
Version = HttpVersion.Version20,
VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher
};
Run Code Online (Sandbox Code Playgroud)
对于 .net core 3.1 及更早版本,设置一个标志以启用未加密的 http2。然后,当您创建 时HttpClient,请指定版本:
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var client = new HttpClient { BaseAddress = new Uri(baseUrl), DefaultRequestVersion = new Version(2, 0) };
Run Code Online (Sandbox Code Playgroud)
如果需要在完全未加密的主机上同时支持 http1 和 http2,则需要侦听两个端口,每个端口对应一个 http 版本。然后您的负载平衡器或代理需要处理 http 版本并定向到适当的端口。
您不会在浏览器上看到 http2,并且可能会出现协议错误,因此在这些情况下,您可以仅将 http1 协议指令用于开发环境。不理想,但它至少可以让您在本地进行测试。
小智 8
确保您使用的是Microsoft.AspNetCore.WebHost而不是通用的,Microsoft.Extensions.Hosting.Host因为在 docker Linux 实例上运行 dotnet core 3 grpc 容器时CreateDefaultBuilder您会遇到烦人的情况OpenSslCryptographicException。
另外,如果您正在使用运行状况检查,请务必将其公开在不同的端口上,如下面的代码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>();
Run Code Online (Sandbox Code Playgroud)
最简单的方法是使用 appSettings.json 中 Kestrel 的配置部分。
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"
}
},
Run Code Online (Sandbox Code Playgroud)
要关闭 SSL,您可能需要从 Statup.cs 配置方法中删除app.UseHsts(),选项并仅公开 Http url。app.UseHttpsRedirections()
您还可以同时使用和Http1AndHttp2来支持两者。Http1Http2