Appearance
HTTP2
要说到 HTTP2 就要想到 HTTP1.0 和 HTTP1.1, 在 HTTP1 中我们知道对于 HTTP 其存在很多缺点
1. 高延迟--带来页面加载速度的降低
其主要原因是: TCP 的对头阻塞(Head-Of-Line Blocking),导致带宽无法被充分利用
对头阻塞
什么是对头阻塞?
我们先看一个 HTTP1.1 管道化
HTTP1.1 管线化
HTTP 管线化是将多个 HTTP 要求(request)整批提交的技术,而在传送过程中不需先等待服务端的回应。管线化机制须通过永久连接(persistent connection)完成,仅 HTTP/1.1 支持此技术(HTTP/1.0 不支持),并且只有 GET 和 HEAD 要求可以进行管线化,而 POST 则有所限制。此外,初次创建连接时也不应启动管线机制,因为对方(服务器)不一定支持 HTTP/1.1 版本的协议。
浏览器将 HTTP 要求大批提交可大幅缩短页面的加载时间,特别是在传输延迟(lag/latency)较高的情况下(如卫星连接)。此技术之关键在于多个 HTTP 的要求消息可以同时塞入一个 TCP 分组中,所以只提交一个分组即可同时发出多个要求,借此可减少网络上多余的分组并降低线路负载。
连接特点
最初的串行请求: 第一次(TCP 的三次握手建立连接 -> 发送第一次的请求数据 -> 服务器返回响应数据 -> TCP 的四次挥手关闭连接) -> 第二次(TCP 的三次握手建立连接 -> 发送请求数据 -> 服务器返回响应数据 -> TCP 的四次挥手关闭连接) -> 第三次(TCP 的三次握手建立连接 -> 发送请求数据 -> 服务器返回响应数据 -> TCP 的四次挥手关闭连接)
在使用持久连接的情况下,某个连接消息的传递类似于
第一次(TCP 的三次握手建立连接 -> 发送请求数据 -> 服务器返回响应数据 ) -> 第二次(发送请求数据 -> 服务器返回响应数据 ) -> 第三次( 发送请求数据 -> 服务器返回响应数据 ) -> TCP 的四次挥手关闭连接
管线化:某个连接上的消息变成了类似这样
TCP 的三次握手建立连接 -> 发送第一次的请求数据-> 发送第二次的请求数据-> 发送第三次的请求数据 -> 服务器返回第二次请求的响应数据 -> 服务器返回第三次请求的响应数据 -> TCP 的四次挥手关闭连接
可见其特点
须通过永久连接(persistent connection)完成
只有 GET 和 HEAD 要求可以进行管线化,而 POST 则有所限制
缺点:
HTTP1.1 要求服务器端支持管线化,但并不要求服务器端也对响应进行管线化处理,只是要求对于管线化的请求不失败,而且现在很多服务器端和代理程序对管线化的支持并不好,现代浏览器 Chrome 和 Firefox 默认并未开启管线化支持。
管道化要求服务端按照请求发送的顺序返回响应(FIFO),原因很简单,HTTP 请求和响应并没有序号标识,无法将乱序的响应与请求关联起来。
客户端需要保持未收到响应的请求,当连接意外中断时,需要重新发送这部分请求。
上面 管道化要求服务端必须按照请求发送的顺序返回响应,那如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达。这就是 HTTP 的队头阻塞
2. 无状态特性--带来的巨大 HTTP 头部
由于报文 Header 一般会携带"User Agent""Cookie""Accept""Server"等许多固定的头字段(如下图),多达几百字节甚至上千字节,但 Body 却经常只有几十字节(比如 GET 请求、 204/301/304 响应),成了不折不扣的“大头儿子”
3. 明文传输--带来的不安全性
HTTP/1.1 在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
当然 HTTPS 解决了这个问题
4.不支持服务器推送消息
对于上面 HTTP1.X 的缺点,HTTP2 应运而生,由谷歌推出 SPDY,才算是正式改造 HTTP 协议本身。降低延迟,压缩 header 等等,SPDY 的实践证明了这些优化的效果,也最终带来 HTTP/2 的诞生。
HTTP2
二进制传输
Header 压缩
多路复用
Server Push
二进制传输
HTTP/1.x 的解析是基于文本的。基于文本协议的解析存在天然缺陷,文本的表现形式有多样性,要做到全面性考虑的场景必然很多。二进制则不同,只识别 0 和 1 的组合。基于这种考虑 HTTP/2.0 的协议解析采用二进制格式,方便且强大。
Header 压缩
HTTP/1.x 的请求和响应头部带有大量信息,而且每次请求都要重复发送,HTTP/2.0 使用 encoder 来减少需要传输的头部大小,通讯双方各自 cache 一份头部 fields 表,既避免了重复头部的传输,又减小了需要传输的大小。
多路复用
HTTP/2.0 支持多路复用,这是 HTTP/1.1 持久连接的升级版。多路复用,就是在一个 TCP 连接中可以存在多条流,也就是可以发送多个请求,服务端则可以通过帧中的标识知道该帧属于哪个流(即请求),通过重新排序还原请求。多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能。
Server Push
这里的服务端推送指把客户端所需要的 css/js/img 资源伴随着 index.html 一起发送到客户端,省去了客户端重复请求的步骤(从缓存中取)