使用从chrome到node-http2服务器的HTTP / 2时,请参阅多个TCP连接

更新(对于任何对结果感兴趣的人:)

我无法弄清为什么chrome和node-http2服务器之间的下一个协议协商失败。 我的怀疑是自签名证书或ALPN / NPN支持问题。 所以我搬到了golang HTTP / 2的实现 。 相同的设置完美地工作,我看到单个多路复用的TCP连接(铬 – > golang)


我一直在阅读关于HTTP / 2的知识,以及它如何通过每个主机的单个多路复用TCP连接来解决HTTP / 1.1的延迟问题,所以我决定尝试一下。

本实验

  • 创build一个简单的HTML文件,引用一个CSS,一个JS和几个图像。
  • Node.js中的一个简单的http服务器,它提供所有这些文件
  • 使用chrome发出http请求
  • 在Ubuntu上使用tcptrack( tcptrack )来跟踪到http服务器的TCP连接。

tptrack窗口显示build立了4个连接。 所以浏览器打开不同的连接图像和CSS / JS请求。

Tcp跟踪来自chrome的http / 1.1请求的输出

我使用tcpdump获得类似的输出。 供参考使用的tcptrack命令是

tcptrack -d -i eth0 -r 3600端口8989

而tcpdump也显示类似的输出

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

服务这些文件的简单的一台http服务器就像下面这样(相关的代码)

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

在此之后,我尝试使用http / 2。

  • 启用chrome标志发送http / 2请求
  • 使用node-http2创build一个http / 2服务器
  • 简单的http服务器具有与http / 1.1相同的代码,只是它使用在步骤2中安装的http2服务器模块。
  • 使用chrome进行请求(它需要与HTTP / 2规范内联的https请求)
  • 捕获的tcptrack / tcpdump输出

http / 2的tcptrack输出

所以,这仍然显示多个TCP连接。 另外,如果我增加了html中图片的数量,连接数量就会增加。

所以我不确定如何阅读这个。 这是HTTP / 2如何performance(或这是一个铬错误)? 有没有更好的方法来使用简单的http / 2客户端服务器可视化HTTP / 2收益?

注意:我为HTTP / 2服务器使用自签名证书,所以chrome在进入页面之前会抛出一个警告,可能这些closures的连接表示它,但我不认为它会影响页面及其组件是如何被协议请求的

感谢大家的耐心阅读,并感谢任何build议。

msingh

PS:Wireshark TCP捕获也不例外。 只是我发现难以隔离Wireshark的stream量,所以使用tcpdump和tcptrack。

更新:更新:查看chrome:// net-internals / HTTP / 2请求协商失败,它回退到使用HTTP / 1.1。 还不明白原因。

铬内部工具事件显示

 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 

下一个协议的值是http / 1.1(next_proto_status和proto)。 但是这并没有说明导致这次倒退的谈判失败了吗? 可以自签名证书是原因吗?

HTTP / 2服务器代码

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

我怀疑你实际上没有使用HTTP / 2。 有一个FF的插件,我想为Chrome浏览器的一些选项,显示您在地址栏中使用的协议。

请注意,HTTP2会通过许多方法为您提供更低的延迟。

单一的连接本身不会给你太多改善的延迟最初,至less不会直到stream量控制窗口增加。 单一连接的关键在于,它可以将窗口扩大到最佳尺寸,并且不会为创build的每个新连接获得缓慢的启动延迟。

但HTTP / 2也有一个推送机制,服务器可以知道CSS,JS和图像与页面相关联,并主动将它们推送到客户端,同时请求获取html。 这节省了往返时间来parsingHTML,然后发送新的请求。 如果资源数量超过6个(HTTP1事实上的连接限制),则会节省更多的往返行程。

我们在我们的网站上运行Jetty HTTP2,并在https://webtide.com/http2-tests/push/上提供了一个演示页面

该图像是由很多小图片构成的,您可能会看到单独使用HTTP / 1加载的情况,但是如果您使用HTTP / 2加载为块