HTTP 2.0 原理

本文目的是学习HTTP 2.0的原理并研究其通信的详细细节 。
1. 二进制分帧层二进制分帧层 , 是HTTP 2.0性能增强的核心 。
HTTP 1.x在应用层以纯文本的形式进行通信 , 而HTTP 2.0将所有的传输信息分割为更小的消息和帧 , 并对它们采用二进制格式编码 。这样 , 客户端和服务端都需要引入新的二进制编码和解码的机制 。
如下图所示 , HTTP 2.0并没有改变HTTP 1.x的语义 , 只是在应用层使用二进制分帧方式传输 。

HTTP 2.0 原理

文章插图
 
因此 , 也引入了新的通信单位:
1.1 帧(frame)HTTP 2.0通信的最小单位 , 包括帧首部、流标识符、优先值和帧净荷等 。
HTTP 2.0 原理

文章插图
 
其中 , 帧类型又可以分为:
  • DATA:用于传输HTTP消息体;
  • HEADERS:用于传输首部字段;
  • SETTINGS:用于约定客户端和服务端的配置数据 。比如设置初识的双向流量控制窗口大小;
  • WINDOW_UPDATE:用于调整个别流或个别连接的流量
  • PRIORITY: 用于指定或重新指定引用资源的优先级 。
  • RST_STREAM: 用于通知流的非正常终止 。
  • PUSH_ PROMISE: 服务端推送许可 。
  • PING: 用于计算往返时间 , 执行“ 活性” 检活 。
  • GOAWAY: 用于通知对端停止在当前连接中创建流 。
标志位用于不同的帧类型定义特定的消息标志 。比如DATA帧就可以使用End Stream: true表示该条消息通信完毕 。流标识位表示帧所属的流ID 。优先值用于HEADERS帧 , 表示请求优先级 。R表示保留位 。
下面是Wireshark抓包的一个DATA帧:
HTTP 2.0 原理

文章插图
 
1.2 消息(message)消息是指逻辑上的HTTP消息(请求/响应) 。一系列数据帧组成了一个完整的消息 。比如一系列DATA帧和一个HEADERS帧组成了请求消息 。
1.3 流(stream)流是连接中的一个虚拟信道 , 可以承载双向消息传输 。每个流有唯一整数标识符 。为了防止两端流ID冲突 , 客户端发起的流具有奇数ID , 服务器端发起的流具有偶数ID 。
所有HTTP 2. 0 通信都在一个TCP连接上完成 ,  这个连接可以承载任意数量的双向数据流Stream 。相应地 ,  每个数据流以 消息的形式发送 ,  而消息由一 或多个帧组成 ,  这些帧可以乱序发送 ,  然后根据每个帧首部的流标识符重新组装 。
HTTP 2.0 原理

文章插图
 
二进制分帧层保留了HTTP的语义不受影响 , 包括首部、方法等 , 在应用层来看 , 和HTTP 1.x没有差别 。同时 , 所有同主机的通信能够在一个TCP连接上完成 。
2. 多路复用共享连接基于二进制分帧层 , HTTP 2.0可以在共享TCP连接的基础上 , 同时发送请求和响应 。HTTP消息被分解为独立的帧 , 而不破坏消息本身的语义 , 交错发送出去 , 最后在另一端根据流ID和首部将它们重新组合起来 。
我们来对比下HTTP 1.x和HTTP 2.0 , 假设不考虑1.x的pipeline机制 , 双方四层都是一个TCP连接 。客户端向服务度发起三个图片请求/image1.jpg , /image2.jpg , /image3.jpg 。
HTTP 1.x发起请求是串行的 , image1返回后才能再发起image2 , image2返回后才能再发起image3 。
HTTP 2.0 原理

文章插图
 
HTTP 2.0建立一条TCP连接后 , 并行传输着3个数据流 , 客户端向服务端乱序发送stream1~3的一系列的DATA帧 , 与此同时 , 服务端已经在返回stream 1的DATA帧
HTTP 2.0 原理

文章插图
 
性能对比 , 高下立见 。HTTP 2.0成功解决了HTTP 1.x的队首阻塞问题(TCP层的阻塞仍无法解决) , 同时 , 也不需要通过pipeline机制多条TCP连接来实现并行请求与响应 。减少了TCP连接数对服务器性能也有很大的提升 。
3. 请求优先级流可以带有一个31bit的优先级: