HTTP 协议的发展史

目前经常被提及的 HTTP 协议有 0.9、1.0、1.1、2 和 3(QUIC 协议),至于 2 和 3 为什么没有小数点了是因为标准委员会不打算再发布子版本了,下面分别来介绍一下各个版本的历史及区别。

HTTP/0.9

现如今几乎没有人使用的版本。1990 年发布,不过那时的 HTTP 并没有作为正式的标准被建立,并且有严重设计缺陷,只支持 GET 方法,服务器只能回应 HTML 格式的字符串,不能回应别的格式,当服务器发送完毕,就关闭TCP连接。

HTTP/1.0

部分服务仍在使用。1996 年 HTTP 正式作为标准发布,1.0 版本新增的主要特性:

  • 支持了传输图像、视频、二进制文件,不再仅仅是 0.9 时的文本。
  • 新增了 POST、HEAD 命令。
  • 必须包含请求头和响应头信息,主要用于描述一些元信息(比如:状态码、缓存等)。

HTTP/1.0 在很长的一段时间都承担着 Web 传输的重要角色,但是随着大家的应用越来越复杂,它也暴露出一些问题:每个 TCP 连接只能发送一个请求,请求完成后就关闭。当需要重复向服务器请求数据的时候,需要重新建立 TCP 连接,随着现代应用的网络请求数增加,这个问题就愈发突出了。

HTTP/1.1

目前部分应用至今仍是在使用 HTTP/1.1 进行通信,由此可见它的这一次更新解决了大多数人的问题,那么我们来看看到底更新了啥吧。
在 1.0 版本发布几个月后,1997 年发 HTTP/1.1 版本,消除了大量歧义内容并引入了多项改进:

  • 引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用。

  • 引入了管道机制(pipelining),允许在第一个应答被完全发送之前就发送第二个请求,以降低通信延迟(注意这并不能解决队头阻塞的问题)。

  • 支持响应分块,对于一些很耗时的动态操作,服务器需要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用”流模式”(stream)取代”缓存模式”(buffer)。

  • 引入内容协商机制,包括语言、编码、类型等。并允许客户端和服务器之间约定以最合适的内容进行交换。

  • 新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。另外,客户端请求的头信息新增了Host字段,凭借 Host 标头,能够使不同域名配置在同一个 IP 地址的服务器上。

    虽然 1.1 版允许复用 TCP 连接,但是同一个 TCP 连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为”队头堵塞”(Head-of-line blocking)。为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入 CSS 代码、域名分片(domain sharding)等等。

HTTP/2

目前大部分应用都在使用 HTTP/2 进行通信。2015年,HTTP/2 发布了,支持了多路复用(丢包可能还是会导致队头阻塞)、Header 压缩等能力,高流量的站点最迅速的普及,在数据传输上节省了可观的成本和支出。

HTTP/2中,有两个概念非常重要:帧(frame)和流(stream)。帧是最小的数据单位,每个帧会标识出该帧属于哪个流,流是多个帧组成的数据流。

它的主要特性如下:

  • 二进制传输。HTTP/2 是二进制协议而不是文本协议,不再可读,也不可无障碍的手动创建,改善的优化技术现在可被实施。
  • 多路复用。所谓多路复用,即在一个TCP连接中存在多个流,即可以同时发送多个请求,对端可以通过帧中的表示知道该帧属于哪个请求。在客户端,这些帧乱序发送,到对端后再根据每个帧首部的流标识符重新组装。通过该技术,可以避免HTTP旧版本的队头阻塞问题,极大提高传输性能。
  • Header 压缩。因为 Header 在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本。在 HTTP/2中使用了 HPACK(HTTP/2 头部压缩算法)压缩格式对传输的 Header进行编码,减少了 Header 的大小。并在两端维护了索引表,用于记录出现过的 Header,后面在传输过程中就可以传输已经记录过的 Header 的键名,对端收到数据后就可以通过键名找到对应的值。
  • 服务端推送。允许服务器主动往客户端推送数据,一个常用的场景是服务端主动往客户端推送数据,实现预加载的一个能力。想象一个场景:拿微博举个例子,我们将资源打包时经常会分成多个 chunk(包),用户第一次访问时会请求发文列表的 chunk,这时候我们可以做的就是预判用户会点击文章详情页,所以服务端可以提前将详情页的 chunk 推送到浏览器,浏览器会进行 HTTP 缓存,用户再列表选中一个文章点击详情页的时候就命中了浏览器的缓存,达到了加快访问速度的目的。

HTTP/3

目前使用的服务很少。在 HTTP/3 中,将弃用 TCP 协议,改为使用基于 UDP 协议的 QUIC 协议实现。

此变化主要为了解决 HTTP/2 中存在的队头阻塞问题。由于 HTTP/2 在单个 TCP 连接上使用了多路复用,受到 TCP 拥塞控制的影响,少量的丢包就可能导致整个 TCP 连接上的所有流被阻塞。

QUIC 是一种实验性的网络传输协议,由 Google 开发,该协议旨在使网页传输更快。在 2018 年 QUIC 得到了 IETF 成员的接受,他们在 2018 年 11 月给出了官方批准,认可 HTTP-over-QUIC 成为 HTTP/3。

总结

HTTP 目前市面上大多数都停留在 HTTP/1.1 和 HTTP/2,个人觉得这两次更新很大程度上推动了 Web 应用的发展,所以这两个版本的协议对于目前来说值得深究一下,本文只做科普性的介绍,在此就不过深的去讲解了,后续如果有机会会另外写一篇文章来介绍,希望本文对你有所帮助😊。

Author: Wang Chunlin
Link: https://github.com/onechunlin/blog/2023/02/08/HTTP 协议的发展史/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.