HTTP 2协议流程
最近在研究HTTP 2相关的协议,且大多数CDN都是默认HTTP 2,所以记录一下HTTP 2的详细通信流程。
1、HTTP 2概述
据Cloudflare统计,HTTP 2网站已经占到所有网站的50%,HTTP 3则占到了20.5%。所以HTTP 2在如今的网络环境中越来越重要。HTTP 2的RFC文档在此。
HTTP 2通信常被分为两类,即h2c和h2。
h2c:是基于HTTP 1.1 Upgrade试探升级HTTP 2,或在C/S框架中客户端已知服务端支持HTTP 2,直接发送HTTP 2数据包,不论哪一种,其通信过程是都是明文的,这是极其不安全的,主流浏览器都不支持,也很少有人使用,所以这里我们不做讨论。
h2:是被大多数人推广使用的,即在TLS的ClientHello包中的ALPN(Application Layer Protocol Negotiation)扩展中就声明支持h2,若服务端支持h2,则会选中该扩展,发回客户端。随后TLS连接建立完之后,就可以直接用HTTP 2通信了。
2、帧结构

HTTP 2的帧(Frame)结构由固定9字节帧头(Frame Header)和可变长度帧负载(Frame Payload)组成,定义于RFC 7540。
| 字段 | 长度 | 说明 |
|---|---|---|
| Length | 24bit | Payload长度 |
| Type | 8bit | 帧类型 |
| Flags | 8bit | 与帧类型相关的标志位 |
| R | 1bit | 保留位,必须为0 |
| Stream Identifier | 31bit | 流ID,0表示连接级帧 |
Length:默认大小区间为为0~16,384(2^14),一旦超过默认最大值2^14(16384),发送方将不再允许发送,除非接收到接收方定义的SETTINGS_MAX_FRAME_SIZE(一般此值区间为2^14 ~ 2^24)值的通知
Type:帧类型,共10种,如下表所示
Flags:与帧类型相关的标志位,如END_STREAM表示流的一端关闭、END_HEADERS表示Header块结束、ACK表示确认SETTINGS或PING帧
R:保留位,必须为0
Stream Identifier:帧所属的流ID,0表示连接帧,如SETTINGS、PING、GOAWAY,奇数表示由客户端创建的流,偶数表示由服务端建立的流
| Type | 帧类型 | 简介 |
|---|---|---|
| 0x0 | DATA | 承载请求或响应的实体数据,受流量控制机制约束 |
| 0x1 | HEADERS | 传输请求或响应的首部块,使用HPACK压缩 |
| 0x2 | PRIORITY | 指定流的优先级和依赖关系 |
| 0x3 | RST_STREAM | 异常终止一个已存在的流 |
| 0x4 | SETTINGS | 交换连接级参数配置,仅使用流ID 0 |
| 0x5 | PUSH_PROMISE | 服务器推送时,声明即将发送的请求 |
| 0x6 | PING | 连接保活、RTT测量,携带8字节不透明数据 |
| 0x7 | GOAWAY | 通知对端即将关闭连接并指明最后可处理流 |
| 0x8 | WINDOW_UPDATE | 流量控制,更新连接或流的发送窗口 |
| 0x9 | CONTINUATION | 继续传输未在HEADERS/PUSH_PROMISE中完成的首部块 |
HTTP 2本质上没有改变HTTP语义,只是将HTTP的Header和Body部分重新用帧结构封装了一下。
HEADERS采用了HPCAK压缩算法,且仅有其使用。
3、通信流程
HTTP 2整体上还是遵循客户端请求-服务端响应的通信结构,只不过会多一些控制帧。
首先,客户端先发送Magic序列,这是一个固定的24字节序列,表明其要用HTTP 2协议通信,然后紧接着必须发送SETTING帧,之后还可能衔接WINDOW_UPDATE帧,随后则是HEADERS和DATA,且HEADERS必须先于DATA。
服务端在TLS握手结束后,立即同步发送SETTING帧。