HTTP版本发展与Google的暗中助力

本文参考资源:

http协议历史 - 承载梦想-韩旭明 - 博客园

HTTP 0.9 HTTP 1.0 HTTP 1.1 HTTP 2.0区别 - 武培轩 - 博客园

HTTP1.0 HTTP1.1 HTTP2.0 主要特性对比 - 前端碎碎念 - SegmentFault 思否

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解-网络编程/专项技术区 - 即时通讯开发者社区!

极客时间《透视HTTP协议》课程

HTTP协议概述

HTTP(HyperText Transfer Protocol)是一个简单的请求-响应协议,它通常运行在TCP之上。最初设想的基本理念是:借助多文档之间相互关联形成的超文本(HyperText),连成可相互参阅的 WWW(World Wide Web, 万维网)

HTTP的发展是由蒂姆·伯纳斯-李于1989年在欧洲核子研究组织(CERN)所发起。他提出万维网的核心概念有:
+ URI:即统一资源标识符,作为互联网上资源的唯一身份
+ HTML:即超文本标记语言,描述超文本文档
+ HTTP:即超文本传输协议,用来传输超文本。

HTTP版本审视

HTTP/0.9

20 世纪 90 年代初期的互联网世界非常简陋,计算机处理能力低,存储容量小,网速很慢,还是一片“信息荒漠”。网络上绝大多数的资源都是纯文本,很多通信协议也都使用纯文本,所以 HTTP 的设计也不可避免地受到了时代的限制。

这一时期的 HTTP 被定义为 0.9 版,结构比较简单,为了便于服务器和客户端处理,它也采用了纯文本格式。蒂姆·伯纳斯-李最初设想的系统里的文档都是只读的,所以只允许用“GET”动作从服务器上获取 HTML 文档(不能是其他格式),并且在响应请求之后立即关闭连接,功能非常有限。

这个时期的HTTP并没有作为正式的标准被建立。HTTP/0.9具有典型的无状态性,每个事务独立进行处理,事务结束时就释放这个连接。由此可见,HTTP协议的无状态特点在其第一个版本0.9中已经成型。一次HTTP/0.9的传输首先要建立一个由客户端到Web服务器的TCP连接,由客户端发起一个请求,然后由Web服务器返回页面内容,然后连接会关闭。如果请求的页面不存在,也不会返回任何错误码。

HTTP/1.0

1993 年,NCSA(美国国家超级计算应用中心)开发出了 Mosaic,是第一个可以图文混排的浏览器,随后又在 1995 年开发出了服务器软件 Apache,简化了 HTTP 服务器的搭建工作。同一时期,计算机多媒体技术也有了新的发展。这些新软件新技术一经推出立刻就吸引了广大网民的热情,更多的人开始使用互联网,研究 HTTP 并提出改进意见,甚至实验性地往协议里添加各种特性,从用户需求的角度促进了 HTTP 的发展。

于是在这些已有实践的基础上,经过一系列的草案,HTTP/1.0 版本在1996年的5月正式发布,并记载于RFC1945。虽然说是初期标准,但该协议标准至今仍被使用在服务器端。它在多方面增强了 0.9 版,形式上已经和我们现在的 HTTP 差别不大了,特点有:

  • 任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。
  • 除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段
  • 增加了响应状态码,标记可能的错误原因
  • 引入了协议版本号概念
  • 引入了 HTTP Header(头部)的概念,让 HTTP 处理请求和响应更加灵活
  • 其他还有支持长连接(使用Connection: keep-alive,但默认还是使用短连接),缓存机制,以及身份认证等

HTTP/1.0的不足:

HTTP1.0规定浏览器和服务器保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器处理完成后立即断开TCP连接(无连接),无法复用连接,服务器不跟踪每个客户端也不记录过去的请求(无状态)。然而TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。

其次就是队头阻塞(head of line blocking)。由于HTTP1.0规定下一个请求必须在前一个请求响应到达之前才能发送。假设前一个请求响应一直不到达,那么下一个请求就不发送,同样的后面的请求也给阻塞了。

为了解决这些问题,HTTP1.1出现了。

HTTP/1.1

1997年公布的HTTP/1.1是目前主流的HTTP协议版本。之前的标准是RFC2068,之后又发布了修订版RFC2616。

这个时期开始,HTTP协议已经成为了一份正式的标准”,而不是一份可有可无的“参考文档”。这意味着今后互联网上所有的浏览器、服务器、网关、代理等等,只要用到 HTTP 协议,就必须严格遵守这个标准,相当于是互联网世界的一个“立法”。

