Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you achieve Http/2 multiplexing with .Net Core HttpClient?

Summary

The Http/2 protocol provides the ability to multiplex multiple requests over a single connection. This allows for more efficient use of connections - see https://http2.github.io/faq/#why-is-http2-multiplexed

I would expect to be able to use the .Net Core HttpClient to achieve this. My test (based on the below) however indicate that there is a 1:1 ratio of request to TCP connections are made.

Is multiplexing supported under .Net Core HttpClient? And if so, how is it achieved?

Work so far

I have a sample app (repo can be found here, with the following code;

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}");
}

This code produces the following results (so I know Http/2 is being used);

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

I can see from Wireshark that 2 connections have been created - each having to go through TLS setup;

Wireshark Capture

If HttpClient was multiplexing the requests, I would expect see a single connection (1 port, 1 handshake, etc).

like image 892
Mark Taylor Avatar asked Dec 15 '17 10:12

Mark Taylor


People also ask

Does HttpClient support http2?

You can't use HTTP/2 with HttpClient in . NET Core 2.1 or 2.2, even if you explicitly set the version in the request.

What is http2 multiplexing?

Multiplexing in HTTP 2.0 is the type of relationship between the browser and the server that use a single connection to deliver multiple requests and responses in parallel, creating many individual frames in this process.

Does HTTP use multiplexing?

HTTP multiplexing is the re-use of established server connections for multiple clients connections. The best way to understand this feature is to compare non-multiplexing behavior to multiplexing behavior.


1 Answers

The problem with my code is that request2 is being received by the HttpClient BEFORE it has had a chance to create a TCP connection for request1. As such, as far as HttpClient is concerned, there is no existing connection to multiplex on.

If however, I create an initial request (request0 in the below) and allow HttpClient to open the connection, then the subsequent requests (1 & 2) use that existing connection.

The code:

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}");
}

And the Wireshark proof (only 1 port, 1 handshake):

Wireshark capture

like image 80
Mark Taylor Avatar answered Sep 29 '22 20:09

Mark Taylor