一道经典的口试题是从 URL 在欣赏器被被输入到页面揭示的进程中产生了什么,大大都答复都是说请求响应之后 DOM 怎么被构建,被绘制出来。可是你有没有想过,收到的 HTML 假如包括几十个图片标签,这些图片是以什么方法、什么顺序、成立了几多毗连、利用什么协议被下载下来的呢?
要搞懂这个问题,我们需要先办理下面五个问题:
现代欣赏器在与处事器成立了一个 TCP 毗连后是否会在一个 HTTP 请求完成后断开?什么环境下会断开?
一个 TCP 毗连可以对应几个 HTTP 请求?
一个 TCP 毗连中 HTTP 请求发送可以一起发送么(好比一起发三个请求,再三个响应一起吸收)?
为什么有的时候刷新页面不需要从头成立 SSL 毗连?
欣赏器对同一 Host 成立 TCP 毗连到数量有没有限制?
先来谈谈第一个问题:现代欣赏器在与处事器成立了一个 TCP 毗连后是否会在一个 HTTP 请求完成后断开?什么环境下会断开?
在 HTTP/1.0 中,一个处事器在发送完一个 HTTP 响应后,会断开 TCP 链接。可是这样每次请求城市从头成立和断开 TCP 毗连,价钱过大。所以固然尺度中没有设定,某些处事器对 Connection: keep-alive 的 Header 举办了支持。
意思是说,完成这个 HTTP 请求之后,不要断开 HTTP 请求利用的 TCP 毗连。这样的长处是毗连可以被从头利用,之后发送 HTTP 请求的时候不需要从头成立 TCP 毗连,以及假如维持毗连,那么 SSL 的开销也可以制止,两张图片是我短时间内两次会见 github.com 的时间统计:
头一次会见,有初始化毗连和 SSL 开销
初始化毗连和 SSL 开销消失了,说明利用的是同一个 TCP 毗连
耐久毗连:既然维持 TCP 毗连长处这么多,HTTP/1.1 就把 Connection 头写进尺度,而且默认开启耐久毗连,除非请求中写明 Connection: close,那么欣赏器和处事器之间是会维持一段时间的 TCP 毗连,不会一个请求竣事就断掉。
所以第一个问题的谜底是:默认环境下成立 TCP 毗连不会断开,只有在请求报头中声明 Connection: close 才会在请求完成后封锁毗连。(具体文档见下面的链接)https://tools.ietf.org/html/rfc2616#section-8.1
第二个问题:一个 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。
正确的流水线实现是巨大的。