Differences between HTTP1.1 and HTTP2
前言
一次面试被问到http1.1和http2有什么区别,当时随便答了些跟keep-alive和upgrade相关的内容,从面试官的眼神里体会到了,我的回答应该差的还挺远的,查了下资料总结如下:
背景
http1.0协议1987年发布,后来www发展越来越普及,为了提高http1.0的传输效率,在1997年又公布了http1.1,主要提出了对一个tcp连接的复用,也就是熟知的connection: keep-alive特性。然而,为了进一步提高基于http协议的应用体验,比如越来越多的移动设备移动娱乐(图片、视频)的需求,google提出了spdy协议,就是为了进一步提高http的性能,提高用户体验。http2协议就是基于spdy,目前应该还是提案阶段。而且提出spdy的同期,google又提出了quic协议,quic提出了spdy中存在的各种问题及部分的解决方案,并提出基于udp方式模拟tcp的面向连接的方式。
Transmission Model
http1.1和http2的第一个不同在于传输模型的不同。
http1.0中,对于资源请求是一个request一个response,几乎所有tcp都是短链接(除非主动开启keepalive特性)。对于一个页面的请求,通常包含了很多资源,如果需要渲染一个包含多资源的页面,只是一应一答的方式,则需要重复建多个tcp连接,增加了资源开销。因此http1.1中,默认开放了keep-alive特性,多个资源的请求可以服用同一个tcp,降低了建链拆链的开销。这种方式被称为pipeline。pipeline的问题是,虽然tcp被服用了,但对资源的请求是串行的,如果排在前面的资源请求出现阻塞,则会影响后续的资源传输。这被称为HOL(head of line) blocking。如果为了解决这个问题,采用并行建多个tcp链接的策略,那么无论是客户端还是服务端,都面临更高的开销,尤其是对服务端而言,在并发连接数有上限的情况下则并发客户端服务数量就会大幅度降低。
http2采用了底层流技术,这个流技术对http上层的语义没有影响,只是在数据流的传输上,不再采用plain text这种方式。当一次请求中包含多个资源的请求时,将不同的资源映射到不同的二进制流上,每个流有唯一id,并且通过parent字段描述不同的流资源间的相互依赖关系。同时,每个流还可以指定优先级,优先级数字越大则优先应答。对于一个资源的数据,通过流传输时,数据被进一步划分成更小的单位,称为frame。在一个流通道中(流通道建立在tcp协议上),可以同时传输不同id的流,实现多个资源的并行,且资源传输的先后顺序可以有应用通过定义优先级的方式灵活定制。
flow control
第二个不同是在flowcontrol上的实现方式的改变。
对于客户端和服务端,本身都有一个buffer,用于缓存不完整的信息,待缓存中的信息完整后,一并处理。考虑如果有大资源需要传输时,可能就会发生buffer溢出,因此tcp协议中采用了滑动窗口的方式避免buffer溢出。接收端在接收数据,发送ack,在ack中可以上报本地buffer中尚存的空余空间,发送端可以根据上报的空余空间,调整 发送速率。一旦空余空间为0,则发送端停止发送。当接收端处理完buffer中的数据后,再请求发送端继续发送。http1.1的流控即依赖了tcp的滑动窗口实现。
由于http2.0提出了并行流的传输方式,它的flow control也是按流来约定的。这个约定被放到了应用层,即应用可以基于自身的buffer请求动态协商缓存大小。同时,在端到端传输过程中流经的中间节点也可以识别flow control参数,从而实现更好的流控。
Predicting Resource Requests
第三个不同是资源预请求策略的不同。
在一次页面的http请求中,为了渲染一个页面,除了需要请求html页面文件外,还需要请求css。http1.1中,如果预测到某些资源在后续的请求中必定会发送,就可以在第一的请求中将这部分资源一并应答给客户端,这种称为resource inlining。但这样的方式有一定问题,比如可能会重复应答客户端已有的资源,当被inline的资源非常大的情况下,对网络资源的浪费也非常大,所以在实际情况下,很少有应用这种方式的。
http2提出了叫server push的方式。如果预测到某些资源是可能会被后续请求的,则先向客户端推送一条PUSH_PROMISE帧,在这条帧中描述了即将推送过来的内容的元数据。如果客户端不需要某些资源,则可以应答一条RST_STREAM来取消某些资源。这样就避免了资源浪费。同时,客户端还可以发送SETTINGS
帧来改变server push的行为。
Compression
最后一个不同是压缩。http1.1只对消息体进行压缩,不对http header压缩,因为header一般很小。但是当请求量比较大时,header对网络带宽的开销也会增大。http2定义hpack的方式对header也进行了压缩,尤其是当两次请求或应答时头部仅有部分差异时,只传输差异部分。
Conclusion
以上是几个主要的不同点,如multiplexing, stream priorization, flow control, server push and compression。如果要了解http1.1和http2性能上的差异分析,可以参考 HTTP/2 – A Real-World Performance Test and Analysis,同时可以关注ietf关于http2协议的文档。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。