• 为 HTTP/2 头压缩专门设计的 HPACK


          HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。如何理解 HPACK 压缩呢? 如果我们约定将常用的请求头的参数用一些特殊的编号来表示,比如 GET /index.html 用一个 1 来表示,POST /index.html 用 2 来表示。那么是不是可以节省很多字节? 为 HTTP/2 的专门量身打造的 HPACK 便是类似这样的思路延伸。它使用一份索引表来定义常用的 HTTP Header。把常用的 HTTP Header 存放在表里。请求的时候便只需要发送在表里的索引位置即可。例如 :method=GET 使用索引值 2 表示,:path=/index.html 使用索引值 5 表示。 具体这里的静态映射表请看附录的Table 1: Static Table Entries。

     

          比如我们想表达 请求的Header内容是:   GET /index.html   只要给服务端发送一个 Frame,该 Frame 的 Payload 部分存储 0x8285,Frame 的 Type 设置为 Header 类型。

          为什么是 0x8285,而不是 0x0205? 这是因为高位设置为 1 表示这个字节是一个完全索引值(key 和 value 都在索引中)。类似的,通过高位的标志位可以区分出这个字节是属于一个完全索引值,还是仅索引了 key,还是 key 和 value 都没有索引。因为索引表的大小的是有限的,它仅保存了一些常用的 HTTP Header,同时每次请求还可以在表的末尾动态追加新的 HTTP Header 缓存。动态部分称之为 Dynamic Table。Static Table 和 Dynamic Table 在一起组合成了索引表:

    参考: http://io.upyun.com/2015/05/13/http2/ 

    image

    HPACK 不仅仅通过索引键值对来降低数据量,同时还会将字符串进行霍夫曼编码来压缩字符串大小。

    以常用的 User-Agent 为例,它在静态表中的索引值是 58,它的值是不存在表中的,因为它的值是多变的。第一次请求的时候它的 key 用 58 表示,表示这是一个 User-Agent ,它的值部分会进行霍夫曼编码(如果编码后的字符串变更长了,则不采用霍夫曼编码)。服务端收到请求后,会将这个 User-Agent 添加到 Dynamic Table 缓存起来,分配一个新的索引值。客户端下一次请求时,假设上次请求User-Agent的在表中的索引位置是 62, 此时只需要发送 0xBE(同样的,高位置 1),便可以代表: User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36。其过程如下图所示:

     

    HPACK: Header Compression for HTTP/2

    image

    图来自: http://chimera.labs.oreilly.com/books/1230000000545/ch12.html#HTTP2_PUSH

     

    WireShark  可以看到具体的 Header 解密后的内容,如下图:

    image

    上图是用的 WireShark  Development Release (1.99.6) 看到的 Header frame 的内容。

    https://www.wireshark.org/download.html 

     

    Header  Frame 的数据格式

    HTTP2 的 Header Frame 的数据区, 分下面几种格式,相关资料请参考:http://http2.github.io/http2-spec/compression.html#index.address.space

     

    1、在 预定的头字段静态映射表 中已经有预定义的 Header Name 和 Header Value值

    image

    这时候的二进制数据格式如上图, 第一位固定为1, 后面7位为映射的索引值

    An indexed header field starts with the '1' 1-bit pattern, followed by the index of the matching header field, represented as an integer with a 7-bit prefix

    例子,

    下图的 83 就是这样的,  83 的二进制字节标示  1000 0011 , 抹掉首位, 就是 3 , 对应的 静态映射表中 的 method: POST。

    image 

    注意,不存在首位为0,但是后面可以在静态表中可以找到的情况。

     

    2、 预定的头字段静态映射表中有 name,需要设置新值。

    Literal Header Field with Incremental Indexing

    这种情况下的数据格式为:

    image

    例子, 一个指定 path的Header, 

    首字符 为 44 ,对应的二进制位   0100 0100   前两个字符为 01 ,  Index 为 4 , 即对应静态映射表中的 path 头。

    第二个字符为 95  对应的二进制位 1001 0101 ,排除首字符对应的 Value Length 为 十进制的21。 即 算上 44, 一共23个字符来记录这个信息。

    image

     

     

    3、预定的头字段静态映射表中没有 name,需要设置新name和新值。

    image

    例子

    40 的二进制是  0100 0000,  
    02 的二进制是  0000 0010, 后七位的十进制值是 2

    86 的二进制是  1000 0110  后7位的十进制值是 6

    image

     

    其他还有2种情况:

    Literal Header Field without Indexing

    • Literal Header Field without Indexing — Indexed Name
    • Literal Header Field without Indexing — New Name

    Literal Header Field Never Indexed

      • Literal Header Field Never Indexed — Indexed Name
      • Literal Header Field Never Indexed — New Name

    请参考: http://http2.github.io/http2-spec/compression.html#index.address.space 

     

    附录

    HTTP2 中, 预定的头字段静态映射表如下。(Table 1: Static Table Entries)

    image

     

     

     

     

    参考资料:

    【协议分析】HTTP2报文头及数据帧格式解析实例分析
    http://blog.csdn.net/jiayanhui2877/article/details/45074315

    HPACK: Header Compression for HTTP/2
    http://http2.github.io/http2-spec/compression.html

    HPACK: Header Compression for HTTP/2
    https://httpwg.github.io/specs/rfc7541.html

    HPACK - Header Compression for HTTP/2
    draft-ietf-httpbis-header-compression-12
    https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#section-2.2

    Chapter 12. HTTP/2

    http://chimera.labs.oreilly.com/books/1230000000545/ch12.html#HTTP2_FRAMING

    Huffman 编码压缩算法
    http://coolshell.cn/articles/7459.html

  • 相关阅读:
    再谈HTTP通信
    【ZOJ】[1586]QS Network
    【ZOJ】[1586]QS Network
    【POJ】[2421]Constructing Roads
    【POJ】[2421]Constructing Roads
    【POJ】[2031]Building a Space Station
    【POJ】[2031]Building a Space Station
    【POJ】[1287]Networking
    【POJ】[1287]Networking
    【杭电】[1875]畅通工程再续
  • 原文地址:https://www.cnblogs.com/ghj1976/p/4586529.html
Copyright © 2020-2023  润新知