# 6.浏览器中的网络

#### 谈及浏览器中的网络，就避不开 HTTP。我们知道 HTTP 是浏览器中最重要且使用最多的协议，是浏览器和服务器之间的通信语言，也是互联网的基石。而随着浏览器的发展，HTTP 为了能适应新的形式也在持续进化，学习 HTTP 的最佳途径就是了解其发展史，所以在接下来的三节文章中，从浏览器发展的视角来学习 HTTP 演进。这三节分别是即将完成使命的 HTTP/1、正在向我们走来的 HTTP/2，以及未来的 HTTP/3。

## 29 | HTTP/1：HTTP性能优化

> 本文主要介绍的是 HTTP/1.1，我们先来学习下 HTTP/1.1 的进化史，然后再介绍在进化过程中所遇到的各种瓶颈，以及对应的解决方法。

### 超文本传输协议HTTP/0.9

> HTTP/0.9 是于 1991 年提出的，主要用于学术交流，需求很简单——用来在网络之间传递`HTML 超文本`的内容，所以被称为`超文本传输协议`。\
> HTTP/0.9 的实现有以下三个特点:
>
> * 第一个是只有一个请求行，并没有 HTTP 请求头和请求体，因为只需要一个请求行就可以完整表达客户端的需求了。 &#x20;
> * 第二个是服务器也没有返回头信息，这是因为服务器端并不需要告诉客户端太多信息，只需要返回数据就可以了。   &#x20;
> * 第三个是返回的文件内容是以 ASCII 字符流来传输的，因为都是 HTML 格式的文件，所以使用 ASCII 字节码来传输是最合适的。

### 被浏览器推动的HTTP/1.0

> 变化是这个世界永恒不变的主旋律，1994 年底出现了拨号上网服务，同年网景又推出一款浏览器，从此万维网就不局限于学术交流了，而是进入了高速的发展阶段。 万维网的高速发展带来了很多新的需求，而 HTTP/0.9 已经不能适用新兴网络的发展，所以这时就需要一个新的协议来支撑新兴网络，这就是 HTTP/1.0 诞生的原因。
>
> 新兴网络带来了新的需求：首先在浏览器中展示的不单是 HTML 文件了，还包括了 JavaScript、CSS、图片、音频、视频等不同类型的文件。因此支持多种类型的文件下载是 HTTP/1.0 的一个核心诉求，而且文件格式不仅仅局限于 ASCII 编码，还有很多其他类型编码的文件。
>
> 为了让客户端和服务器能更深入地交流，HTTP/1.0 引入了`请求头`和`响应头`，它们都是以为 Key-Value 形式保存的，在 HTTP 发送请求时，会带上请求头信息，服务器返回数据时，会先返回响应头信息。\
> HTTP/1.0 的方案是通过请求头和响应头来进行协商，在发起请求时候会通过 HTTP 请求头告诉服务器它期待服务器返回什么类型的文件、采取什么形式的压缩、提供什么语言的文件以及文件的具体编码。

### 缝缝补补的HTTP/1.1

> 技术继续发展、需求不断迭代更新，HTTP/1.0也不能满足需求了，HTTP/1.1又在HTTP/1.0上继续更新：

#### 改进持久连接

> HTTP/1.1 中增加了持久连接的方法，它的特点是在一个 TCP 连接上可以传输多个 HTTP 请求，只要浏览器或者服务器没有明确断开连接，那么该 TCP 连接会一直保持。 HTTP 的持久连接可以有效减少 TCP 建立连接和断开连接的次数，这样的好处是减少了服务器额外的负担，并提升整体 HTTP 的请求时长。\
> 持久连接在 HTTP/1.1 中是默认开启的，所以你不需要专门为了持久连接去 HTTP 请求头设置信息，如果你不想要采用持久连接，可以在 HTTP 请求头中加上Connection: close。目前浏览器中对于同一个域名，默认允许同时建立 6 个 TCP 持久连接.

#### 不成熟的HTTP管线化

> 如果 TCP 通道中的某个请求因为某些原因没有及时返回，那么就会阻塞后面的所有请求，这就是著名的队头阻塞的问题。\
> HTTP/1.1 中试图通过管线化的技术来解决队头阻塞的问题。HTTP/1.1 中的管线化是指将多个 HTTP 请求整批提交给服务器的技术，虽然可以整批发送请求，不过服务器依然需要根据请求顺序来回复浏览器的请求。\
> FireFox、Chrome 都做过管线化的试验，但是由于各种原因，它们最终都放弃了管线化技术.

#### 提供虚拟主机的支持

> 在 HTTP/1.0 中，每个域名绑定了一个唯一的 IP 地址，因此一个服务器只能支持一个域名。\
> 但是随着虚拟主机技术的发展，需要实现在一台物理主机上绑定多个虚拟主机，每个虚拟主机都有自己的单独的域名，这些单独的域名都公用同一个 IP 地址。\
> 因此，HTTP/1.1 的请求头中增加了 Host 字段，用来表示当前的域名地址，这样服务器就可以根据不同的 Host 值做不同的处理。

#### 对动态生成的内容提供了完美的支持

