关于http:灵魂一问一个TCP连接可以发多少个HTTP请求

52次阅读

共计 3157 个字符,预计需要花费 8 分钟才能阅读完成。

一道经典的面试题是从 URL 在浏览器被输出到页面展示的过程中产生了什么,大多数答复都是说申请响应之后 DOM 怎么被构建,被绘制进去。

然而你有没有想过,收到的 HTML 如果蕴含几十个图片标签,这些图片是以什么形式、什么程序、建设了多少连贯、应用什么协定被下载下来的呢?

要搞懂这个问题,咱们须要先解决上面五个问题:

1. 古代浏览器在与服务器建设了一个 TCP 连贯后是否会在一个 HTTP 申请实现后断开?什么状况下会断开?

2. 一个 TCP 连贯能够对应几个 HTTP 申请?

3. 一个 TCP 连贯中 HTTP 申请发送能够一起发送么(比方一起发三个申请,再三个响应一起接管)?

4. 为什么有的时候刷新页面不须要从新建设 SSL 连贯?

5. 浏览器对同一 Host 建设 TCP 连贯到数量有没有限度?

先来谈谈第一个问题:古代浏览器在与服务器建设了一个 TCP 连贯后是否会在一个 HTTP 申请实现后断开?什么状况下会断开?

在 HTTP 1.0 中,一个服务器在发送完一个 HTTP 响应后,会断开 TCP 连贯。然而这样每次申请都会从新建设和断开 TCP 连贯,代价过大。

所以尽管规范中没有设定,某些服务器对 Connection: keep-alive 的 Header 进行了反对。

意思是说,实现这个 HTTP 申请之后,不要断开 HTTP 申请应用的 TCP 连贯。

这样的益处是连贯能够被从新应用,之后发送 HTTP 申请的时候不须要从新建设 TCP 连贯,以及如果维持连贯,那么 SSL 的开销也能够防止,两张图片是我短时间内两次拜访 Github.com 的工夫统计:

头一次拜访,有初始化连贯和 SSL 开销,总耗时 1.05s

初始化连贯和 SSL 开销隐没了,阐明应用的是同一个 TCP 连贯
耗时减小到 440.90ms

长久连贯:既然维持 TCP 连贯益处这么多,HTTP 1.1 就把 Connection 头写进规范,并且默认开启长久连贯。

除非申请中写明 Connection:close,那么浏览器和服务器之间是会维持一段时间的 TCP 连贯,不会一个申请完结就断掉。

所以第一个问题的答案是:默认状况下建设 TCP 连贯不会断开,只有在申请报头中申明 Connection:close 才会在申请实现后敞开连贯。

具体文档见上面的链接:
https://tools.ietf.org/html/r…

第二个问题:一个 TCP 连贯能够对应几个 HTTP 申请?

理解了第一个问题之后,其实这个问题曾经有了答案,如果维持连贯,一个 TCP 连贯是能够发送多个 HTTP 申请的。

第三个问题:一个 TCP 连贯中 HTTP 申请发送能够一起发送么(比方一起发三个申请,再三个响应一起接管)?

HTTP 1.1 存在一个问题,单个 TCP 连贯在同一时刻只能解决一个申请,意思是说:两个申请的生命周期不能重叠,任意两个 HTTP 申请从开始到完结的工夫在同一个 TCP 连贯里不能重叠。

尽管 HTTP 1.1 标准中规定了 Pipelining 来试图解决这个问题,然而这个性能在浏览器中默认是敞开的。

先来看一下 Pipelining 是什么,RFC 2616 中规定了:
A client that supports persistent connections MAY“pipeline”its requests (i.e., send multiple requests without waiting for each response). A server MUST send its responses to those requests in the same order that the requests were received.

一个反对长久连贯的客户端能够在一个连贯中发送多个申请(不须要期待任意申请的响应)。收到申请的服务器必须依照申请收到的程序发送响应。

至于规范为什么这么设定,咱们能够大略揣测一个起因:因为 HTTP 1.1 是个无状态的文本协定,同时返回的内容也并不能辨别对应于哪个发送的申请,所以程序必须维持统一。

