在 .Net 中将 HTTP 2 与 HttpClient 结合使用
Use HTTP 2 with HttpClient in .Net
我正在尝试通过 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/2 协议,但您没有设置 protocol property. Please do so. Did you check if it is possible on the operating system you use? .NET Core does not support this for Mac OS yet for example. Also make sure you setup the needed properties as described here using the options variable when calling ConfigureKestrel. Logically, you can also try 来设置 http 版本。
通过 curl 调用,您可以检查 http/2 call 在您的情况下是否可行。
此外,.NET Core(您使用的)中的原始 HttpClient 存在问题。请使用 HttpClientFactory.
更新 - .NET Core 3.0
.NET Core 3.0 现在 supports 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);
原答案
您can't use HTTP/2 with HttpClient in .NET Core 2.1 or 2.2,即使您在请求中明确设置了版本。您必须显式配置 .NET Core 以使用 .NET Core 2.0 随附的 old HttpClientHandler 实例,方法是使用 :
设置 App Context 开关
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
或者通过将 DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER
环境变量设置为 0
或 false
。
this Github issue 中的讨论表明 HTTP/2 计划支持 .NET Core 3.0。 Microsoft Connect 2018 发布的 3.0 Preview 1 还不支持HTTP/2。
HttpClientHandler 最高支持 .NET Core 2.0 HTTP/2。以下代码将 return 2.0
在一个以 Core 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。相同的代码将 return 1.1
作为协议版本。
如果在创建 HttpClient 之前设置了应用上下文切换,则使用 HTTP/2。此代码将 return 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;
switch和环境变量在.NET Core 2.1 SDK Preview 2官方公告中有说明:
Sockets Performance and SocketsHttpHandler
We made major improvements to sockets in .NET Core 2.1. Sockets are the basis of both outgoing and incoming networking communication. The higher-level networking APIs in .NET Core 2.1, including HttpClient and Kestrel, are now based on .NET sockets. In earlier versions, these higher-level APIs were based on native networking implementations.
...
You can use one of the following mechanisms to configure a process to use the older HttpClientHandler:
From code, use the AppContext class:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
The AppContext switch can also be set by config file.
The same can be achieved via the environment variable DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER. To opt out, set the value to either false or 0.
当前建议的模式是在 ConfigureServices
方法中注册 HttpClient
依赖项:https://docs.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);
});
...
}
我正在尝试通过 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/2 协议,但您没有设置 protocol property. Please do so. Did you check if it is possible on the operating system you use? .NET Core does not support this for Mac OS yet for example. Also make sure you setup the needed properties as described here using the options variable when calling ConfigureKestrel. Logically, you can also try
通过 curl 调用,您可以检查 http/2 call 在您的情况下是否可行。
此外,.NET Core(您使用的)中的原始 HttpClient 存在问题。请使用 HttpClientFactory.
更新 - .NET Core 3.0
.NET Core 3.0 现在 supports 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);
原答案
您can't use HTTP/2 with HttpClient in .NET Core 2.1 or 2.2,即使您在请求中明确设置了版本。您必须显式配置 .NET Core 以使用 .NET Core 2.0 随附的 old HttpClientHandler 实例,方法是使用 :
设置 App Context 开关AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
或者通过将 DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER
环境变量设置为 0
或 false
。
this Github issue 中的讨论表明 HTTP/2 计划支持 .NET Core 3.0。 Microsoft Connect 2018 发布的 3.0 Preview 1 还不支持HTTP/2。
HttpClientHandler 最高支持 .NET Core 2.0 HTTP/2。以下代码将 return 2.0
在一个以 Core 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。相同的代码将 return 1.1
作为协议版本。
如果在创建 HttpClient 之前设置了应用上下文切换,则使用 HTTP/2。此代码将 return 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;
switch和环境变量在.NET Core 2.1 SDK Preview 2官方公告中有说明:
Sockets Performance and SocketsHttpHandler
We made major improvements to sockets in .NET Core 2.1. Sockets are the basis of both outgoing and incoming networking communication. The higher-level networking APIs in .NET Core 2.1, including HttpClient and Kestrel, are now based on .NET sockets. In earlier versions, these higher-level APIs were based on native networking implementations.
...
You can use one of the following mechanisms to configure a process to use the older HttpClientHandler:
From code, use the AppContext class:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
The AppContext switch can also be set by config file.
The same can be achieved via the environment variable DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER. To opt out, set the value to either false or 0.
当前建议的模式是在 ConfigureServices
方法中注册 HttpClient
依赖项:https://docs.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);
});
...
}