> 在设计 HTTP/1.0 时，需要在响应头中设置完整的数据大小，如Content-Length: 901，这样浏览器就可以根据设置的数据大小来接收数据。\
> 不过随着服务器端的技术发展，很多页面的内容都是动态生成的，因此在传输数据之前并不知道最终的数据大小，这就导致了浏览器不知道何时会接收完所有的文件数据。 HTTP/1.1 通过引入 Chunk transfer 机制来解决这个问题，服务器会将数据分割成若干个任意大小的数据块，每个数据块发送时会附上上个数据块的长度，最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持。

#### 客户端Cookie、安全机制

> 除此之外，HTTP/1.1 还引入了客户端 Cookie 机制和安全机制。

## 30 ｜ HTTP/2：如何提升网络速度？

> HTTP/1.1为网络效率做了大量的优化，最核心的三种方式为：
>
> * 增加了持久连接。   &#x20;
> * 浏览器为每个域名最多同时支持6个TCP持久连接。   &#x20;
> * 使用CDN的实现域名分片机制。

### HTTP/1.1的主要问题

> HTTP/1.1对带宽的利用率却并不理想，这也是 HTTP/1.1 的一个核心问题. 带宽是指每秒最大能发送或者接收的字节数。我们把每秒能发送的最大字节数称为上行带宽，每秒能够接收的最大字节数称为下行带宽。
>
> 出现宽带利用率不理想的原因，主要为：
>
> * 第一个原因，TCP的慢启动。  &#x20;
> * 第二个原因，同时开启了多条TCP连接，那么这些连接会竞争固定的宽带。  &#x20;
> * 第三个原因，HTTP/1.1队头阻塞的问题。

### HTTP/2的多路复用

> HTTP/2 的解决方案可以总结为：一个域名只使用一个 TCP 长连接和消除队头阻塞问题.\
> 具体实现就是：通过引入二进制分帧层，实现 HTTP 的多路复用技术。

### HTTP/2其他特性

> * 可以设置请求的优先级。 &#x20;
> * 服务器推送。   &#x20;
> * 头部压缩。 &#x20;
>
> HTTP/2 协议规范于 2015 年 5 月正式发布，在那之后，该协议已在互联网和万维网上得到了广泛的实现和部署。从目前的情况来看，国内外一些排名靠前的站点基本都实现了 HTTP/2 的部署。使用 HTTP/2 能带来 20%～60% 的效率提升，至于 20% 还是 60% 要看优化的程度。总之，我们也应该与时俱进，放弃 HTTP/1.1 和其性能优化方法，去“拥抱”HTTP/2

## 31 | HTTP/3.0:甩掉TCP、TLS的包袱，构建高效网络

> 和通常一样，介绍 HTTP/3 之前，我们先来看看 HTTP/2 到底有什么缺陷。

### 1.TCP的队头阻塞

> 在 TCP 传输过程中，由于单个数据包的丢失而造成的阻塞称为 TCP 上的队头阻塞。\
> 有测试数据表明，当系统达到了 2% 的丢包率时，HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。

### 2.TCP建立连接的延时

> 网络延迟又称为 RTT（Round Trip Time）。我们把从浏览器发送一个数据包到服务器，再从服务器返回数据包到浏览器的整个往返时间称为 RTT。RTT 是反映网络性能的一个重要指标。

### 3.TCP协议僵化

> 虽然我们知道了TCP的队头阻塞和建立连接延时等缺点，但是通过改进TCP协议来解决这些问题非常困难，这里说的非常困难就是指TCP协议僵化。\
> TCP协议僵化体现在两个方面：第一个是中间设备的僵化；除中间设备的僵化外，操作系统也是导致TCP协议僵化的另外一个原因。

### QUIC协议

> HTTP/3 选择了一个折衷的方法——UDP 协议，基于 UDP 实现了类似于 TCP 的多路数据流、传输可靠性等功能，我们把这套功能称为 QUIC 协议。 HTTP/3 中的 QUIC 协议集合了以下几点功能:
>
> * 实现了类似 TCP 的流量控制、传输可靠性的功能。虽然 UDP 不提供可靠性的传输，但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。 &#x20;
> * 集成了 TLS 加密功能。  &#x20;
> * 实现了 HTTP/2 中的多路复用功能。 &#x20;
> * 实现了快速握手功能。

### HTTP/3的挑战

> 通过上面的分析，我们相信在技术层面，HTTP/3 是个完美的协议。不过要将 HTTP/3 应用到实际环境中依然面临着诸多严峻的挑战，这些挑战主要来自于以下三个方面:
>
> * 第一，从目前的情况来看，服务器和浏览器端都没有对 HTTP/3 提供比较完整的支持。Chrome 虽然在数年前就开始支持 Google 版本的 QUIC，但是这个版本的 QUIC 和官方的 QUIC 存在着非常大的差异。   &#x20;
> * 第二，部署 HTTP/3 也存在着非常大的问题。因为系统内核对 UDP 的优化远远没有达到 TCP 的优化程度，这也是阻碍 QUIC 的一个重要原因。 &#x20;
> * 第三，中间设备僵化的问题。这些设备对 UDP 的优化程度远远低于 TCP，据统计使用 QUIC 协议时，大约有 3%～7% 的丢包率。
