前段时间看浏览器性能优化的时候,对比多家网站,发现某大型网站的服务还在使用 HTTP/1.1,没有使用 HTTP/2 ,然后突然就好奇 HTTP/3 怎么样了。。。就来挖一下 HTTP 的事情
然后就很感慨:
我们做的很多努力就是为了提升效率和安全
很久以前
谈未来之前,咱们先讲讲现实。你了解 HTTP 吗?这个定义于 1991 年的协议是用来管理 Web 的。它的全名是超文本传输 协议,让你可以从网页中获取资源,网页数据从 Web 服务器传输到你的浏览器上。它基于较低级别的协议——TCP,这里是重点——而且它是无状态的。这意味着每个请求都是完全独立的。页面上显示的每个 GIF 图片都在互联网上独立存在,这对这些 GIF 图片本身来说是好事。但对我们来说,这样的一个系统是有些支离破碎的。
问题在于每个请求一次只会查找一个文件。每次都要创建一个昂贵的 TCP 连接。想象一下,如果你的页面上有 10,000 个小技巧,这会是多么沉重的负担啊。
为了更好地向大家解释互联网的协议机制,这里我找了个网上的图
尽管浏览器可以同时发出六个不同的请求,但是 HTTP 仍然很慢,并且需要很多 TCP 连接。另外,我们开发人员通常不会在意这一点。我们喜欢在页面上塞满各种垃圾。比如说巨大的 jQuery 库,包含 300 个无用的 CSS 样式表,结尾是一个透明的 8 兆大 PNG 图。
当谷歌发现我们在互联网上到处倾倒垃圾后,他们就开始搞一个称为 SPDY 的东西了。目的是什么呢?当然是加快互联网的速度。
SPDY 是一个规范,建议继续使用 HTTP,但要更改一些规则。通过压缩标头、对请求进行优先级排序和多路复用,它将把所有 TCP 请求和连接变成单独的一个!
具体来说,当你读取 HTML 时,浏览器会查看你在页面中要询问的所有内容。然后,它可以一次获取所有内容,这样就可以避免一个文件一个文件地获取了。
HTTP2 的第一份草案基于 SPDY。HTTP2 很快被广泛采用,随后互联网上的一切变得快多了。今天,互联网上 42.7%的内容使用 HTTP2。
铺垫了这么久,我们再从头来讲,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 年开始大规模使用然后被广为人知,从而被大规模使用。
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 的传输流程:
所以,使用了 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:
所以,HTTP/2 最直接的效果就是:快!
有一个非常著名的 demo 展示 HTTP/2 有多快:HTTP/2: the Future of the Internet | Akamai
到目前为止,全球有 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 有多快:
有没有震惊到?
QUIC
大家都知道,UDP 比 TCP 快很多,但也有会丢包的问题,所以 UDP 的使用场景并没有那么流行,比如我们熟知的也就 QQ 在用 UDP,还有一些 DNS 服务使用 UDP。
那其实让 UDP 更稳定不就行了?QQ 其实是在 UDP 的基础上自己实现了一层协议来保证稳定性(重试)。
只是各自实现 UDP 扩展协议的做法不太「互联网」。
Google 的思路也是很简单:先搞定,再标准化。
事实上,QUIC 的拥塞算法是直接实现一遍 TCP 的算法。
那 QUIC 都做了些什么呢:
- 减少了 TCP 三次握手及 TLS 握手时间,甚至可以做到 0RTT。
- 改进的拥塞控制。
- 避免队头阻塞的多路复用。
- 连接迁移。
- 前向冗余纠错。
再来看一下架构图:
那么可以大规模使用了么?
还不行:
- HTTP/3 还是草案状态,没有完全标准化
- 浏览器还不支持——除了 MacOS Big Sur 以上版本的 Safari 浏览器以外,包括 Chrome 在内都需要手动开启支持。
如何启用?
- 改造自己的服务,比如,golang 有个 quic-go 的项目可以原生支持到 QUIC;
- 使用 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 会发生什么事情。。。