比方你向服务器发送了两个申请 GET /query?q=A 和 GET /query?q=B,服务器返回了两个后果,浏览器是没有方法依据响应后果来判断响应对应于哪一个申请的。

Pipelining 这种构想看起来比拟美妙,然而在实践中会呈现许多问题:

  • 一些代理服务器不能正确的解决 HTTP Pipelining。
  • 正确的流水线实现是简单的。
  • Head-of-line Blocking 队头阻塞:在建设起一个 TCP 连贯之后,假如客户端在这个连贯间断向服务器发送了几个申请。

依照规范,服务器应该依照收到申请的程序返回后果,假如服务器在解决首个申请时破费了大量工夫,那么前面所有的申请都须要等着首个申请完结能力响应。

所以古代浏览器默认是不开启 HTTP Pipelining 的。

然而,HTTP2 提供了 Multiplexing 多路复用传输个性,能够在一个 TCP 连贯中同时实现多个 HTTP 申请。至于 Multiplexing 具体怎么实现的就是另一个问题了。

咱们能够看一下应用 HTTP2 的成果:

绿色是发动申请到申请返回的等待时间,蓝色是响应的下载工夫,能够看到都是在同一个 Connection,并行实现的。

所以这个问题也有了答案:在 HTTP 1.1 存在 Pipelining 技术能够实现这个多个申请同时发送,然而因为浏览器默认敞开,所以能够认为这是不可行的。

在 HTTP2 中因为 Multiplexing 特点的存在,多个 HTTP 申请能够在同一个 TCP 连贯中并行进行。

那么在 HTTP 1.1 时代,浏览器是如何进步页面加载效率的呢?次要有上面两点:

  • 维持和服务器曾经建设的 TCP 连贯,在同一连贯上程序解决多个申请。
  • 和服务器建设多个 TCP 连贯。

第四个问题:为什么有的时候刷新页面不须要从新建设 SSL 连贯?

在第一个问题的探讨中曾经有答案了,TCP 连贯有的时候会被浏览器和服务端维持一段时间。TCP 不须要从新建设,SSL 天然也会用之前的。

第五个问题:浏览器对同一 Host 建设 TCP 连贯到数量有没有限度?

假如咱们还处在 HTTP 1.1 时代,那个时候没有多路传输,当浏览器拿到一个有几十张图片的网页该怎么办呢?

必定不能只开一个 TCP 连贯程序下载,那样用户必定等的很好受,然而如果每个图片都开一个 TCP 连贯发 HTTP 申请,那电脑或者服务器都可能受不了。

要是有 1000 张图片的话总不能开 1000 个 TCP 连贯吧,你的电脑批准 NAT 也不肯定会批准。

所以答案是:有。Chrome 最多容许对同一个 Host 建设六个 TCP 连贯。不同的浏览器有一些区别。
https://developers.google.com…

那么回到最开始的问题,收到的 HTML 如果蕴含几十个图片标签,这些图片是以什么形式、什么程序、建设了多少连贯、应用什么协定被下载下来的呢?

如果图片都是 HTTPS 连贯并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器磋商能不能用 HTTP2,如果能的话就应用 Multiplexing 性能在这个连贯上进行多路传输。

不过也未必会所有挂在这个域名的资源都会应用一个 TCP 连贯去获取,然而能够确定的是 Multiplexing 很可能会被用到。

如果发现用不了 HTTP2 呢?或者用不了 HTTPS(事实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能应用 HTTP 1.1)。

那浏览器就会在一个 Host 上建设多个 TCP 连贯,连贯数量的最大限度取决于浏览器设置,这些连贯会在闲暇的时候被浏览器用来发送新的申请,如果所有的连贯都正在发送申请呢?那其余的申请就只能等等了。

作者:松若章
出处:https://zhuanlan.zhihu.com/p/…

欢送关注我的微信公众号「码农解围」,分享 Python、Java、大数据、机器学习、人工智能等技术,关注码农技术晋升•职场解围•思维跃迁,20 万 + 码农成长充电第一站,陪有幻想的你一起成长

正文完
 0