HTTP 协议梳理

  最近,了解到优秀的 QUIC 协议以及基于 QUIC 的 HTTP 3。于是, 我梳理了一下 HTTP 的发展历程,总结整理了各个版本的特性。

  HTTP协议是超文本传输协议 Hyper Text Transfer Protocol 的缩写,是用于从万维网(WWW,World Wide Web )服务器传输超文本到本地浏览器的传送协议。HTTP 是基于 TCP/IP 协议的应用层协议。

HTTP 0.9 版本

  HTTP 0.9 版本于 1991 年发布,它不涉及数据包的传输,只规定了客户端和服务器之间的通信格式,默认使用 80 端口,该版本非常简单,只支持 GET 请求,没有首部,其设计目标也只是获取 HTML,也就是说只支持文本传输。经过随后几年的发展,HTTP 逐渐流行起来。截至 1995 年,世界上有超过 18000 台服务器在 80 端口处理 HTTP 请求。

HTTP 1.0 版本

  HTTP 1.0 版本于 1996 年 5 月发布,该版本大大丰富了 HTTP 的传输内容,为互联网的发展奠定了基础。相比 HTTP 0.9,HTTP 1.0 主要有以下特性:

  • 支持传输 HTML 文件以外其他类型的内容,这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。
  • 除了 GET 命令,还加入了 POST 、HEAD 等命令, 丰富了浏览器与服务器的交互手段。
  • HTTP 请求和回应的格式改变。 除了数据部分,每次通信都必须包括头信息,用来描述一些元数据。请求与响应支持 HTTP 头,增加了状态码。
  • ……

  但是,HTTP 1.0 版本还是存在一些缺点,其中主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。但是,TCP 新建连接的成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢,因为 TCP 通过慢开始启动。 所以,HTTP 1.0 版本的性能就比较差。随着网页加载的外部资源越来越多,这个问题就变得更加突出。

HTTP 1.1 版本

  HTTP 1.1 版本于1997年1月发布,直到现在它还是最流行的版本。它进一步完善了 HTTP 协议,主要有持久连接、管线化等新特性。

持久连接

  客户端发送请求时,在请求头部增加 Connection: keep-alive,即 TCP 连接时默认不关闭,可以被多个请求复用。客户端和服务器发现对方一段时间没有活动,也可以主动关闭连接。规范的做法是,客户端在最后一个请求时,发送 Connection: close,明确要求服务器关闭 TCP 连接。为了安全性,对于同一个域名,大多数浏览器允许同时建立 6 个持久连接。

1-1

  如图所示(图片引用自《图解HTTP》),在 HTTP 1.0 版本中,每个资源的下载都需要重新建立连接,每次建连都包含tcp的三次握手,完成数据传递后又通过tcp的四次挥手关闭连接。周而复始,访问一个较为复杂的网页会消耗大量的时间。采用持久连接后,服务端发出响应后让TCP连接继续打开着。同一对客户端/服务端之间的后续请求和响应可以通过这个连接发送。

   需要注意的是,HTTP 的 Keep-alive 主要是保持客户端与服务端的连接不会因为一次请求的结束而被关闭,以此来实现连接复用的目的。而 TCP 的 Keep-alive 则更像一种保鲜机制,即当连接建立后,相关socket可以定期向对端发送心跳包来检查连接是否还有效,用户可以设置相关的参数,包括多久开始发送、每次发送的间隔、发送次数等。如果一直没有收到对端的响应,则认为连接已经断开并释放相关资源。

管线化 pipeline

  HTTP 管线化是将多个 HTTP 请求整批提交的技术,而在传送过程中不需先等待服务端的回应。管线化机制须通过持久连接完成。浏览器将HTTP请求大批提交可大幅缩短页面的加载时间,特别是在传输延迟较高的情况下。如下图所示,有了持久连接的支持,就把多个HTTP请求放到一个TCP连接中发送,并且在发送过程中不需要等待服务器对前一个请求的响应;只不过,客户端还是要按照发送请求的顺序来接收响应。

1-2

  对头阻塞问题:如图所示,客户端依次发送了 3 个请求,假设服务端对第 1 个请求内容的处理是比较耗时的,在第 1 个请求处理完成之前,请求 2 和请求 3 都已经处理完成了,而此时,但是响应 2 和响应 3 还不能返回,必须等到响应 1 返回之后才能返回。更严重的是,如果服务端在处理pipeline请求的时候出现问题,那么排在后面的请求都会被阻塞。

不足之处

  虽然 HTTP 1.1 版本相比于以前的版本进行了比较大的优化,但是它依然存在以下问题:

  • 在传输数据时,每次都要重新建立连接,对移动端特别不友好。
  • 传输内容是明文,不够安全。
  • HTTP头部内容过大,每次请求的头部变化不大,造成浪费。
  • 持久连接给服务端带来性能压力。

