HTTP协议发展史

2024-08 1

一个数据包的旅程

02-网络协议.png

  • 请求方要发送的数据包,在应用层加上HTTP头组成新的数据包交给传输层。
  • 传输层会在数据包前面附加上 TCP 头,组成新的 TCP 数据包,再将新的 TCP 数据包交给网络层;
  • 网络层再将 IP 头附加到数据包上,组成新的 IP 数据包,并交给底层;
  • 数据包被传输到目的地的网络层,在这里拆开 IP 头信息,并将拆开来的数据部分交给传输层;
  • 在传输层,数据包中的 TCP 头会被拆开,并根据 TCP 中所提供的端口号,把数据部分交给上层的应用程序;
  • 最终,含有“Web应用”信息的数据包就旅行到了目的地主机的上层应用程序这里。

超文本传输协议 HTTP/0.9

HTTP/0.9 是于 1991 年提出的,主要作用是在网络之间传递 HTML 超文本的内容,所以被称为超文本传输协议。其传输流程如下:

  • 因为 HTTP 都是基于 TCP 协议的,所以客户端先要根据 IP 地址、端口和服务器建立 TCP 连接,而建立连接的过程就是 TCP 协议三次握手的过程。
  • 建立好连接之后,会发送一个 GET 请求行的信息,如GET /index.html用来获取 index.html。
  • 服务器接收请求信息之后,读取对应的 HTML 文件,并将数据以 ASCII 字符流返回给客户端。
  • HTML 文档传输完成后,断开连接。

db1166c68c22a45c9858e88a234f1a34.png

总的来说,当时的需求很简单,就是用来传输体积很小的 HTML 文件,所以 HTTP/0.9 的实现有以下三个特点:

  • 第一个是只有一个请求行,并没有 HTTP 请求头和请求体,因为只需要一个请求行就可以完整表达客户端的需求了。
  • 第二个是服务器也没有返回头信息,这是因为服务器端并不需要告诉客户端太多信息,只需要返回数据就可以了。
  • 第三个是返回的文件内容是以 ASCII 字符流来传输的,因为都是 HTML 格式的文件,所以使用 ASCII 字节码来传输是最合适的。

被浏览器推动的 HTTP/1.0

随着万维网的高速发展,而 HTTP/0.9 已经不能适用新兴网络的需求。

首先在浏览器中展示的不单是 HTML 文件了,还包括了 JavaScript、CSS、图片、音频、视频等不同类型的文件。因此支持多种类型的文件下载是 HTTP/1.0 的一个核心诉求,而且文件格式不仅仅局限于 ASCII 编码,还有很多其他类型编码的文件。

因此HTTP/1.0 引入了请求头和响应头,它们都是以为 Key-Value 形式保存的,在 HTTP 发送请求时,会带上请求头信息,服务器返回数据时,会先返回响应头信息。

b52b0d1a26ff2b8607c08e5c50ae687d.png

引入请求头和响应头之后,HTTP/1.0的各种需求便可以借此满足了:

  1. 通过请求头的accept和响应头content-type字段,浏览器和服务器便完成了数据类型的传递。
  2. 通过请求头的accept-encoding和响应头的content-encoding字段,浏览器和服务器便完成了压缩类型的传递。
  3. 通过请求头的accept-language和响应头的Content-Language字段,浏览器和服务器便完成了语言版本的传递。
  4. 通过请求头的accept-Charset和响应头的content-type字段,浏览器和服务器便完成了编码形式的传递。(因为utf-8的广泛使用,accept-Charset已不再使用)
  5. 通过相应行的状态码字段,浏览器知道了服务器处理该请求的情况。
  6. 通过响应头的Expires字段为浏览器提供缓存机制。
  7. 通过请求头的用户代理User-Agent字段为服务器提供了用户客户端信息。

如下面这个例子,便是浏览器的请求头,它告诉服务器:期待服务器返回什么类型的文件、采取什么形式的压缩、提供什么语言的文件以及文件的具体编码。

accept: text/html
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh
accept-Charset: ISO-8859-1,utf-8

服务器接收到请求头后,会告诉浏览器它所支持的格式,比如服务器不支持 gzip,只支持 br 压缩,那么它会通过响应头中的 content-encoding 字段告诉浏览器最终的压缩类型,最终浏览器需要根据响应头的信息来处理数据。

content-encoding: br
content-type: text/html; charset=UTF-8

缝缝补补的 HTTP/1.1

随着技术的继续发展,很快 HTTP/1.0 也不能满足需求了,所以 HTTP/1.1 又在 HTTP/1.0 的基础之上做了大量的更新。

  1. **改进持久连接:**HTTP/1.0每次通信发送请求后都需要收到 ACK 消息,以确认对方已接收到数据。如果每次请求都要在收到上次请求的 ACK 消息后再请求,那么效率无疑很低。

    为此,HTTP/1.1 中增加了持久连接的方法,它的特点是在一个 TCP 连接上可以传输多个 HTTP 请求,只要浏览器或者服务器没有明确断开连接,那么该 TCP 连接会一直保持。

