简介

在 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