• 连接Connection:1个TCP连接,包含一个或者多个Stream
  • 数据流Stream:一个双向通讯数据流,包含一条或者多条Message
  • 消息Message:对应HTTP/1中的请求或者响应,包含一条或者多条Frame
  • 数据帧Frame:最小单位,以为禁止压缩格式存放HTTP/1中的内容

HTTP2基本概念 - 图1

Stream ID 的作用

实现多路复用的关键

  • 接收端的实现可据此并发组装消息
  • 同一Stream内的frame必须是有序的(无法并发)
  • SETTING_MAX_CONNECTION_STREAMS控制着并发Stream数

HTTP2基本概念 - 图2

推送依赖性请求的关键

  • 由客户端建立的流必须是奇数
  • 由服务器端建立的流必须是偶数

image.png

流状态管理的约束性规定

  • 新建立的流ID必须大于曾经建立过的状态为opened或者reserved的流ID
  • 在新建立的流上发送帧时,意味着更小ID且为idle状态的流置为closed状态
  • StreamID不能复用,长连接耗尽ID应创建新连接

    应用层流控仅影响控制帧

  • StreamID为0的流仅用于传输控制帧

  • 在HTTP/1升级到h2c中,以ID为1流返回响应,之后流进入half-closed(local)状态

帧格式:帧类型及设置帧的子类型

image.png

9字节标准帧头部:帧长度

  • 0至2^14 (16384)- 1
    • 所有实现必须可以支持16KB以下的帧
  • 2^14(16384)至 2^24 - 1 (16777215)
    • 传递16KB到16MB的帧时,必须接受端首先公布自己可以处理此大小
    • 通过SETTINGS_MAX_FRAME_SIZE帧(Identifier = 5)告知 (SETTING帧)

      帧类型

      | 帧类型 | 类型编码 | 用途 | | —- | —- | —- | | DATA | 0x0 | 传递HTTP包体 | | HEADERS | 0x1 | 传递HTTP头部 | | PRIORITY | 0x2 | 指定Stream流的优先级 | | RST_STREAM | 0x3 | 终止Stream流 | | SETTINGS | 0x4 | 修改连接或者Stream流的配置 | | PUSH_PROMISE | 0x5 | 服务端推送资源时描述请求的帧 | | PING | 0x6 | 心跳检测,兼具计算RTT往返时间的功能 | | GOAWAY | 0x7 | 优雅的终止连接或者通知错误 | | WINDOW_UPDATE | 0x8 | 实现流量控制 | | CONTINUATION | 0x9 | 传递较大HTTP头部时的持续帧 |

Setting设置帧格式(type=0x4)

  • 设置帧并不是“协商”, 而是发送方向接受方通知其特性、能力
  • 一个设置帧可同时设置多个对象
  • Identifier:设置对像
  • Value:设置值

image.png
image.png

  • 设置类型

    • SETTING_HEADER_TABLE_SIZE(0x1):通知对端索引表的最大尺寸(单位字节,初识4096字节)
    • SETTING_ENABLE_PUSH(0x2):value设置为0时可禁用服务器推送功能,1表示启用推送功能
    • SETTING_MAX_CONCURRENT_STREAMS(0x3):告诉接收端允许的最大并发流数量
    • SETTING_INITAL_WINDOW_SIZE(0x4):声明发送端的窗口大小,用于Stream级别的流控,初识值2^16-1(65535)
    • SETTING_MAX_FRAME_SIZE(0x5):设置帧的最大大小,初始值2^14(16384)
    • SETTING_MAX_HEADER_LIST_SIZE(0x6):知会对端头部索引表的最大尺寸,单位字节,基于未压缩的头部

      服务端的主动消息推送

      服务端推送的价值

  • 提前将资源推送至浏览器缓存

  • 特性:推送可以基于已经发送的请求,例如客户端请求html,主动推送js文件
  • 实现方式:

    • 推送资源必须对应一个请求
    • 请求由服务端PUSH_PROMISE帧发送
    • 响应在偶数ID的STREAM中发送

      实现方式

  • PUSH_PROMISE

    • 在stram1中通知客户端CSS资源即将来临
    • 在Stream2中发送CSS资源(Stream1和2可以并发)

