简单来讲,HTTP/2,是HTTP协议的第二个主要版本。HTTP/2是HTTP协议自1999年HTTP1.1发布后的首个更新,主要基于google的SPDY协议。 HTTP/2的特色是:在不改动HTTP语义、方法、状态码、URI及首部字段的状况下,大幅度提升了web性能。css
SPDY是谷歌研发的应用层协议,用户提高web性能。html
(Head-of-Line Blocking)
HTTP/2的请求再也不基于文本传输,具体方式为:在同一个域名下开启一个TCP connection
,每一个http请求以流(stream)的方式在此链接上传输,每一个stream是由若干帧(frame) 组成,frame是HTTP/2资源传输的最小单元,frame中的字段identifier
标识此帧属于哪个流,identifier相同的frame属于同一流,服务端将identifier相同的帧解析成可用数据。在这个TCP connection中,同时传输了多个流的帧数据,这就是HTTP/2的多路复用。ios
每个帧(frame) 都包含length、type、flags、stream identifier、frame playload等字段, 这里说下帧的type字段,在HTTP/2的标准中定义了10种不一样的帧type。web
frame的PRIORITY字段用于标识流的权重(1-256)和依赖关系,以正确的顺序请求资源对于用户体验相当重要。浏览器
服务器根据依赖关系和权重进行带宽分配,高优先级的资源得到更多的带宽。缓存
权重的大致规则不外乎 根文档 - 样式文件 - 字体文件 - 脚本文件 - 背景图 - 图标文件 - 图片。 不一样的浏览器规则会有所差别。安全
ios中浏览器的资源权重参考:服务器
ps: 服务端对于高优先级的资源的策略是分配更多的带宽,可是不会保证此资源必定会优先返回,这是为了不
线头阻塞
。cookie
多路复用让http请求变得廉价,建立一个新流的成本很低,理论上能够同时发起无限个请求,不过咱们能够在stream的SETTINGS字段上设置SETTINGS_MAX_CONCURRENT_STREAMS用于限制最大并发数。网络
HTTP1.x中,咱们经过将重要的js代码或者css样式代码嵌入html页面中,让页面能够快速响应,可是内嵌代码最大的弊端是没法缓存。哪怕只是修改一个小样式也必须下载整个文件。
这也是其它资源整合的共同弊端,如图片以base64的方式嵌入代码、CSS精灵图(sprite)等,每当修改了精灵图中的一个小图,咱们不得不从新下载整张精灵图。
HTTP/2容许服务端主动推送资源,当TCP connection创建后,服务器能够主动推送资源而非客户端发起请求,服务端推送是基于frame的PUSH_PROMISE字段来实现的。并且服务端push的资源是能够被缓存的。
关于服务端推送一个常见的问题是若是客户端已经有一份缓存了怎么办?
浏览器能够经过PUSH_PROMISE字段判断资源是否已经缓存,而后经过发送RST_STREAM帧用于终止推送。在这个过程当中,服务端只是推送了资源的地址,并无直接推送资源的实体,这样的目的也是为了减小没必要要的资源传输。
HTTP/2规定,由客户端发起的流的ID(stream identifier)都是奇数,由服务端发起的流ID是偶数。
HTTP/2其实是对HTTP1的一个数据封装,本质上没有改变HTTP1的语义,状态码、URI 以及header字段等。
要实现对HTTP1的封装,HTTP/2在传输层(TCP, UDP 或者SSL/TSL安全协议层)和应用层之间新增一个二进制分帧层,在分帧层中,HTTP/2将全部信息分割成帧(frame),其中原http header信息被封装到 HEADER 类型的帧中,内容被封装到DATA类型的帧中。
二进制分帧是多路复用,头部信息压缩,服务端推送, 流量控制等HTTP/2功能的基础。
在HTTP1.x中,HTTP协议都是由状态行,消息头,主体构成,在传输过程当中,主体内容通常都是通过gzip压缩,或者传说的自己就是二进制流(视频,图片)等,而消息头和状态行都是纯文本传输的。
并且不少消息头中的字段冗余如 COOKIE,UserAgent等,浪费了大量带宽,增长了网络延时。不少时候请求消息头的大小甚至超过了主体内容的大小。
HTTP/2经过维护静态字典和动态字典的方式来压缩首部
1:对于静态字典中匹配的头部名称或头部名称和值的组合,可使用一个字符表示,如创建链接时:
method:GET 可使用 1表示 (彻底匹配)
cookeie: xxx 可使用 2:xxx表示 (头部匹配)
复制代码
2:同时将cookeie: xxx加入动态字典中,这样后续的整个cookie键值对均可以使用一个字符表示:
cookeie: xxx 可使用 3表示 (加入到动态字典)
复制代码
3:对于静态字典和动态字典中都不存在的内容,使用了哈夫曼(霍夫曼)编码来压缩体积。
不是全部的头部信息均可以被添加到动态字典中,这时就是使用哈夫曼编码压缩的场景。
HTTP1中的状态行信息如Status等在2.0中都以键值对的方式放入头部中,作为消息头的一部分。
动态字典会在每一个TCP链接上维护一个,且动态字典的内容是根据请求量逐渐累积的。 因此在HTTP/2的网站中,咱们须要作的再也不是整合资源和散列域名了。而是分散资源和使用一个链接,如下两种状况下浏览器会使用一个链接: