伯阳的网络笔记:HTTP/2 基础
1. HTTP/1.x 的问题
不得不说, HTTP/1.1 是一个伟大的协议,现在仍然有非常多的网站使用它,充分说明了它的健壮、巧妙。但是,它毕竟是一个创建于互联网时代前的协议,虽然已经很有预见性了,但是仍然有些过时了。主要有以下几个问题:
- HTTP 只允许每个 TCP 连接有一个未完成的请求,会有队首阻塞的问题;
- 对于同一个域名,浏览器最多可以同时创建 6~8 个 TCP 连接;
- Header 有点过大了;
- 为了尽可能减少请求数,需要做合并文件、减少图像等优化工作,但是这无疑造成了单个请求内容变大延迟变高的问题;
- 明文传输。
所以,随着求变的声音越来越多,HTTP/2 应声而出。
2. SPDY
等一下,正式讲到 HTTP/2 之前,我们需要先提一下 SPDY。
因为迟迟没有 HTTP/1.1 的优化出线,谷歌自己推出了一个新的网络协议,叫做 SPDY,它的很多设计,被采用到了 HTTP/2 当中,比如说多路复用、二进制分帧、头部压缩、服务器推送等等。
3. HTTP/2 简介
在2012年,W3C向社会征求 HTTP/2 的建议,然后决定将 SPDY 当做制定标准的基础。目标上, HTTP/2 致力于突破上一代协议众所周知的性能限制,对 HTTP/1.x 进行扩展,而非替代,核心概念不会改变。下图展示了 HTTP/1 和 HTTP/2 的区别。
它做了很多改变,下面细讲。 不过在讲之前,要先解释 HTTP/2 中的几个概念:
- 流
已建立的连接上的双向字节流 - 消息
与逻辑消息对应的完整的一系列数据帧 - 帧
HTTP/2 通信的最小单位
所有的 HTTP/2 通信都是在一个 TCP 连接上完成,这个连接可以承载任意数量的双向数据流。相应的,每个数据流以消息的形式发送,而消息由一个或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流表示符重新组装。
二进制分帧
HTTP/2 性能增强的核心,全在于新增的二进制分帧层,它定义了如何封装 HTTP 消息并在客户端与服务器之间传输。
这里的”层”,指的是位于会话层和应用层之间的一个新的机制:HTTP 的语义不受影响,不同的是传输期间对它们的编码方式改变了。HTTP/1.x 以换行符作为纯文本的分隔符,而 HTTP/2 将所有传输的信息分割为更小的消息和帧,并对他们采用了二进制格式的编码。
多向请求和响应
在 HTTP/1.x 中,如果客户端想要发送多个并行的请求以改进性能,那么必须使用多个 TCP 连接;每个连接每次只交付一个响应,多个响应必须要排队。更糟糕的在于,这样非常容易发生队首堵塞,从而造成 TCP 连接效率低下。
HTTP/2 中的二进制分帧,突破了这种限制,客户端和服务器可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,然后在另一端把他们重新组合起来。如下如所示。
将 HTTP 消息分解为独立的帧,交错发送,然后在另外一端重新组装是 HTTP/2 最重要的一项增强。它带来了以下几个优点:
- 可以并行交错的发送请求,请求之间互不影响;
- 可以并行交错的发送响应,响应之间互不干扰;
- 只使用一个连接即可并行发送多个请求和响应(多路复用);
- 消除不必要的延迟;
- 不必再继续在为了绕过 HTTP/1.x 的限制做很多工作;
- ……
总之,这个技术解决了 HTTP/1.1 中存在的队首阻塞问题,也消除了并行处理和发送请求及响应时对多个连接的依赖。
流量控制
在同一个 TCP 上传输多个数据流,就意味着要共享带宽。标定数据流的优先级有助于按序交付,但只有优先级还不足以确定多个数据流或多个连接之间的资源分配。所以,HTTP/2 提供了一个简单的机制:
- 流量控制基于每一跳进行,而非端到端的控制;
- 流量控制基于窗口更新帧进行,即接收方广播自己准备接受某个数据流的多少字节,以及对整个连接要接收多少字节;
- 流量控制窗口大小通过 WINDOW_UPDATE 帧更新;
我们可以发现,它和 TCP 流量控制非常类似,事实上这两个机制是一样的。
这个由程序员手动控制。
服务器推送
服务器可以对一个客户端请求发送多个响应。换句话说,除了对最初请求的响应外,服务器还可以额外向客户端推送资源,而无需客户端明确地请求。
因为有些资源,比如去线上阅读说一本书,就可以预测到下一步可能的阅读的页面,进而提前进行缓存。
首部压缩
HTTP 的每一次通信都会带一组完整的首部,用于描述传输的资源及其属性。在 HTTP/1.1 中,这些数据都是以纯文本的形式发送的,通常会给每个请求增加 500~800 字节的负荷;如果再算上 cookie ,增加的负荷可能会加大到上千字节。为了减少这些开销,HTTP/2 会压缩首部数据。
HTTP/2 连接的两端都知道已经发送了哪些首部,这些首部是什么,从而可以针对之前的数据只编码发送差异数据。
4. 加密
虽然一直有加入 TLS 的提议,但是最后 HTTP/2 并未强制加入 TLS。只是有些网站会加上。
5. HTTP/2 和 HTTP/3
HTTP/2 依然是以 TCP 作为基础的,但是 TCP 依然会有三次握手消耗时间,为了优化它,谷歌专门搞了一个基于 UDP 协议的 QUIC 协议。这个协议正在被一些大厂使用,但是因为源于 UDP 协议,有可能被运营商破坏,前景依然需要观察。
QUIC的相关原理可以查看科普:QUIC协议原理分析这篇文章,以及这个HTTP/3 讲解
总结
总的来说,HTTP/2 是基于 HTTP/1.1 进行的拓展,有效的优化了速度和数据量。在多路复用、二进制分帧、头部压缩、服务器推送上的优化非常的精妙和让人陶醉。
引用
RFC7540:Hypertext Transfer Protocol Version 2 (HTTP/2)
《Web性能权威指南》