HTTP/1.1的特点有:

  • 引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,默认使用Connection: keep-alive客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接
  • 引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。需要注意的是,服务器必须按照客户端请求的先后顺序依次回送相应的结果,以保证客户端能够区分出每次请求的响应内容。而这个响应过程是串行的。
  • 新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名
  • 增加了缓存管理和控制;
  • 允许响应数据分块(chunked),利于传输大文件。对于一些很耗时的动态操作,服务器需要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)
  • 强制要求 Host 头,让互联网主机托管成为可能。
  • 提供了范围请求功能(宽带优化):HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。这是支持文件断点续传的基础。

HTTP/1.1的不足:

虽然1.1版允许复用TCP连接,但队头阻塞的问题仍存在,服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。

为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接(并发连接)。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。

SPDY协议与HTTP/2

HTTP/1.1标准数十年没有更新,而为了解决对队头阻塞的问题,只能使用切图、JS 合并等网页优化手段。

Google 对此表示不满,并着手致力改进HTTP/1.1协议。首先开发了自己的浏览器 Chrome,然后推出了新的 SPDY (读作SPeeDY)协议,并在 Chrome 里应用于自家的服务器。SPDY 没有完全改写 HTTP 协议,而是在 TCP/IP 的应用层与运输层之间通过新加会话层的形式运作。同时,考虑到安全性问题,SPDY 规定通信中使用 SSL。

后来随着Chrome后来日趋增高的用户占有率,SPDY也成为了主流的协议,终于,互联网标准化组织忍不住了,开始以 SPDY 为基础制定新版本的 HTTP 协议,最终在 2015 年发布了 HTTP/2,RFC 编号 7540。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

我查阅这部分资料的时候,翻到了数十年前的一条新闻,现在看还挺有意思的:

Google正制订一项新协议,旨在替换掉HTTP - InfoQ

SPDY的基本特征:
+ 多路复用流:SPDY允许在一个连接上无限制并发流。因为请求在一个通道上,TCP效率更高:更少的网络连接,发出更少更密集的数据包。
+ 请求优先级:虽然无限的并发流解决了序列化的问题,但他们引入了另一个问题:如果带宽通道受限制, 客户端可能会因防止堵塞通道而阻止请求。为了克服这个问题,SPDY实行请求优先级:客户端从服务器端请求它希望的项目数量,并为每个请求分配一个优先级。这可以防止在网络通道被非关键资源堵塞时,高优先级的请求被挂起。
+ HTTP报头压缩:SPDY压缩请求和响应HTTP报头,从而减少传输的数据包数量和字节数。
+ 推送功能:支持服务器主动向客户端推送数据的功能。这样,服务器可直接发送数据,而不必等待客户端的请求。

基于SPDY的HTTP2.0的特点:
+ 二进制协议,不再是纯文本
+ 可发起多个请求,废弃了 1.1 里的管道(多路复用)
+ 使用专用算法压缩头部,减少数据传输量
+ 允许服务器主动向客户端推送数据(和websocket有点不一样,它类似于预测用户要用到什么数据,提前推送给客户端)
+ 增强了安全性,“事实上”要求加密通信
+ 因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。

QUIC协议与HTTP/3

HTTP 2.0 虽然大大增加了并发性,但还是有问题的。因为 HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序的。当其中一个数据包遇到问题,TCP 连接需要等待这个包完成重传之后才能继续进行。虽然 HTTP 2.0 通过多个 stream,使得逻辑上一个 TCP 连接上的并行内容,进行多路数据的传输,然而这中间并没有关联的数据。一前一后,前面 stream 2 的帧没有收到,后面 stream 1 的帧也会因此阻塞,说到底这是TCP的固有问题。

于是Google又作妖了,着手研发QUIC协议。QUIC 是 Quick UDP Internet Connections 的缩写,在大概2014年的时候面世,它改造了UDP协议,通过UDP无连接的特性减小传输延迟,但改进和实现了部分TCP的功能,例如可靠传输。它和UDP一样是一个传输层的协议,在这种协议之上建立的HTTP协议称为HTTP over QUIC

HTTP over QUIC 相比现在广泛应用的 http2+tcp+tls 协议有如下优势:
+ 减少了 TCP 三次握手及 TLS 握手时间
+ 改进的拥塞控制
+ 避免队头阻塞的多路复用
+ 连接迁移
+ 前向冗余纠错

这里就不详细介绍Quic了,实际上自定义UDP实现TCP的功能的场景并不少见,这里面牵扯到自定义连接机制、自定义重传机制、自定义流量控制、自定义拥塞控制等实现。

2018 年,互联网标准化组织 IETF 提议将“HTTP over QUIC”更名为“HTTP/3”并获得批准,HTTP/3 正式进入了标准化制订阶段,也许两三年后就会正式发布,到时候我们很可能会跳过 HTTP/2 直接进入 HTTP/3。(持怀疑态度)

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/http%e7%89%88%e6%9c%ac%e5%8f%91%e5%b1%95%e4%b8%8egoogle%e7%9a%84%e6%9a%97%e4%b8%ad%e5%8a%a9%e5%8a%9b/