HTTP版本演进:第二回
续前文,本文将详细的介绍一下1.x版本的特性,主要就是1.1啦。
1.x版本的三个特点:
长连接管道化串行传输
长连接
1.0版本遵循的规则是:建立链路--发送请求--接收响应--断开链路。对于每一个请求而言,1.5个rtt(往返时延)是必须的。假使我们现在有n个请求,那么固定的时耗就是1.5 * n。那么1.1的重大改进,就是利用长连接,实现了多个请求共用一个TCP连接通道。这样除了第一个请求外,对于后面的每个请求,都能省去用于建立链路的1个rtt耗时,即:我们能够节省(n-1)次的rtt(往返时延)。这就是长连接带来的好处。
插个题外话:我们知道,c端在发送资源请求之前,需要通过三次握手建立连接链路,时间损耗,就用掉了1.5个往返,这里有个细节我之前一直没在意。就是发送资源请求的时间点与建立连接的那最后0.5的往返时刻是同时发生的,可以理解为,1.5的往返耗时,包含了请求时间,见下图:
同时,通过上图,也能看出,为什么1.1版本的改进影响巨大。著名案例就是苹果的工程师们针对itunes的改进,有兴趣自行谷歌。
但是,通过长连接虽然实现了公用tcp链路,我们发现了新的问题,因为规则仍然是第二个请求必须等待第一个请求的响应返回之后,才能发出。如此一来,当s端返回第一个请求的响应后直到第二个请求到达前的这段时间,都是处于空闲状态。这就叫c端的响应阻塞。我们希望的是,s端能够在处理完第一个请求发出响应后,立刻开始处理第二个请求,甚至,可以并行处理多个请求,怎么破?具体实践方法:管道化。
管道化。
1.1版本之前,每次请求都需要等待上次请求的响应返回才能发出,1.1版本开始实现了无需等待,对于c端的改动,就是无需等待串行发送请求,到达s端就是一个队列,s端能够挨个取出请求发出响应或者开启多线程并行处理,直至队列空。这样,能够一定程度上的充分利用s端的处理能力。这就是管道化。
共用一个tcp链路的情况下,c端先后发送html和css的请求。从图中发现,当s端返回html请求的响应后,一直处于空闲状态,直到css请求到达才开始处理。
**使用了管道化,c端串行发出请求,s端并行处理请求串行返回。理论上讲,通过长连接节省(n-1)个rtt基础上,再次节省了(n-1)个rtt。**
但是,由于http1.x协议本身的局限性,严格规定执行串行传输的策略,串型传输就是先进先出,对c端而言,请求必须依次发出。对s端而言即使后到的请求率先处理完成,也得等待。他不允许一个连接上的多个响应交错到达(多路复用)。这就导致了一个问题:倘若c端并行发送了两个请求:一个请求html,另一个请求了css。s端也能够并行的处理请求,css文件20ms完成,html40ms完成,那么在css完成的时候,她不能直接返回,而是要再等待20ms,即html请求处理完成后,再吧css的响应发出。想象一下,倘若html文件因为某种原因一直都是在处理的状态,那么后面的css响应就永远给不到c端,这就叫队首阻塞。
怎么破?
- 并行tcp发送请求。
- http2.0多路复用。
后文详解,敬请期待。
