http2 包演进历史
HTTP 协议历史
HTTP/0.9 (1991)
有 get,post 等方法了
GET /\r\n
<HTML>
<HEAD><TITLE>...</TITLE></HEAD>
<BODY>
…
</BODY></HTML>
(disconnect)
HTTP/1.0 (1996)
新增了协议号,Headers,Content-Type
GET / HTTP/1.0\r\n
User-Agent: Mozilla/3.0 (X11; blah)\r\n
Cookie: foo=val\r\n
\r\n
HTTP/1.0 200 OK
Content-Type: text/html
<HTML>...
(disconnect)
HTTP/1.0, evolved
新增 Connection Header,设置为 keep-alive 后续的请求可以使用同一个 tcp 连接
GET / HTTP/1.1\r\n
User-Agent: Mozilla/3.0 (X11; blah)\r\n
Connection: keep-alive\r\n
\r\n
HTTP/1.0 200 OK
Content-Length: 1203
Content-Type: text/html
Connection: keep-alive
<HTML>...
GET /underconstruction.gif HTTP/1.1\r\n ...
HTTP/1.1 (~1999)
- keep-alive 改为默认设置,发送
Connection: close
才会断开连接 - 支持
Transfer-Encoding: chunked
,可以发送位置大小的数据,不需要关闭 tcp 连接来通知发送结束了
GET / HTTP/1.1\r\n
User-Agent: Mozilla/3.0 (X11; blah)\r\n
Host: example.com\r\n
\r\n
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
3FF
<HTML>...
GET /underconstruction.gif HTTP/1.1\r\n ...
实操
$ telnet example.com 80
Trying 93.184.215.14...
Connected to example.com.
Escape character is '^]'.
GET / HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 402131
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
...
HTTP/1. x 的问题
- One thing at a time
- Lots of waiting
- TCP setup, slow start
- TLS handshakes too: ClientHello, ServerHello
- requests are ~800B+cookies
- No way for servers to gracefully shut down
- Server TCP FIN & client request both in flight
- No way for client to abort a request without killing TCP connection
- Workaround, special cases
HTTP/2 (2012-)
http2 的诞生用于修复 http1.x 中存在的诸多问题,如队头阻塞、头部冗余、连接复用等问题
- 语义和 http1.x 保持一致
- 二进制协议
- 支持多路复用
- 头部压缩
- 请求优先级
- 服务器推送
基本概念
- 流:流是连接中的一个虚拟信道,可以承载双向的消息
- 消息:是指逻辑上的 HTTP 消息,比如请求、响应等
- 帧:HTTP 2.0 通信的最小单位,每个帧包含帧首部,至少也会标识出当前帧所属的流,承载着特定类型的数据
帧
使用帧作为数据传输的单位
- 9 个字节的头帧数据
- 3 个字节的帧长度
- 1 个字节的帧类型
- 1 个字节的 flags 数据
- 4 个字节的 Stream ID
- N 个字节的 payload
0x00000c010500000001828466882f91d35d055c87a7
目前有 9 种基础帧类型
const (
FrameData FrameType = 0x0
FrameHeaders FrameType = 0x1
FramePriority FrameType = 0x2
FrameRSTStream FrameType = 0x3
FrameSettings FrameType = 0x4
FramePushPromise FrameType = 0x5
FramePing FrameType = 0x6
FrameGoAway FrameType = 0x7
FrameWindowUpdate FrameType = 0x8
FrameContinuation FrameType = 0x9
)
多路复用
http2 链路是全双工的且支持多路复用,多个流的数据的可以交替传输
HPACK 算法
HPACK 是 HTTP/2 中的头部压缩格式,主要用于减少头部数据的大小,从而提高传输效率。
如下图所示,已有的 header 就不会再重复发送。
协议磋商
- 询问服务器是否支持 http 2 不支持则降级为 http 1.1
- 发起带有 HTTP 2.0 Upgrade 首部的 HTTP 1.1 请求
- 服务器拒绝升级,通过 HTTP 1.1 返回响应
- 服务器接受 HTTP 2.0 升级,切换到新分帧
请求流程
HTTPS 请求流程
延伸阅读
- RFC 9113
- HTTP/2 and http2 in Go 1.6
- London Go Gathering 2015 | HTTP/2 with Brad Fitzpatrick
- 深入理解 Web 协议 (三):HTTP 2
- High Performance Browser Networking
- http2 explained
- Hacking with Andrew and Brad: an HTTP/2 client
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。