宋秋晓

You are the JavaScript in my HTML

0%

HTTP/3 快~来~了

前段时间看浏览器性能优化的时候,对比多家网站,发现某大型网站的服务还在使用 HTTP/1.1,没有使用 HTTP/2 ,然后突然就好奇 HTTP/3 怎么样了。。。就来挖一下 HTTP 的事情

img

然后就很感慨:

我们做的很多努力就是为了提升效率和安全

很久以前

谈未来之前,咱们先讲讲现实。你了解 HTTP 吗?这个定义于 1991 年的协议是用来管理 Web 的。它的全名是超文本传输 ​​ 协议,让你可以从网页中获取资源,网页数据从 Web 服务器传输到你的浏览器上。它基于较低级别的协议——TCP,这里是重点——而且它是无状态的。这意味着每个请求都是完全独立的。页面上显示的每个 GIF 图片都在互联网上独立存在,这对这些 GIF 图片本身来说是好事。但对我们来说,这样的一个系统是有些支离破碎的。

问题在于每个请求一次只会查找一个文件。每次都要创建一个昂贵的 TCP 连接。想象一下,如果你的页面上有 10,000 个小技巧,这会是多么沉重的负担啊。

为了更好地向大家解释互联网的协议机制,这里我找了个网上的图
img
尽管浏览器可以同时发出六个不同的请求,但是 HTTP 仍然很慢,并且需要很多 TCP 连接。另外,我们开发人员通常不会在意这一点。我们喜欢在页面上塞满各种垃圾。比如说巨大的 jQuery 库,包含 300 个无用的 CSS 样式表,结尾是一个透明的 8 兆大 PNG 图。

当谷歌发现我们在互联网上到处倾倒垃圾后,他们就开始搞一个称为 SPDY 的东西了。目的是什么呢?当然是加快互联网的速度。

SPDY 是一个规范,建议继续使用 HTTP,但要更改一些规则。通过压缩标头、对请求进行优先级排序和多路复用,它将把所有 TCP 请求和连接变成单独的一个!

具体来说,当你读取 HTML 时,浏览器会查看你在页面中要询问的所有内容。然后,它可以一次获取所有内容,这样就可以避免一个文件一个文件地获取了。

HTTP2 的第一份草案基于 SPDY。HTTP2 很快被广泛采用,随后互联网上的一切变得快多了。今天,互联网上 42.7%的内容使用 HTTP2。
img

铺垫了这么久,我们再从头来讲,HTTP 标准和 HTML 标准一样古老,都是由互联网之父 Tim Berners-Lee 在 1989 年发起,然后经由 IEFT 发展起来。不过 HTTP 第一个被广泛应用的版本是 0.9 版本,对我们影响比较多的是 1.0 版本和后来的 1.1 版本,我记得国内有些门户网站在 2010 年之后还在用 HTTP/1.0。

HTTP 时间轴

  • 1991, HTTP/0.9
  • 1996, HTTP/1.0
  • 1997, HTTP/1.1
  • 2009, SPDY
  • 2012, HTTP/2
  • 2018, HTTP/3

我们从 HTTP/1.1 开始来说

HTTP/1.1

HTTP/0.9 只支持 get 方法,然后 HTTP/1.0 定义了其它方法比如 post、put 等等,并且在通讯中指定版本以及请求头和响应头。当然这些还不够,所以在第二年,就又推出了 HTTP/1.1 版本,增加了很多特性:

  • 缓存机制
  • 增加长链接: keep-alive,并默认开启,这样就解决了每次请求完成之后就关闭造成的效率低下问题。
  • 分块传输:Transfer-Encoding:chunked
  • pipelining:流水线或者称为通信管道复用。值得注意的是,HTTP/1.1 在 1997 年就制定了,还是在 2009 年开始大规模使用然后被广为人知,从而被大规模使用。

img

HTTP/1.1 的问题

其实当时 HTTP 的效率已经「够用」了对吧?不是的,HTTP/1.1 当然不是完美的,有很多明显的问题:

  • 高延迟,队头阻塞带来的高延迟问题导致页面加载速度降低
  • 无状态特性,带来了巨大的 HTTP Header。比如,UA,Cookie,Accept,Server 等头部信息,可能会浪费几千字节的开销。而 Body 却可能只有几个字节。
  • 明文传输,不安全,一个是内容容易被监控,比如密码,被监控之后,就可能会被劫持(篡改)。
  • 不支持服务器推送。

所以,HTTP/1.1 的负面特征很明显:慢和不安全。

HTTPS?

安全问题当然是可以解决的,那就是使用 HTTPS。

HTTPS 不是新的协议,它其实是在 HTTP 层和 TCP 层之间加入了安全层,使用 SSL/TLS 协议来进行数据传输的加解密操作。

简单复习一下 SSL/TLS:
  • 1994 年,NetScape 公司设计了 SSL 协议(Secure Sockets Layer)的 1.0 版,但是未发布。
  • 1995 年,NetScape 公司发布 SSL 2.0 版,很快发现有严重漏洞。
  • 1996 年,SSL 3.0 版问世,得到大规模应用。
  • 1999 年,互联网标准化组织 IETF 接替 NetScape 公司,发布了 SSL 的升级版 TLS 1.0 版。
  • 2006 年,TLS 1.1 版。
  • 2008 年,TLS 1.2。
  • 2011 年,TLS 1.2 修订版 。
  • 2015 年,SSL 3.0 被中止支持。
  • 2018 年,TLS 1.3 发布,移除了 MD5、SHA1 和 RC4 的支持。
  • 2020 年,微软、Google、苹果、Mozilla 四家浏览器业者在 2020 年终止支持 TLS 1.0 及 1.1 版,新版的浏览器会警告页面不安全。

