0、




在真正试图解决你的疑问的之前,我们来看一下,从发出request之前到接收respon之后,都发生了什么。

0.你向浏览器的地址栏输入一个域名.如 http://www.zhihu.com

1.浏览器向你的本地DNS服务器请求解析该域名,即将你的http://www.zhihu.com 解析为真实的IP地址.详细协议请查询RFC文档,其中对DNS协议的格式内容,指令意义,压缩算法,等都作出了规定。

2.拿到ip地址之后,发起TCP 握手(3次),详情请看计算机网络TCP协议部分

3.握手成功,构造request,即 HTTP 中request请求.并发送到目的地。有关HTTP协议的内容请查阅RFC文档可以购买HTTP权威指南作为参考和释疑.

4.服务器接受到一个完整的request(该边界的指定一般是conten-length,chunked也有),根据用户的request内容运算出相应的response。

5.服务器将response 沿着request建立的连接,向浏览器(客户端)发送数据。

5.5 keepalive的时候不关闭该连接,没有keepalive的时候发起tcp close,4次握手

6.浏览器根据接收到的response开始渲染页面。

至此,一个网页的打开过程完毕,我们从中提取出耗时的部分。

1.DNS查询时间(一来一回,走UDP协议) 网络IO

2.tcp 建立连接握手 网络IO

3.request构造时间(cpu运算)

4.request发送完毕时间(网络IO)

5.服务器接收request运算构造response(CPU运算,特指构造response过程中没有任何IO操作)

6.服务器发送response到客户端的时间(网络IO)

6.5 服务器关闭连接时间(IO)

7.客户端接收数据渲染页面时间(cpu运算)。

至此,一个流程就这样简单地构造完毕了


1、http 1.0:每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接。之后, 从1996年开始,很多HTTP/1.0浏览器与服务器都对协议进行了扩展,那就是“keep-alive”扩展协议。使用HTTP/1.0的客户端在首部中加上"Connection:Keep-Alive",请求服务端将一条连接保持在打开状态。服务端如果愿意将这条连接保持在打开状态,就会在响应中包含同样的首部。如果响应中没有包含"Connection:Keep-Alive"首部,则客户端会认为服务端不支持keep-alive,会在发送完响应报文之后关闭掉当前连接。

对于http 1.0,具有一些性能上的缺陷。




例如,一个包含有许多图像的网页文件中并没有包含真正的图像数据内容,而只是指明了这些图像的URL地址,当WEB浏览器访问这个网页文件时,浏览器首先要发出针对该网页文件的请求,当浏览器解析WEB服务器返回的该网页文档中的HTML内容时,发现其中的图像标签后,浏览器将根据标签中的src属性所指定的URL地址再次向服务器发出下载图像数据的请求。显 然,访问一个包含有许多图像的网页文件的整个过程包含了多次请求和响应,每次请求和响应都需要建立一个单独的连接,每次连接只是传输一个文档和图像,上一次和下一次请求完全分离。即使图像文件都很小,但是客户端和服务器端每次建立和关闭连接却是一个相对比较费时的过程,并且会严重影响客户机和服务器的性能。当一个网页文件中包含JavaScript文件,CSS文件等内容时,也会出现类似上述的情况。

同时,带宽和延迟也是影响一个网络请求的重要因素。在网络基础建设已经使得带宽得到极大的提升的当下,大部分时候都是延迟在于响应速度。基于此会发现,http1.0被抱怨最多的就是连接无法复用,和head of line blocking这两个问题。理解这两个问题有一个十分重要的前提:客户端是依据域名来向服务器建立连接,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个。显然连接数并不是越多越好,资源开销和整体延迟都会随之增大。连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。head of line blocking会导致带宽无法被充分利用,以及后续健康请求被阻塞。


2、http 1.1:HTTP/1.1采取持久连接的方式替代了Keep-Alive。HTTP/1.1的连接默认情况下都是持久连接。如果要显式关闭,需要在报文中加上Connection:Close首部。即在HTTP/1.1中,所有的连接都进行了复用。然而如同Keep-Alive一样,空闲的持久连接也可以随时被客户端与服务端关闭。不发送Connection:Close不意味着服务器承诺连接永远保持打开。HttpClient通过连接池来管理持久连接。

HTTP/1.1的KeepAlive就是串行的会话模式,一去一回,省掉的是TCP层面重复创建的成本。



在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。

3、多路复用代替原来的序列和阻塞机制,所有就是请求的都是通过一个 TCP 连接并发完成。



在 HTTP/2 中,有了二进制分帧之后,HTTP/2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2 中:

  • 同域名下所有通信都在单个连接上完成,同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应
  • 单个连接可以承载任意数量的双向数据流,单个连接上可以并行交错的请求和响应,之间互不干扰
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低

4、区别的原因:

原因是因为HTTP1.1 及更低版本的协议,并没有一个字段用来区分一个response是归属于哪一个request的。但HTTP 2 就有这个字段了。因此在HTTP1.1 及更低版本,你只能在发送一个request之后,等待response的到来。HTTP1.1 request和response 的无标识符问题(即response无法指明是哪一个request的),就造就了现在这种情况。HTTP 2 协议解除了这个问题。