HTTP前世今生

2019-11-12  本文已影响0人  道无虚

HTTP简介

HTTP (Hypertext transfer protocol) 翻译成中文是超文本传输协议,是互联网上重要的一个协议。由欧洲核子研究委员会 CERN 的英国工程师 Tim Berners-Lee v 发明的,同时他也是 WWW 的发明人,最初的主要是用于传递通过 HTML 封装过的数据。

在 1991 年发布了 HTTP 0.9 版,在 1996 年发布 1.0 版。1997 年是 1.1 版,1.1 版也是到今天为止传输最广泛的版本(初始RFC2068在1997年发布,然后在1999年被RFC2616取代,再在2014年被RFC7230/7231/7232/7233/7234/7235 取代)。

2015 年发布了 2.0 版,其极大的优化了 HTTP/1.1 的性能和安全性,而 2018 年发布的 3.0 版,继续优化 HTTP/2,激进地使用 UDP 取代 TCP 协议。

目前,HTTP/3 在 2019 年 9 月 26 日 被 Chrome、Firefox、和 Cloudflare 支持。下面会简单地说一下 HTTP 的前世今生,让大家学到一些知识,并希望可以在推动一下 HTTP 标准协议的发展。

HTTP 0.9/1.0

0.9 和 1.0 这两个版本,就是最传统的 Request – Response 的模式了。HTTP 0.9 版本的协议简单到极点,请求时不支持请求头,只支持 GET 方法,没了。HTTP 1.0 扩展了 0.9 版,其中主要增加了几个变化:

我们可以看到,HTTP 1.0 开始让这个协议变得很文明了,一种工程文明。因为:

国内很多公司 HTTP 无论对错只返回 200,这种把 HTTP Status Code 全部抹掉完全是一种工程界的倒退。

但是,HTTP 1.0 性能上有一个很大的问题,那就是每请求一个资源都要新建一个 TCP 链接。而且是串行请求,所以就算网络变快了,打开网页的速度也还是很慢。所以,HTTP 1.0 应该是一个必须要淘汰的协议了。

HTTP 1.1

HTTP/1.1 主要解决了 HTTP 1.0 的网络性能的问题,以及增加了一些新的东西:

HTTP/1.1 应该分成两个时代,一个是 2014 年前,一个是 2014 年后。因为 2014 年 HTTP/1.1 有了一组 RFC(7230 /7231/7232/7233/7234/7235),这组 RFC 又叫 “HTTP/2 预览版”。其中影响 HTTP 发展的是两个大的需求:

自从 2005 年以来,整个世界的应用 API 越来多,这些都造就了整个世界在推动 HTTP 的前进。我们可以看到,自 2014 的 HTTP/1.1 以来,这个世界基本的应用协议的标准基本上都是向 HTTP 看齐了。也许 2014 年前,还有一些专用的 RPC 协议。但是 2014 年以后,HTTP 协议的增强,让我们实在找不出什么理由不向标准靠拢,还要重新发明轮子了。

HTTP 2.0

虽然 HTTP/1.1 已经开始变成应用层通讯协议的一等公民了,但是还是有性能问题,虽然 HTTP/1.1 可以重用 TCP 链接,但是请求还是一个一个串行发的,需要保证其顺序。然而,大量的网页请求中都是些资源类的东西,这些东西占了整个 HTTP 请求中最多的传输数据量。所以,理论上来说,如果能够并行这些请求,那就会增加更大的网络吞吐和性能。

另外,HTTP/1.1 传输数据时,是以文本的方式。借助耗 CPU 的 Zip 压缩的方式减少网络带宽,但是耗了前端和后端的 CPU。这也是为什么很多 RPC 协议诟病 HTTP 的一个原因,就是数据传输的成本比较大。

其实,在 2010 年时,Google 就在搞一个实验型的协议,这个协议叫 SPDY。这个协议成为了 HTTP/2 的基础(也可以说成 HTTP/2 就是 SPDY 的复刻)。HTTP/2 基本上解决了之前的这些性能问题,其和 HTTP/1.1 最主要的不同是:

对于这些性能上的改善,在 Medium 上有篇文章 “ HTTP/2: the difference between HTTP/1.1, benefits and how to use it ” 你可看一下相关的细节说明和测试。

当然,还需要注意到的是 HTTP/2 的协议复杂度比之前所有的 HTTP 协议的复杂度都上升了许多许多。其内部还有很多看不见的东西,比如其需要维护一个 “优先级树” 来用于来做一些资源和请求的调度和控制。如此复杂的协议,自然会产生一些不同的声音,或是降低协议的可维护和可扩展性。所以也有一些争议。尽管如此,HTTP/2 还是很快地被世界所采用。

