简介
在 HTTP/1.1 中,Header 部分是不会被压缩的,这造成了在传输过程中传输了许多冗余的 Header。
HTTP/2 中采用 HPACK 算法对 HTTP头部进行压缩,以达到减小传输数据量的目的。
术语
- Dynamic Table - 运行过程中动态生成的映射表
- Static Table - RFC 定义的,静态映射表
Compression Process Overview
Header List Ordering
编解码器必须使用原始 header 的顺序进行编解码,即,禁止一定规则排序后在进行编解码。Encoding and Decoding Contexts
一个 HTTP 请求的客户端和服务端独立维护动态表。
同一个连接上,客户端控制服务端动态表;服务端控制客户端动态表。
即在传输过程中,通过不同的标志位标记是否添加以及添加 only header or both 到对端的动态表中。
+———-+——————————————-+———————-+
| Index | Header Name | Header Value |
+———-+——————————————-+———————-+
| 1 | :authority | |
| 2 | :method | GET |
| 3 | :method | POST |
| 4 | :path | / |
| 5 | :path | /index.html |
| 6 | :scheme | http |
| 7 | :scheme | https |
| 8 | :status | 200 |
| 9 | :status | 204 |
| 10 | :status | 206 |
| 11 | :status | 304 |
| 12 | :status | 400 |
| 13 | :status | 404 |
| 14 | :status | 500 |
| 15 | accept-charset | |
| 16 | accept-encoding | gzip, deflate |
| 17 | accept-language | |
| 18 | accept-ranges | |
| 19 | accept | |
| 20 | access-control-allow-origin | |
如上部分静态索引表所示,一个索引可以表示 header + value
也可以仅表示一个 header
Indexing Tables
HPACK 使用两个 table 来索引头部。一个叫做静态表是固定的,另一个叫做动态表在运行过程中动态生成。
Static Table
https://www.rfc-editor.org/rfc/rfc7541.html#appendix-A
Dynamic Table
- 初始化为空;
- 动态表是一个 first-in, first-out 的队列;
- 队头元素索引最小,队尾元素索引最大;
- 动态表内数据可以重复;
Huffman
对于不使用索引表的 Header,Header 名和值需要使用 Huffman 编码后进行传递。
HTTP2 目前使用静态 Huffman 编码,常见的编码 Table 见:https://www.rfc-editor.org/rfc/rfc7541.html#appendix-B
HTTP2 hpack 算法实现
https://github.com/golang/net/blob/master/http2/hpack/hpack.go
参考
https://www.rfc-editor.org/rfc/rfc7541.html
https://github.com/golang/net/blob/master/http2/hpack/hpack.go
https://developers.google.com/web/fundamentals/performance/http2?hl=zh-cn#%E6%A0%87%E5%A4%B4%E5%8E%8B%E7%BC%A9