Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

See multiple TCP connections when using HTTP/2 from chrome to node-http2 server

UPDATE (for anyone interested in the outcome :)

I wasn't able to figure out why next protocol negotiation between chrome and node-http2 server fails. My suspicion was self signed certificate or ALPN/NPN support issue. So I moved to golang HTTP/2 implementation. The same setup works perfectly and I see single mutliplexed TCP connection (chrome --> golang)


I have been reading about HTTP/2 and how it solves the latency issue with HTTP/1.1 with single multiplexed TCP connection per host so I decided to try it out.

The experiment

  • created a simple html file with references to one css, one js and couple of images.
  • A simple http server in Node.js which serves all these files
  • Used chrome to make a http request
  • Used tcptrack on Ubuntu (tcptrack) to track TCP connections being made to the http server.

The tcptrack window shows 4 connections established. So the browser is opening different connection for image and css/js request.

Tcp track output for http/1.1 request from chrome

I get similar output using tcpdump. For reference tcptrack command used was

tcptrack -d -i eth0 -r 3600 port 8989

and tcpdump also shows similar output

tcpdump -i eth0 -nns 0 "dst port 8989 and tcp[tcpflags] == tcp-syn"

The simple all in one http server serving these files was something like below (relevant code)

(function(){
  ...........
  var server = http.createServer(function(request, response) {
      ..........
      fs.readFile(filetoRet, function (err,data) {
      if(filePath.indexOf(".jpg") >-1){
        response.writeHead(200, {"Content-Type": "image/jpg"});
      }.....
      
      response.write(data);
      response.end();
      });

   
  });
   

  server.listen(8989);  
})()

After this I tried using http/2.

  • Enabled chrome flag to send http/2 request
  • Created a http/2 server using node-http2
  • The simple http server has the same code as http/1.1 except that it uses http2 server module installed in step 2.
  • Made the request using chrome (It needed to be an https request inline with HTTP/2 spec)
  • Captured tcptrack/tcpdump output

tcptrack output for http/2

So, this still shows multiple TCP connections being made. Also if I increase the number of images in the html, the number of connections increases.

So I am not sure how to read this. Is this how HTTP/2 should behave (or is this a chrome bug)? Is there a better way to visualize the HTTP/2 gains using a simple http/2 client server?

Note:I am using self signed certificate for the HTTP/2 server so chrome throws a warning before proceeding to the page and possibly those closed connections represent it but I don't think it should impact how the page and its components are requested by protocol

Thanks for everyone's patience in reading this and appreciate any suggestions.

msingh

P.S : Wireshark TCP capture is no different. Just that I found it harder to isolate the traffic in Wireshark so used tcpdump and tcptrack.

Update: update: Looking at chrome://net-internals/ the HTTP/2 request negotiation fails and it falls back to using HTTP/1.1. Don't understand the reason yet.

The chrome internal tool events show

t=879052 [st= 0] +HTTP_STREAM_JOB  [dt=19]
                  --> original_url = "https://msinghlinux.ads.com:8900/"
                  --> priority = "HIGHEST"
                  --> url = "https://msinghlinux.ads.com:8900/"
t=879052 [st= 0]   +PROXY_SERVICE  [dt=0]
t=879052 [st= 0]      PROXY_SERVICE_RESOLVED_PROXY_LIST
                      --> pac_string = "DIRECT"
t=879052 [st= 0]   -PROXY_SERVICE
t=879052 [st= 0]   +HOST_RESOLVER_IMPL_REQUEST  [dt=0]
                    --> address_family = 0
                    --> allow_cached_response = true
                    --> host = "msinghlinux.ads.com:8900"
                    --> is_speculative = false
t=879052 [st= 0]      HOST_RESOLVER_IMPL_CACHE_HIT
t=879052 [st= 0]   -HOST_RESOLVER_IMPL_REQUEST
t=879052 [st= 0]   +SOCKET_POOL  [dt=19]
t=879071 [st=19]      SOCKET_POOL_BOUND_TO_CONNECT_JOB
                      --> source_dependency = 26961 (CONNECT_JOB)
t=879071 [st=19]      SOCKET_POOL_BOUND_TO_SOCKET
                      --> source_dependency = 26967 (SOCKET)
t=879071 [st=19]   -SOCKET_POOL
t=879071 [st=19]    HTTP_STREAM_REQUEST_PROTO
                    --> next_proto_status = "negotiated"
                    --> proto = "http/1.1"
t=879071 [st=19]    HTTP_STREAM_JOB_BOUND_TO_REQUEST
                    --> source_dependency = 26910 (URL_REQUEST)
t=879071 [st=19] -HTTP_STREAM_JOB

The value of next protocol is http/1.1 (next_proto_status and proto). But it doesn't say what failed in the negotiation that caused this fallback? Can the self signed certificate be the reason?

HTTP/2 Server code

var options = {
  key: fs.readFileSync('./server.key'),
  cert: fs.readFileSync('./server.crt')
};

options.log = bunyan.createLogger(...);
require('http2').createServer(options,function(request, response) {
      .... same code as http/1.1 server


}).listen(8900);
like image 212
factotum Avatar asked Apr 27 '15 01:04

factotum


People also ask

Does HTTP use multiple TCP connections?

In one of the pairs of protocols given below, both the protocols can use multiple TCP connections between the same client and the server. Which one is that? Explanation: HTTP may use different TCP connection for different objects of a webpage if non-persistent connections are used.

How many parallel TCP connections does HTTP 2 use for a single domain?

This allows at most 6-8 concurrent requests per domain. With HTTP/2, browsers open only 1 connection per domain. However, thanks to the multiplexing feature of the HTTP/2 protocol, the number of concurrent requests per domain is not limited to 6-8, but it is virtually unlimited.

How many TCP connections does HTTP use?

Why just one TCP connection? With HTTP/1, browsers open between four and eight connections per origin. Since many sites use multiple origins, this could mean that a single page load opens more than thirty connections.

Does Chrome use http2?

HTTP/2 protocol is Not Supported on Google Chrome 27. If you use HTTP/2 protocol on your website or web app, you can double-check that by testing your website's URL on Google Chrome 27 with LambdaTest.


1 Answers

I suspect that you are not actually using HTTP/2. There is a plugin for FF and I think some option for Chrome that shows you the protocol used in the address bar.

Note that HTTP2 will give you lower latency via a number of methods.

The single connection itself is not going to give you too much improved latency initially, at least not until it's flow control window increases. The point of the single connection is that it can grow it's window to optimal size and you stop getting slow start delays for each new connection created.

But HTTP/2 also has a push mechanism, where the server can know that the CSS, JS and images are associated with a page and proactively push them to the client along with a request to get the html. This saves on the round trip times to parse the HTML and then send new requests. Even more round trips are saved if the number of resources is more than 6 (the HTTP1 defacto connection limit).

We are running Jetty HTTP2 on our website and we have a page that demos push at https://webtide.com/http2-tests/push/

That image is made from many small images, which you tend to see load individually with HTTP/1, but they load as a block if you use HTTP/2

like image 129
gregw Avatar answered Nov 15 '22 00:11

gregw