关于http-2:HTTP20的二进制是什么

40次阅读

共计 3188 个字符,预计需要花费 8 分钟才能阅读完成。

这篇纯正满足本人的好奇心

我如同是一个在海边游玩的孩子,不断为拾到比通常更润滑的石子或更漂亮的 贝壳而欢欣鼓舞,而展示在我背后的是齐全未探明的真谛之海。牛顿

写本文的时候,想起高中物理课本的一句话:

我如同是一个在海边游玩的孩子,不断为拾到比通常更润滑的石子或更漂亮的贝壳而欢欣鼓舞,而展示在我背后的是齐全未探明的真谛之海。

那个时候不懂这句话,忙于刷分,现在纯正是为了本人的好奇心而探索一些问题,脑海中又开始复现这句话。本文的问题来自于后面的一篇文章:《HTTP 学习笔记 (三) HTTP/2》,这篇文章里咱们提到了 HTTP/ 2 的几个特点:

  1. is binary, instead of textual

二进制代替了文本

  1. is fully multiplexed, instead of ordered and blocking

多路复用

  1. can therefore use one connection for parallelism

并行申请

  1. uses header compression to reduce overhead

压缩申请头,缩小耗费

  1. allows servers to“push”responses proactively into client caches

容许服务器被动推送响应进入客户端的缓存中

其实对于 1 我是不了解的,毕竟在计算机的世界都是“二进制”嘛,过后我的想法是难道是跟 JDK 解决 String 一样的操作,在 JDK8 之前,String 自身是借助于 char 来存储的:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];}

到了 JDK 8 之后, JDK 借助 byte 来存储字符串:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc {
    @Stable
    private final byte[] value;}    

毕竟一个 char 占两个字节, 一个 byte 只占一个字节,因为我之前用程序连贯过充电桩,接管充电桩的报文,给的报文都是 byte 类型的,byte 更小,像 String 就带了一些额定的信息,所以我猜测,是这个意义上的二进制,然而这只是猜测,我想过用抓包工具去验证我的猜测,然而发现抓包工具我用的并部署,再加上 HTTP/2.0 都是加密报文,抓包挺麻烦的,我也想过看 HTTP Client 的源码,然而这两个奏效都太慢了,最近偶尔翻看 MongDB 的文档,翻到了这方面的阐明,这个问题就有了答案。其实 HTTP 也对下面的二进制进行了解释:

Why is HTTP/2 binary?

Binary protocols are more efficient to parse, more compact“on the wire”, and most importantly, they are much less error-prone, compared to textual protocols like HTTP/1.x, because they often have a number of affordances to“help”with things like whitespace handling, capitalization, line endings, blank lines and so on.

二进制协定绝对于文本协定,比方 HTTP/1.x,解析效率、传输效率更高,有更好的容错性。还提供了一些机制能够帮忙解决空白字符、大小写、空行等等。

For example, HTTP/1.1 defines four different ways to parse a message; in HTTP/2, there’s just one code path.

例如,HTTP/1.1 定义了四种解析数据的形式,然而在 HTTP/2, 只有一种代码门路。

It’s true that HTTP/2 isn’t usable through telnet, but we already have some tool support, such as a Wireshark plugin.

尽管 HTTP/ 2 曾经不能再应用 Telnet 了,然而咱们也有其余工具的反对,比方 Wireshark plugin。

所以 HTTP 说本人是二进制的,潜台词是 HTTP/ 2 的数据包采取了高度结构化的格局,因为在计算机中,最终一切都是二进制模式存在。在 HTTP/ 2 中传输的数据会被格式化为帧 (frame), 每个帧都会被调配一个流。HTTP/ 2 的帧具备特定的格局,如下图所示:

 +-----------------------------------------------+
 |                 Length (24)                   |
 +---------------+---------------+---------------+
 |   Type (8)    |   Flags (8)   |
 +-+-------------+---------------+-------------------------------+
 |R|                 Stream Identifier (31)                      |
 +=+=============================================================+
 |                   Frame Payload (0...)                      ...
 +---------------------------------------------------------------+

在 HTTP/ 2 中,每个帧都由两局部组成: 帧头 (9 个字节),帧头是固定长度的,占据 9 个字节,蕴含了对于该帧的一些信息,比方长度、类型等。帧头前面是有效载荷,长度可变,取决于帧的类型和内容。这有点相似于 TCP 数据包,读取 HTTP/ 2 帧能够遵循定义好的过程 (先读取数据长度,而后帧的类型)。相比之下,HTTP/1.1 是由一个 ASCII 编码的文本行组成的非结构化格局,尽管这些文本最终将以二进制模式传输,然而基本上它是一串字符的流,而不是明确地被分为独立的帧。

HTTP/1.1 的音讯通过一一字符地读取字符来解析,直到达到换行字符为止,这种形式有点凌乱,然而因为无奈晓得每行的长度,所以必须一一字符进行解决。对于 HTTP 注释的长度能够提前晓得,咱们能够在 HTTP 头里获知到这个信息。

这让我想起了 MongDB 的 BSON,我想 BSON 中的 binary 的语义该当和 HTTP/ 2 的 binary 语义是对等的,在 BSON 标准的官网能够看到咱们的猜测是正确的:

BSON is a binary format in which zero or more ordered key/value pairs are stored as a single entity. We call this entity a document.

BSON 是一种二进制格局,其中有零个或多个有序的键 / 值对被存储为一个繁多的实体,咱们将这个实体称之为文档。

上面是一个 JSON 和其对应的 BSON 格局的示例:

{"hello": "world"} →
\x16\x00\x00\x00           // total document size 总的文档大小 算上大小字段自身
\x02                       // 0x02 = type String 
hello\x00                  // field name 字段值
\x06\x00\x00\x00world\x00  // field value 字段值
\x00                       // 0x00 = type EOO ('end of object')

总结一下,在计算机中最终一切都是二进制格局,当咱们在数据格式中看到二进制时,咱们能够了解为这种存储构造是高度结构化的 , 读取效率更高,更为紧凑,将数据从新进行布局。

正文完
 0