image-20240906211542597.png

在这个背景下,下面就来谈 HTTP/1.1 的队头阻塞。下图中,一个 TCP 连接同时传输 10 个请求,其中第 1、2、3 个请求已被客户端接收,但第 4 个请求丢失,那么后面第 5 - 10 个请求都被阻塞,需要等第 4 个请求处理完毕才能被处理,这样就浪费了带宽资源。

image-20240906211820855.png

因此,HTTP 一般又允许每个主机建立 6 个 TCP 连接,这样可以更加充分地利用带宽资源,但每个连接中队头阻塞的问题还是存在。

持久连接在 HTTP/1.1 中是Connection:keep-alive默认开启的,可在请求头加上Connection: close关闭。

  1. 支持管道传输:TCP请求有队头阻塞问题。HTTP/1.1尝试将多个 HTTP 请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。

    FireFox、Chrome 都做过管线化的试验,但是由于各种原因,它们最终都放弃了管线化技术

  2. 支持虚拟主机:HTTP/1.1 的请求头中增加了 Host 字段,表示当前的域名地址。多个域名地址可公用一个IP地址。服务器中可配置根据不同域名处理不同的请求。

  3. 客户端 Cookie、安全机制:HTTP/1.1 还引入了客户端 Cookie 机制和安全机制。

  4. 引入新的缓存策略:cache-control和协商缓存。

总结如下:

  1. 增加了持久连接;
  2. 浏览器为每个域名最多同时维护 6 个 TCP 持久连接;
  3. 使用 CDN 的实现域名分片机制。
  4. 引入新的缓存策略:cache-control和协商缓存。

推广中的HTTP/2.0

HTTP/1.0尚存在不少问题,其中最致命的是TCP的慢启动以及队头阻塞问题,针对这些问题,HTTP/2 协议规范于 2015 年 5 月正式发布,并做了如下优化:

  1. 多路复用:HTTP/2.0采用一个域名只建立一个TCP连链接、每个请求都被拆分成多个片段进行传输。并且重要的请求可以通过标记优先级让服务器优先处理。

4837434655a6d87f1bf5e3d899a698d1.png

  1. 服务器推送:服务器在接受到html文件的请求后,可以配置同时返回特定的cssjs文件,从而减少这两个文件的请求时间。

  2. 头部压缩:HTTP/2 对请求头和响应头进行了压缩。

缺陷:

  1. HTTP/2.0虽然引入了多路复用的机制,但是仍不能完美解决队头阻塞问题。如果请求的某个片段失败后,后续的请求仍然被阻止,这是TCP协议的特性,无法改变。有测试数据表明,当系统达到了 2% 的丢包率时,HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。

33d2b4c14a7a2f19ef6677696b67de96.png

  1. TCP每次通信都需要握手,三次握手带来了每次通信都会有1.5 RTT(Round Trip Time)的延迟。如果还要进行TLS连接,那么还会消耗1~2个RTT的延迟。因此在传输数据前,可能需要花费3~4个RTT的时间。

image-20240503163851082.png

未来的HTTP/3.0

鉴于TCP协议的根本性缺陷以及中间设备僵化等问题,HTTP/3.0摒弃了TCP协议,采用基于UDP协议的QUIC(Quick UDP Internet Connections)协议,该协议和TCP协议的对比如下:

0bae470bb49747b9a59f9f4bb496a9c6.png

  1. 实现了类似 TCP 的流量控制、传输可靠性的功能:提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。

  2. 集成了 TLS 加密功能:目前 QUIC 使用的是 TLS1.3,相较于早期版本 TLS1.3 有更多的优点,其中最重要的一点是减少了握手所花费的 RTT 个数。

  3. 实现了 HTTP/2 中的多路复用功能。和 TCP 不同,QUIC 实现了在同一物理连接上可以有多个独立的逻辑数据流(如下图)。实现了数据流的单独传输,就解决了 TCP 中队头阻塞的问题。

05cc5720989aec75730ee4cb7e7c149a.png

缺陷

  1. 服务器和浏览器端都没有对 HTTP/3 提供比较完整的支持。
  2. 部署 HTTP/3 也存在着非常大的问题。因为系统内核对 UDP 的优化远远没有达到 TCP 的优化程度,这也是阻碍 QUIC 的一个重要原因。
  3. 中间设备僵化的问题。这些设备对 UDP 的优化程度远远低于 TCP,据统计使用 QUIC 协议时,大约有 3%~7% 的丢包率。

参考链接:

  • HTTP