摘要

Http / 2协议提供了在单个连接上复用多个请求的功能。这样可以更有效地使用连接-请参见https://http2.github.io/faq/#why-is-http2-multiplexed

我希望能够使用.Net Core HttpClient来实现此目的。我的测试(基于以下内容)表明请求与TCP连接的比例为1:1。

.Net Core HttpClient是否支持多路复用?如果是这样,如何实现?

到目前为止工作

我有一个示例应用程序(可以在here中找到存储库,带有以下代码;

using (var httpClient = new HttpClient())
{
   var request1 = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
   request1.Version = new Version(2, 0);

   var request2 = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
   request2.Version = new Version(2, 0);

   var task1 = httpClient.SendAsync(request1);
   var task2 = httpClient.SendAsync(request2);

   Task.WaitAll(task1, task2);

   var response1 = task1.Result;
   var response2 = task2.Result;

   Console.WriteLine($"Response 1 - Http Version: {response1.Version}, Http Status Code: {response1.StatusCode}");
   Console.WriteLine($"Response 2 - Http Version: {response2.Version}, Http Status Code: {response2.StatusCode}");
}


这段代码产生以下结果(所以我知道正在使用Http / 2);

Response 1 - Http Version: 2.0, Http Status Code: OK
Response 2 - Http Version: 2.0, Http Status Code: OK


从Wireshark中可以看到已经创建了2个连接-每个连接都必须经过TLS设置;

.net-core - 您可以使用.Net Core HttpClient实现Http/2复用吗?-LMLPHP

如果HttpClient复用请求,我希望看到一个连接(1个端口,1个握手等)。

最佳答案

我想我有答案(尽管肯定会重视反馈);

我上面的代码的问题在于,HttpClient在有机会为request1创建TCP连接之前就已经收到了request2。因此,就HttpClient而言,不存在要进行多路复用的现有连接。

但是,如果我创建一个初始请求(下面的request0)并允许HttpClient打开连接,则后续请求(1和2)将使用该现有连接。

代码:

using (var httpClient = new HttpClient())
{
   // Setup first connection
   var request0 = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
   request0.Version = new Version(2, 0);

   var task0 = httpClient.SendAsync(request0);
   var response0 = task0.Result;

   Console.WriteLine($"Response 0 - Http Version: {response0.Version}, Http Status Code: {response0.StatusCode}");

   // Now send the multiplexed requests
   var request1 = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
   request1.Version = new Version(2, 0);

   var request2 = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
   request2.Version = new Version(2, 0);

   var task1 = httpClient.SendAsync(request1);
   var task2 = httpClient.SendAsync(request2);

   Task.WaitAll(task1, task2);

   var response1 = task1.Result;
   var response2 = task2.Result;

   Console.WriteLine($"Response 1 - Http Version: {response1.Version}, Http Status Code: {response1.StatusCode}");
   Console.WriteLine($"Response 2 - Http Version: {response2.Version}, Http Status Code: {response2.StatusCode}");
}


还有Wireshark证明(仅1个端口,1个握手):

.net-core - 您可以使用.Net Core HttpClient实现Http/2复用吗?-LMLPHP

我将继续进行进一步的研究,但这似乎是一个胜利者。如上所述,任何反馈都非常感谢。

09-25 16:07
查看更多