再来复习一下 HTTPS 的传输流程:
img
所以,使用了 HTTPS 的网站,访问起来更慢了!

那能不能不用 HTTPS?

当然不能啦。

其实大家在 2014 年之前对网络传输的安全问题并不太重视,因为没有出过什么问题,最多就是遇到运营商缓存问题。

嗯,没有遇到安全问题之前当然不会重视安全问题啦。

然而在 2014 年之后,开始遇到各种令人发指的中国网络运营商劫持,当时各大互联网服务都被劫持过,刚开始劫持整个页面,后来劫持 js 文件,甚至某省的运营商将公共 cdn 的 jquery 文件给劫持了

所以说,运营商其实是推动了 HTTPS 的普及了。

HTTP/2

那 Google 在发现了 HTTP 1.1 的弊端后,开始尝试解决。

然后 Google 搞了 SPDY,然后 SPDY 被 IETF 在 2015 年标准化为 HTTP/2。

这就是 Google 牛逼的地方:解决问题就是改变世界,某度也就搞个度娘娱乐一下。。。

HTTP/2 的特性:
  • 请求头压缩
  • 多路复用
  • 二进制传输
HTTP/2 VS HTTP/1.1:

img
所以,HTTP/2 最直接的效果就是:快!

有一个非常著名的 demo 展示 HTTP/2 有多快:HTTP/2: the Future of the Internet | Akamai

img
到目前为止,全球有 49.7% 的网站使用了 HTTP/2。 via Usage Statistics of HTTP/2 for Websites, December 2020

HTTP/2 一定要加密么?

是的

IETF 工作组在是否强制加密上有很大的争议,并且最后并没有达成一致,也就是说标准并没有说必须要加密。。。

不过大部分客户端实现的时候,让加密(HTTPS)成为事实上的标准了。

HTTP/2 的不足

嗯。。。上面提到的 HTTP 1.1 的两个关键问题在 HTTP/2 中并没有得到解决:

  • TLS 握手延时
  • 队头阻塞

嗯,HTTP/2 主要解决了通道的效率问题,但还是不够快。

TLS 1.3

上面 HTTP/2 的不足中,TLS 的握手延迟,是没办法避免的,不过 TLS 1.3 带来了很大的变化(虽然目前使用的还不多):

  • 快——TLS 1.2 及以下版本需要 2 次往返才能完成握手,也就是 2-RTT,而 TLS 1.3 可以做到 1-RTT 甚至 0-RTT
  • 更安全——废弃了 3DES、RC4、AES-CBC 等加密组件,废弃了 SHA1、MD5 等哈希算法。

HTTP/3

然后牛逼的 Google 又折腾出了 QUIC 协议(Quick UDP Internet Connections,快速 UDP 网络连接),算是抛弃了 TCP 协议了。

然后 IETF 接受了 HTTP Over QUIC 作为下一个 HTTP 版本的提议,将其命名为 HTTP/3。

先看下 HTTP/3 有多快:
img
有没有震惊到?

QUIC

大家都知道,UDP 比 TCP 快很多,但也有会丢包的问题,所以 UDP 的使用场景并没有那么流行,比如我们熟知的也就 QQ 在用 UDP,还有一些 DNS 服务使用 UDP。

那其实让 UDP 更稳定不就行了?QQ 其实是在 UDP 的基础上自己实现了一层协议来保证稳定性(重试)。

只是各自实现 UDP 扩展协议的做法不太「互联网」。

Google 的思路也是很简单:先搞定,再标准化。

事实上,QUIC 的拥塞算法是直接实现一遍 TCP 的算法。

那 QUIC 都做了些什么呢:

  1. 减少了 TCP 三次握手及 TLS 握手时间,甚至可以做到 0RTT。
  2. 改进的拥塞控制。
  3. 避免队头阻塞的多路复用。
  4. 连接迁移。
  5. 前向冗余纠错。

再来看一下架构图:
img

那么可以大规模使用了么?

还不行:

  • HTTP/3 还是草案状态,没有完全标准化
  • 浏览器还不支持——除了 MacOS Big Sur 以上版本的 Safari 浏览器以外,包括 Chrome 在内都需要手动开启支持。
如何启用?
  1. 改造自己的服务,比如,golang 有个 quic-go 的项目可以原生支持到 QUIC;
  2. 使用 web 服务比如 NGINX, NGINX 已经开发了 QUIC 分支,可以下载源代码自行编译。

向下兼容

你可能会说,HTTP/3 现在没法投入生成啊。。。

不急,其实可以先简单的升级一下 TLS 来提升 HTTP/2 的效率了,HTTP/3 正式发布了再支持也不迟。

升级到 TLS 1.3

要求:

  • Apache 版本 2.4.37 +
  • Nginx 版本 1.13.0+
  • OpenSSL 版本 1.1.1 +
  • 证书支持,也就是不能使用 SHA1/RC4 等加密的证书了

PS: IIS 的任何版本都不支持 TLS 1.3
升级也很简单,比如 Nginx 简单配置一下就行了:

1
ssl_protocols TLSv1.2 TLSv1.3;

效果:

毕竟 TLS 1.2 要 2 RTT,而 TLS 1.3 只需要 1 RTT,甚至 0 RTT,这里国外网站测试的数据通常是可以节省 100ms 以上的握手时间。 via https://medium.com/codavel-blog/measuring-tls-1-3-performance-ee301b1e8774

结语

我其实蛮期待如果证券交易所的服务支持了 HTTP/3 会发生什么事情。。。

参考文章

-------------本文结束感谢您的阅读-------------
1