HTTP/2 请求相关的知识整理

HTTP/2 请求相关的知识整理

简介

HTTP 2.0 是在 SPDY 基础上形成的下一代互联网通信协议。HTTP/2 的目的是通过支持请求与响应的多路复用来较少延迟,通过压缩 HTTPS 首部字段将协议开销降低,同时增加了请求优先级和服务器端推送的支持。

主要变化

使用 HTTP 帧的方式传输数据

报文格式替换为:

1
2
3
4
5
6
7
8
9
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
  • Length: 载荷的长度,无符号24位整型。对于发送长度大于2^14 (16384字节)的载荷, 只有在接收方设置 SETTINGS_MAX_FRAME_SIZE 为更大的值时才被允许传输
  • Type: 8位的值表示帧类型,决定了帧的格式和语义。协议实现上必须忽略任何未知类型的帧。
  • Flags: 为 Type 保留的布尔标识,大小是8位。对确定的帧类型赋予特定的语义,否则发送时必须忽略(设置为0x0)。
  • R: 1位的保留字段,尚未定义语义。 发送和接收必须忽略(0x0)。
  • Stream Identifier: 31位无符号整型的流标示符。 其中0x0作为保留值,表示与连接相关的frames作为一个整体而不是一个单独的流。

使用流和复用机制增强性能

在一个 HTTP/2 的连接中, 流是服务器与客户端之间用于帧交换的一个独立双向序列. 流有几个重要的特点:

  • 一个 HTTP/2 连接可以包含多个并发的流,各个端点从多个流中交换帧。
  • 流可以被客户端或服务器单方面建立,使用或共享。
  • 流也可以被任意一方关闭。
  • 帧在一个流上的发送顺序很重要。接收方将按照他们的接收顺序处理这些帧。特别是 HEADERS 和DATA 帧的顺序,在协议的语义上显得尤为重要。
  • 流用一个整数(流标识符)标记。端点初始化流的时候就为其分配了标识符。

下面是流的生命周期:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
                         +--------+
send PP | | recv PP
,--------| idle |--------.
/ | | \
v +--------+ v
+----------+ | +----------+
| | | send H / | |
,------| reserved | | recv H | reserved |------.
| | (local) | | | (remote) | |
| +----------+ v +----------+ |
| | +--------+ | |
| | recv ES | | send ES | |
| send H | ,-------| open |-------. | recv H |
| | / | | \ | |
| v v +--------+ v v |
| +----------+ | +----------+ |
| | half | | | half | |
| | closed | | send R / | closed | |
| | (remote) | | recv R | (local) | |
| +----------+ | +----------+ |
| | | | |
| | send ES / | recv ES / | |
| | send R / v send R / | |
| | recv R +--------+ recv R | |
| send R / `----------->| |<-----------' send R / |
| recv R | closed | recv R |
`----------------------->| |<----------------------'
+--------+

send: 发送这个frame的终端
recv: 接受这个frame的终端

H: HEADERS帧 (隐含CONTINUATION帧)
PP: PUSH_PROMISE帧 (隐含CONTINUATION帧)
ES: END_STREAM标记
R: RST_STREAM帧

引入流的依赖关系和优先级机制

客户端可以给一个新的流分配一个优先级,做法是在用来打开流的 HEADERS 帧中包含优先次序信息。在其他任何时间,可以用 PRIORITY 帧改变一个流的优先级。

每个流可以显式指定依赖其他的流。如果流被其他流所依赖,这就表明这个流在资源的分配上优先于它的从属流。

新增服务器推送机制(抢先推送与相应内容相关的请求)

HTTP/2 允许服务器先行发送(或推送)与先前客户端初始请求相关的响应(对应"许诺"的请求)到客户端。这在服务端知道客户端将会须要这些响应来完全地处理原始请求的响应时会很有用。

许诺的请求必须是可缓存的(参见 [RFC7231], 4.2.3 节),必须是安全的(参见 [RFC7231], 4.2.1 节),必须不能包含请求体。 客户端收到不是可缓存的,不能被识别为安全的或者是表明存在请求体的许诺请求必须重置许诺流并设置 PROTOCOL_ERROR 类型的流错误。 注意这可能导致在客户端不能识别一个新的方法是不是安全的时候重置流。

参考资料

协议原文

协议中文译版


HTTP/2 请求相关的知识整理
https://wangqian0306.github.io/2021/http/
作者
WangQian
发布于
2021年11月3日
许可协议