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 tcptrack window shows 4 connections established. So the browser is opening different connection for image and css/js request.
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.
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);
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With