hello2dj

if you can't explain it simply, you don't understand it well enough

http2

  • 支持请求与响应的多路复用来减少延迟。

  • 压缩 HTTP 首部字段将协议开销降至最低。

  • 增加对请求优先级和服务器端推送的支持。

    同时由于考虑到庞大的 HTTP1.1 协议用户,所以 HTTP 方法、状态码、URI 及首部字段,等核心概念保持不变,也就是当前正在运行的网站不用做任何改变即可在 HTTP2 协议上运行。

  • 二进制分帧层:

  • 流、消息和帧:

    二进制分帧机制改变了客户端与服务器之间交互数据的方式,涉及到以下几个重要的概念:

  1. 流:已建立的 TCP 连接上的双向字节流,逻辑上可看做一个较为完整的交互处理单元,即表达一次完整的资源请求-响应数据交换流程;一个业务处理单元,在一个流内进行处理完毕,这个流生命周期完结。

  2. 消息:由一个或多个帧组合而成,例如请求和响应。

  3. 帧:HTTP2 通信的最小单位,每个帧包含帧首部,至少也会标识出当前帧所属的流。所有 HTTP2 通信都在一个连接上完成,此连接理论上可以承载任意数量的双向数据流。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。图示如下:

    HTTP2 的所有帧都采用二进制编码,所有首部数据都会被压缩。上图只是演示数据流、消息和帧之间的关系,而非实际传输时的编码结果。

  • 多向请求与响应:

    在 HTTP1.1 中,如果想使用多个并行 request 请求,必须多开 TCP 连接,但是一个域名对同一个浏览器客户端是有数量限制的(6 个左右),同时,每一个连接中的响应是按照顺序排队进行的,容易导致队头堵塞。

二进制分帧层实现了多向请求和响应,客户端和服务器可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。图示如下:

由上图可以看出,同一个 TCP 连接可以传输多个数据流,并且服务器到客户端方向有多个数据流,流是一个逻辑信道,所以属于它的帧可以乱序发送,最后再根据标记组合起来即可。把 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP2 最重要的改进,带来了巨大的性能提升,主要因为如下几个原因:

  1. 可以并行交错地发送请求,请求之间互不影响。
  2. 可以并行交错地发送响应,响应之间互不干扰。
  3. 只使用一个连接即可并行发送多个请求和响应。
  4. 消除不必要的延迟,从而减少页面加载的时间。

二进制分帧机制解决了 HTTP1.1 队头阻塞问题,也消除了并行处理和发送请求及响应时对多个 TCP 连接的依赖

  • 请求优先级:

    每个流都包含一个优先级,用来告诉对端哪个流更重要,当资源有限的时候,服务器会根据优先级来选择应该先发送哪些流。HTTP2 中,每个请求都可以带一个 31bit 的优先值,0 表示最高优先级。数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

  • 服务器推送:

    当前 web 页面的功能越来越强大,排版越来越精美,所以需要引用的 js 文件、css 文件或者图片等内容也越来越多,对每一个资源的外部引用,都是一次 request 请求。在 HTTP1.1 中,由于不具有多向请求与响应,所以可能需要额外的 TCP 连接,甚至导致队头堵塞,HTTP1.1 对此问题的解决方案可以参阅 HTTP 请求延迟解决方案一章节。当客户端获取服务器发送来的文档之后,通过分析获知需要引入额外的资源,然后再向服务器发送请求获取这些资源,如此大费周章,倒不如服务器主动推送这些额外资源。推送资源的特点如下:

  • 客户端可以缓存推送过来的资源。

  • 客户端可以拒绝推送过来的资源。

  • 推送资源可以由不同的页面共享。

  • 服务器可以按照优先级推送资源。

  • 首部压缩:

    在 HTTP1.1 中,每次请求或者响应都会发送一组首部信息,同时这些信息都是以文本形式发送,如果带有 cookie 信息的话,那么发送首部信息就是一份相当大的额外开销。为减少这些开销并提升性能,HTTP2 会压缩首部元数据,HTTP2 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键/值对,对于相同的数据,不再通过每次请求和响应发送,首部表在 HTTP2 的连接存续期内始终存在,由客户端和服务器共同渐进地更新。

http1 的一个问题