image.png

PUSH帧的格式

  • PUSH_PROMISE帧,type=0x5,只能由服务端发送

image.png

PUSH推送模式的禁用

  • SETTINGS_ENABLE_PUSH

    • 1 表示启用推送功能
    • 0 表示禁用推送功能

      Stream的状态变迁

  • 帧符号

    • H: HEADERS帧
    • PP: PUSH_PROMISE帧
    • ES: END_STREAM标志位
    • R: RES_STREAM帧
  • 流状态
    • idel: 起始状态
    • closed:关闭
    • open:可以发送任何帧
    • half closed 单向关闭
      • remote: 不再接受数据帧
      • local:不能再发送数据帧
    • reserved
      • remote
      • local

image.png

RST_STREAM帧(type=0x3)

  • HTTP2多个流共享同一连接,RST帧允许立刻终止一个未完成的流
  • RST_STREAM帧不使用任何flag
  • RST_STREAM帧的格式

image.png

常见错误码

  • NO_ERROR(0x0):没有错误。GOAWAY帧优雅关闭连接时可以使用此错误码
  • PROTOCOL_ERROR(0x1):检测到不识别的协议字段
  • INTERNAL_ERROR(0x2):内部错误
  • FLOW_CONTROL_ERROR(0x3):检测到对端没有遵守流控策略
  • SETTING_TIMEOUT(0x4):某些设置帧发出后需要接收端应答,在期待时间内没有得到应用则由此错误码表示
  • STREAM_CLOSED(0x5):当Stream已经处于半关闭状态不再接收Frame帧时
  • FRAME_SIZE_ERROR(0x6):接收到的Frame Size不合法
  • REFUSED_STREAM(0x7):拒绝先前的Steam流的执行
  • CANCEL(0x8):表示Stream不再存在
  • COMPRESS_ERROR(0x9):对HPACK压缩算法执行失败
  • CONNECT_ERROR(0xa):连接失败
  • ENHANCE_YOUR_CALM(0xb):检测到对端的行为可能导致负载的持续增加,提醒对方“冷静”一点
  • INADEQUATE_SECRITY(0xc):安全等级不够
  • HTTP_1_1_REQUIRED(0xd):对端只能接受HTTP/1.1协议

    Stream优先级与资源分配规则

    PRIORITY优先级设置帧

  • 帧类型:type=0x2

  • 不使用flag标志位字段
  • Stream Dependency:依赖流
  • Weight权重:取值范围为1到256. 默认权重16
  • 仅针对Stream流,若ID为0试图影响连接,则接收端必须报错
  • 在idle和closed状态下,仍然可以发送Priority帧

image.png

exclusive标志位

image.png

HTTP2流量控制

为什么需要HTTP/2应用层流控

  • HTTP/2,多路复用意味着多个Stream必须共享TCP层的流量控制
  • 问题:多个Stream争夺TCP的流控制,互相干扰可能造成Stream阻塞

image.png

  • 代理服务器内存有限,上下游网速不一致时,通过流控管理内存

    由应用层决定发送速度

  • HTTP/2中的流控制既针对单个Stream,也针对整个TCP连接

    • 客户端与服务器都具备流量控制能力
    • 单向流控制:发送端和接收端独立设定流量控制
    • 以信用为基础:接收端设定上限,发送端应当遵循接收端发出的指令
    • 流量控制窗口(流或者连接)初始值是65535字节
    • 只有DATA帧服从流量控制
    • 流量控制不能被禁用

      WINDOW_UPDATE帧

  • type=0x8,不使用任何flag

  • 窗口范围1 to 2^31(2,147,483,647)
    • 0是错误的,接收端应返回PROTOCOL_ERROR
  • 当Stream ID为0时表示对连接流控,否则为对Stream流控
  • 流控仅针对直接建立TCP连接的两端
    • 代理服务器并不需要透传WINDOW_UPDATE帧
    • 接收端的缩小流控窗口会醉总传递到源发送端

image.png