HTTP/2 是 2015 年推出的。其发布后,Google 宣布移除对 SPDY 的支持,拥抱标准的 HTTP/2。过了一年后,就有 8.7% 的网站开启了 HTTP/2,根据这份报告 ,截止至本文发布时(2019 年 10 月 1 日), 在全世界范围内已经有 41% 的网站开启了 HTTP/2。

HTTP/2 的官方组织在 Github 上维护了一份各种语言对 HTTP/2 的实现列表,大家可以去看看。

我们可以看到,HTTP/2 在性能上对 HTTP 有质的提高。所以,HTTP/2 被采用的也很快。如果你在你的公司内负责架构的话,HTTP/2 是你一个非常重要的需要推动的一个事。除了因为性能上的问题,推动标准落地也是架构师的主要职责。因为,你企业内部的架构越标准,你可以使用到开源软件,或是开发方式就会越有效率。跟随着工业界的标准的发展,你的企业会非常自然的享受到标准所带来的红利。

HTTP 3.0

然而,这个世界没有完美的解决方案。HTTP/2 也不例外,其主要的问题是:若干个 HTTP 的请求在复用一个 TCP 的连接,底层的 TCP 协议是不知道上层有多少个 HTTP 的请求的。所以,一旦发生丢包,造成的问题就是所有的 HTTP 请求都必须等待这个丢了的包被重传回来,哪怕丢的那个包不是我这个 HTTP 请求的。因为 TCP 底层是没有这个知识了。

这个问题又叫 Head-of-Line Blocking 问题,这也是一个比较经典的流量调度的问题。这个问题最早主要的发生的交换机上。下图来自 Wikipedia。

WeChat Image_20191009085733.jpg

图中,左边的是输入队列。其中的 1、2、3、4 表示四个队列,四个队列中的 1、2、3、4 要去右边的 Output 的端口号。此时,第一个队列和第三个队列都要写右边的第四个端口。然后,一个时刻只能处理一个包。所以,一个队列只能在那等另一个队列写完。其此时的 3 号或 1 号端口是空闲的,而队列中的要去 1 和 3 号端口号的数据,被第四号端口给 Block 住了。这就是所谓的 HOL Blocking 问题。

HTTP/1.1 中的 Pipeline 中如果有一个请求 Block 了,那么队列后请求也统统被 Block 住了;HTTP/2 多请求复用一个 TCP 连接,一旦发生丢包就会 Block 住所有的 HTTP 请求。这样的问题很讨厌。好像基本无解了。

是的 TCP 是无解了,但是 UDP 是有解的 !于是 HTTP/3 破天荒地把 HTTP 底层的 TCP 协议改成了 UDP!

然后又是 Google 家的协议进入了标准 – QUIC (Quick UDP Internet Connections)。接下来是 QUIC 协议的几个重要的特性,为了讲清楚这些特性,我需要带着问题来讲(注:下面的网络知识,如果你看不懂的话,你需要学习一下 《TCP/IP 详解》 一书( 在我写 Blog 的这 15 年里,这本书推荐了无数次了),或是看一下本站的 《 TCP 的那些事》。):

所以,QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议。

但是对于 UDP 还是有一些挑战的,这个挑战主要来自互联网上的各种网络设备。这些设备根本不知道是什么 QUIC,他们看 QUIC 就只能看到的就是 UDP,所以,在一些情况下,UDP 就是有问题的。

好了,就算搞定上面的东西,还有一些业务层的事没解。这个事就是 HTTP/2 的头压缩算法 HPACK,HPACK 需要维护一个动态的字典表来分析请求的头中哪些是重复的,HPACK 的这个数据结构需要在 Encoder 和 Decoder 端同步这个东西。在 TCP 上,这种同步是透明的,然而在 UDP 上这个事不好干了。所以,这个事也必须要重新设计了,基于 QUIC 的 QPACK 就出来了,利用两个附加的 QUIC Steam,一个用来发送这个字典表的更新给对方,另一个用来 Ack 对方发过来的 Update。

目前看下来,HTTP/3 目前看上去没有太多的协议业务逻辑上的东西,更多是 HTTP/2 + QUIC 协议。但 HTTP/3 因为动到了底层协议,所以,在普及方面上可能会比 HTTP/2 要慢的多的多。但是,可以看到 QUIC 协议的强大。细思及恐,QUIC 这个协议真对 TCP 是个威胁,如果 QUIC成熟了,TCP 是不是会有可能成为历史呢?

未来十年,让我们看看 UDP 是否能够逆袭 TCP……

原文链接

上一篇 下一篇

猜你喜欢

热点阅读