- 连接Connection:1个TCP连接,包含一个或者多个Stream
- 数据流Stream:一个双向通讯数据流,包含一条或者多条Message
- 消息Message:对应HTTP/1中的请求或者响应,包含一条或者多条Frame
- 数据帧Frame:最小单位,以为禁止压缩格式存放HTTP/1中的内容
Stream ID 的作用
实现多路复用的关键
- 接收端的实现可据此并发组装消息
- 同一Stream内的frame必须是有序的(无法并发)
- SETTING_MAX_CONNECTION_STREAMS控制着并发Stream数
推送依赖性请求的关键
- 由客户端建立的流必须是奇数
- 由服务器端建立的流必须是偶数
流状态管理的约束性规定
- 新建立的流ID必须大于曾经建立过的状态为opened或者reserved的流ID
- 在新建立的流上发送帧时,意味着更小ID且为idle状态的流置为closed状态
-
应用层流控仅影响控制帧
StreamID为0的流仅用于传输控制帧
- 在HTTP/1升级到h2c中,以ID为1流返回响应,之后流进入half-closed(local)状态
帧格式:帧类型及设置帧的子类型
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:设置值
设置类型
- 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
- 在stram1中通知客户端CSS资源即将来临
- 在Stream2中发送CSS资源(Stream1和2可以并发)
PUSH帧的格式
- PUSH_PROMISE帧,type=0x5,只能由服务端发送
PUSH推送模式的禁用
SETTINGS_ENABLE_PUSH
帧符号
- H: HEADERS帧
- PP: PUSH_PROMISE帧
- ES: END_STREAM标志位
- R: RES_STREAM帧
- 流状态
- idel: 起始状态
- closed:关闭
- open:可以发送任何帧
- half closed 单向关闭
- remote: 不再接受数据帧
- local:不能再发送数据帧
- reserved
- remote
- local
RST_STREAM帧(type=0x3)
- HTTP2多个流共享同一连接,RST帧允许立刻终止一个未完成的流
- RST_STREAM帧不使用任何flag
- RST_STREAM帧的格式
常见错误码
- 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帧
exclusive标志位
HTTP2流量控制
为什么需要HTTP/2应用层流控
- HTTP/2,多路复用意味着多个Stream必须共享TCP层的流量控制
- 问题:多个Stream争夺TCP的流控制,互相干扰可能造成Stream阻塞
-
由应用层决定发送速度
HTTP/2中的流控制既针对单个Stream,也针对整个TCP连接
type=0x8,不使用任何flag
- 窗口范围1 to 2^31(2,147,483,647)
- 0是错误的,接收端应返回PROTOCOL_ERROR
- 当Stream ID为0时表示对连接流控,否则为对Stream流控
- 流控仅针对直接建立TCP连接的两端
- 代理服务器并不需要透传WINDOW_UPDATE帧
- 接收端的缩小流控窗口会醉总传递到源发送端