在 .Net 中使用 HTTP 2 和 HttpClient

问题描述 投票:0回答:3

我正在尝试通过 HTTP 2.0 请求数据。我正在使用 .Net Core 2.2 中的 HttpClient。我使用的是 Windows 10,但在生产环境中将在 Linux 上运行。问题是响应中的版本似乎始终是“1.1”。我做错了什么?

using (var client = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("GET"),
    "https://duckduckgo.com/"
    ))
    {
        request.Version = new Version(2, 0);
        var response = await client.SendAsync(request);

        Console.WriteLine(response.Version);
    }
}
http asp.net-core .net-core dotnet-httpclient http2
3个回答
25
投票

更新 - .NET Core 3.0

.NET Core 3.0 现在支持 HTTP/2。以下代码将打印

2.0
:

var client = new HttpClient();

var req = new HttpRequestMessage(HttpMethod.Get, "https://http2.akamai.com/demo"){
             Version = new Version(2, 0) 
             };

var x = await client.SendAsync(req);
var version = x.Version;

Console.WriteLine(version);

原答案

无法在 .NET Core 2.1 或 2.2 中将 HTTP/2 与 HttpClient 一起使用,即使您在请求中显式设置版本也是如此。您必须显式配置 .NET Core 以使用 .NET Core 2.0 附带的old HttpClientHandler 实例,方法是使用 :

设置应用程序上下文开关
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);

或者将

DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER
环境变量设置为
0
false

此 Github 问题中的讨论表明 .NET Core 3.0 计划支持 HTTP/2。 Microsoft Connect 2018 上发布的 3.0 Preview 1 尚不支持 HTTP/2。

HttpClientHandler 使用到 .NET Core 2.0 支持 HTTP/2。以下代码将在面向 Core 2.0 的项目中返回

2.0
:

var client = new HttpClient();

var req = new HttpRequestMessage(HttpMethod.Get, "https://http2.akamai.com/demo")
{
    Version = new Version(2, 0)
};

var x = await client.SendAsync(req);
var version = x.Version;

Console.WriteLine(version);

如果更改目标运行时,请确保彻底清理项目 - 删除

bin
obj
所有目标文件,否则您最终可能会像我一样运行错误的运行时。

在 2.1 中,添加了一个新的、更快的 SocketsHttpClientHandler 作为默认值。新的处理程序尚不支持 HTTP/2。相同的代码将返回

1.1
作为协议版本。

如果在创建 HttpClient 之前设置了应用程序上下文切换,则使用 HTTP/2。此代码将返回

2.0
。有趣的是,不需要指定 HTTP 版本。当 HTTP/2 可用时,将协商实际协议版本。即使未指定版本,Akamai URL 和
https://www.google.com
都将使用 HTTP/2:

AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
var client = new HttpClient();

var req = new HttpRequestMessage(HttpMethod.Get, "https://http2.akamai.com/demo");
var x = await client.SendAsync(req);

var version = x.Version;

开关和环境变量在 .NET Core 2.1 SDK Preview 2 官方公告中进行了解释:

Sockets 性能和 SocketsHttpHandler

我们对 .NET Core 2.1 中的套接字进行了重大改进。套接字是传出和传入网络通信的基础。 .NET Core 2.1 中的更高级别网络 API(包括 HttpClient 和 Kestrel)现在基于 .NET 套接字。在早期版本中,这些更高级别的 API 基于本机网络实现。

...

您可以使用以下机制之一来配置进程以使用旧版 HttpClientHandler:

从代码中,使用 AppContext 类:

AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);

AppContext开关也可以通过配置文件设置。

同样可以通过环境变量 DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER 来实现。要选择退出,请将值设置为 false 或 0。


5
投票

当前建议的模式是在

HttpClient
方法中注册
ConfigureServices
依赖项:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests

这是使用类型化客户端注册默认

HttpClient
并将其配置为使用 HTTP/2 的示例:

public void ConfigureServices(IServiceCollection services)
{
...
    services.AddHttpClient<ExampleService>()
        .ConfigureHttpClient((client) =>
        {
            client.DefaultRequestVersion = new Version(2, 0);
        });
...
}

1
投票

您想使用 http/2 协议,但没有设置 protocol 属性。请这样做。您是否检查过您使用的操作系统是否可以?例如,.NET Core 尚不支持 Mac 操作系统。另请确保在调用ConfigureKestrel时使用选项变量按照此处所述设置所需的属性。按理说,你也可以尝试这种替代方式来设置http版本。

通过进行curl调用,您可以检查您的

http/2调用是否适合您的情况。

此外,.NET Core(您使用的)中的原始 HttpClient 也存在问题。请使用

HttpClientFactory

© www.soinside.com 2019 - 2024. All rights reserved.