# HTTP 的发展历程

前言

了解http的发展历史,可以帮助我们更好的理解这项协议的内容。http协议自诞生到现在为止,共有四个版本,下面我们就来看看每个版本都有哪些作用,以及它是如何一步一步的演化成现在的协议版本的。

# HTTP/0.9

HTTP/0.9是最早的一个协议版本,它的内容非常简单:

  • 只有一个命令 GET
  • 没有描述实体内容的头部信息(headers)
  • 服务端返回的内容是html格式的字符串
  • 每个事务结束就释放连接。例如,客户端请求服务端的一个网页,服务端返回后,会关闭这次TCP连接。

举个例子,http/0.9的工作过程大概如下:

  1. 客户端发送请求:GET /index.html
  2. 服务端返回内容:<html>...</html>
  3. 关闭TCP连接,结束。

# HTTP/1.0

由于互联网的发展,http/0.9已经满足不了需求了,于是在它的基础上,http/1.0协议主要增加了以下内容:

  • 增加了请求头与响应头
  • 响应对象支持多种数据格式
  • 增加了状态码
  • 支持多种方法,比如POST,HEAD
  • 支持长连接(默认还是短连接)
  • 缓存机制(Pragma首部字段等)、身份验证、多字符集等

http/1.0增加的内容,很多我们现在都还在沿用。

# HTTP/1.1

http/1.1 是目前沿用最广泛的一个版本,它相对与1.0,主要增加了以下内容:

  • 默认使用长连接

    我们经常看到这个header字段:Connection: Keep-Alive,这是在http/1.1中默认开启的一个功能,它可以在每次请求完毕以后,依旧保持着这个TCP连接,这就极大的避免了1.0及以前版本的短连接方式带来的问题:重复创建TCP连接。我们知道,创建TCP需要客户端与服务端进行三次握手,如果每次请求都要重新创建新的TCP连接的话,那么就会增加很多的消耗和延迟,影响效率。

  • Pipeline
    Pipeline的技术可以让浏览器可以同时向服务器发送几个请求,收到请求的服务器必须按照请求的顺序来发送响应。这个看起来似乎很美好,但是实践的时候却会出现很多问题,比如:

    • pipelining只能适用于http1.1,一般来说,支持http1.1的server都要求支持pipelining
    • 只有幂等的请求(GET,HEAD)能使用pipelining,非幂等请求比如POST不能使用,因为请求之间可能会存在先后依赖关系
    • head of line blocking并没有完全得到解决,server的response还是要求依次返回,遵循FIFO(first in first out)原则。也就是说如果请求1的response没有回来,2,3,4,5的response也不会被送回来
    • 绝大部分的http代理服务器不支持pipelining
    • 和不支持pipelining的老服务器协商有问题
    • 可能会导致新的Front of queue blocking问题

所以浏览器大多数要么不支持,要么是默认关闭这个功能的。

  • 支持范围请求

    增加了请求头range来标识需要请求的资源的范围,和状态码206(Partial Content)来标识这次范围请求的成功状态。这很大程度上节省了带宽。试想一个很大的文件,我们下载到一半以后因为一些原因网络断开,这时候再次下载的时候,我们不希望还是从头下载。理想情况下,应该是从上次停掉的地方接着下载,这样才不会浪费。

  • 增加了host字段来提供虚拟主机的功能

    请求头新增了host字段来表示标识请求的目标主机。我们知道,一台物理主机上可以有多个虚拟主机,比如我有一个阿里云的服务器,我在上面部署了一个商城的服务,一个新闻的服务,当我从浏览器上访问的时候,实际上通过DNS解析后,最终都会通过IP地址找到我的这台阿里云服务器,但是具体找的是哪一个服务,我们可以通过host字段来判断。如果没有host字段或者host字段包含多个值的时候,服务器一般会返回400的错误码。

  • 更强大的缓存处理和更丰富的错误处理

    提供了E-TagCache-Control来进行更精确的缓存的控制;新增了很多状态码来表示可能出现的http错误信息等。

# HTTP/2.0

关于http2的介绍,可以具体的参考知乎上的这个讨论:知乎-HTTP/2 相比 1.0 有哪些重大改进。这里我只给出一个大概的介绍,它相对于1.1,做出了如下的改进:

  • 多路复用

多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。

  • 二进制分帧

HTTP/2在应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。

  • 首部压缩

使用HPACK算法对首部字段进行压缩,减少了传输的数据量。

  • 服务端推送

服务端推送是一种在客户端请求之前发送数据的机制。在 HTTP/2 中,服务器可以对客户端的一个请求发送多个响应。Server Push 让 HTTP1.x 时代使用内嵌资源的优化手段变得没有意义;如果一个页面的请求是由你发起的,服务器很可能会响应主页内容、logo、js脚本、样式表等,因为它知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源,不过与之相比,服务器推送还有一个很大的优势:可以缓存!也让在遵循同源的情况下,不同页面之间可以共享缓存资源成为可能。

# 参考资料

上次更新: 3/5/2020, 3:28:07 AM