HTTP/2.0的二进制是什么?

简介: HTTP/2.0的二进制是什么?

这篇纯粹满足自己的好奇心

我好像是一个在海边玩耍的孩子,不时为拾到比通常更光滑的石子或更美丽的 贝壳而欢欣鼓舞,而展现在我面前的是完全未探明的真理之海。牛顿

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

我好像是一个在海边玩耍的孩子,不时为拾到比通常更光滑的石子或更美丽的贝壳而欢欣鼓舞,而展现在我面前的是完全未探明的真理之海。

那个时候不懂这句话,忙于刷分,如今纯粹是为了自己的好奇心而探究一些问题,脑海中又开始复现这句话。本文的问题来自于前面的一篇文章:《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')

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

相关文章
|
Web App开发 存储
Http服务器如何在HTTP response中传送二进制图片
要想知道如何传送这些二进制,先来点二进制文件的背景知识    —文件魔数 magic number: 操作系统的文件,其起始的几个字节的内容是固定的。
1255 0
|
Web App开发 新零售 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
1.尽可能地了解需求,系统层面适用开闭原则 2.模块化,低耦合,能快速响应变化,也可以避免一个子系统的问题波及整个大系统 3.
735 0
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
异步通信 对于BS(Browser-Server 浏览器)架构,很多情景下server的处理时间较长。 如果浏览器发送请求后,保持跟server的连接,等待server响应,那么一方面会对用户的体验有负面影响; 另一方面,很有可能会由于超时,提示用户服务请求失败。
759 0
|
Web App开发 前端开发 关系型数据库
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
fuser可用于查询文件、目录、socket端口和文件系统的使用进程 1.查询文件和目录使用者 fuser最基本的用法是查询某个文件或目录被哪个进程使用: # fuser -v .
874 0
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
最近在线上往hbase导数据,因为hbase写入能力比较强,没有太在意写的问题。让业务方进行历史数据的导入操作,中间发现一个问题,写入速度太快,并且业务数据集中到其中一个region,这个region无法split掉,处于不可用状态。
1321 0
|
Web App开发 前端开发
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
Every Programmer Should Know These Latency Numbers 1秒=1000毫秒(ms) 1秒=1,000,000 微秒(μs) 1秒=1,000,000,000 纳秒(ns) 1秒=1,000,000,000,000 皮秒(ps) L1 cache reference .
639 0
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
zookeeper watch的定义如下:watch事件是一次性触发器,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher。
923 0
|
Web App开发 大数据
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
                                                                               1.
1678 0
|
Web App开发 监控 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
hadoop服务器更换硬盘操作步骤(datanode hadoop目录${HADOOP_HOME}/bin    日志位置:/var/log/hadoop)1.登陆服务器,切换到mapred用户,执行jps命令,查看是否有TaskTracker进程。
1001 0

热门文章

最新文章