SPDY 协议

  2009年,Google 公开了自行研发的 SPDY 协议, 目标是优化 HTTP 协议的性能,通过压缩、多路复用和优先级等技术,缩短网页的加载时间并提高安全性。其核心思想是尽量减少 TCP 连接数。SPDY 并不是一种用于替代 HTTP 的协议,而是对 HTTP 协议的增强。主要有以下改进:

  • 支持多路复用,实现请求优化。
  • 压缩了HTTP报文首部信息,节省了传输数据带宽。
  • 支持服务器推送技术。
  • 强制使用SSL传输协议,全部请求由SSL加密,信息传输更安全。

1-3

  SPDY 为 HTTP 2 版本的制定提供了原型和参考依据。2016年,Google 决定不再支持 SPDY 的开发,这也是为了给 HTTP 2 让路。

HTTP 2 版本

  HTTP 2 版本于 2015 年发布。因为标准委员会不打算再发布子版本,所以它不叫 HTTP 2.0 ,下一个新版本将是 HTTP 3。虽然 HTTP 2 版本基本沿用了 SPDY 的设计理念,但仍然存下以下差异:

  • HTTP 2 可以在TCP之上直接使用,而 SPDY 必须在 TLS 层之上。
  • 更加完善的协议商讨和确认流程。
  • 更加完善的服务器推送机制。
  • 新的头部压缩算法 HPACK。
  • 添加了控制帧的种类,对帧的格式考虑更加细致。

1-4

二进制分帧

  HTTP 2 在应用层与传输层之间增加一个二进制分帧层,使得客户端与服务器通过交换帧来通信,帧是通信的最小单位,以此达到在不改动 HTTP 的语义,HTTP 方法、状态码、URI 及首部字段的情况下。二进制分帧层会将所有传输的信息分为更小的消息和帧,并采用二进制格式编码,其中 HTTP 1.x 的首部信息会被封装到 Headers 帧,而 Request Body 则封装到 Data 帧。该机制使得 HTTP 2 突破了 HTTP 1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量。

多路复用

  所谓多路复用,即在一个 TCP 连接中存在多个流,即可以同时发送多个请求,对端可以通过帧中的表示知道该帧属于哪个请求。客户端乱序发送帧,到服务端后再根据每个帧首部的流标识符重新组装。通过该技术,可以避免 HTTP 旧版本的队头阻塞问题,极大提高传输性能。

  如图所示,HTTP 2 引入了流和帧的概念,将每个完整的请求响应过程称为一个流,再将每个流拆分为多个帧(包括数据帧,控制帧等)。通过流和帧将一个完成请求响应过程“打碎”,再按照优先级将多个流的帧数据混在一起发送到服务端,服务端再通过流ID和帧ID将数据还原,以同样的方式将数据传回给客户端。

1-5

数据流优先级

  虽然多路复用解决队头阻塞的问题,但是引入了另一个问题,即如何确保在有限的带宽中优先加载最重要的资源。多路复用机制有可能会影响重要资源的加载。因此,HTTP 2 对数据流可以设置优先级,优先级决定了客户端和服务端处理不同的流采用不同的策略。

服务端推送

  在 HTTP 2 中,服务器可以向客户发送请求之外的内容,比如正在请求一个页面时,服务器会把页面相关的 logo,CSS 等文件直接推送到客户端,而不会等到请求来的时候再发送,因为服务器认为客户端会用到这些东西。只有当服务端认为某些资源存在一定的关联性,即客户端申请了资源A,必然会继续申请资源B、资源C、资源D…的时候,服务端才会主动推送这些资源,以此来达到节省浏览器发送请求的过程。

头部压缩

  在HTTP 就斑斑中很多头部都是重复的甚至多余的,此外,有些头部的内容则比较庞大。由于 HTTP 是无状态协议,头部中每次会携带一些重复的信息,造成资源的浪费。因此,HTTP 2 使用首部表来跟踪和存储之前发送的键值对,对于相同的内容,不会再每次请求和响应时发送。将头部进行压缩不仅可以节省资源,还可以缩短数据传递的延迟。

HTTP 3 版本

  QUIC(Quick UDP Internet Connections)协议是 Google 提出的一种基于UDP的低延时、多并发的传输协议。如下图所示,它实现了基于 UDP 的 TLS + HTTP 2 功能。

1-6

  QUIC 将原来 TCP 在操作系统内核空间中的实现(例如,拥塞避免、流量控制、丢包重传等)转移到用户空间,这使得 QUIC 更加灵活。此外,由于 QUIC 不是在操作系统内核中进行开发,因此开发迭代速度相对较快,部署成本低、阻力小。QUIC 的最大优点是快,其主要有以下特性:

  • 0 RTT 。
  • UDP 之上的多路复用,避免了队头阻塞。
  • 连接迁移。
  • 前向冗余纠错。
  • ……

  Http-Over-QUIC 已经正式更名为 HTTP 3,这标志着 QUIC 会在随后的几年内成为支持 HTTP 的主要协议。

总结

  本文主要梳理了 HTTP 协议发展的历程,简单介绍了各个版本的新特性。对于 HTTP 2 以及 HTTP 3,其中有很多有意思的、值得探讨的机制,我将在后续的博客中详细介绍。

坚持原创技术分享,您的支持将鼓励我继续创作!