1.HTTP演变史
在我们更深入地研究 HTTP/3之前,让我们快速了解一下 HTTP 多年来的演变,以便更好地理解为什么需要HTTP/3: 1.1 HTTP 0.9:只有一行的协议 Tim Berners-Lee 最初的HTTP 建议是以简洁为出发点设计的,目的是推动他的另一个刚刚萌芽的思想——万维网的应用。1991年,是一个单纯的年代,网上只有文字,看不了图。
telnet example.com 80
GET /
<html>...
?
请求只有一行,包括GET 方法和要请求的文档的路径。响应是一个超文本文档,没有首部,也没有其他元数据,只有HTML。HTTP 0.9 的功能:
◎客户端 / 服务器、请求 / 响应协议;
◎ASCII 协议,运行于 TCP/IP 链接之上;
◎设计用来传输超文本文档(HTML);
◎服务器与客户端之间的连接在每次请求之后都会关闭。
1.2 HTTP 1.0:迅速发展及参考性RFC 1991 年到1995 年,HTML 规范和一种新型的名叫“Web 浏览器”的软件都获得了快速发展。于是,1996 年,HTTP 工作组发布了RFC 1945,在该文档中记录了许多HTTP/1.0实现的通用方法,于是HTTP/1.0就诞生了。HTTP 1.0 的请求对我们而言应该是非常熟悉的:
telnet example.com 80
GET / HTTP/1.0
User-Agent: HappyBrowser
Accept: */*
HTTP/1.0 200 OK
Content-Type: text/html
Server: HappyServer
<h1>It works</h1>
?
请求行中包含HTTP 版本号,随后是请求首部;响应状态,后跟响应首部。该协议的关键变化:
◎请求可以由于多行首部字段构成;
◎响应对象前面添加了一个响应状态行;
◎响应对象也有自己的由换行符分隔的首部 字段;
◎响应对象不局限于超文本;
◎服务器与客户端之间的连接在每次请求之后都会关闭。
1.3 HTTP 1.1:互联网标准 在1997年1月,发布了HTTP/1.1的第一个正式标准 RFC2068[2]。然后,在两年半之后的1999年6月,许多改进和更新被纳入该标准,并以 RFC 2616[3]的形式发布。
GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Host: www.example.club
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Sun, 28 Feb 2021 08:01:33 GMT
Content-Type: text/html
Content-Length: 3750
Last-Modified: Tue, 26 Nov 2019 05:45:22 GMT
Connection: keep-alive
ETag: "5ddcbbf2-ea6"
Accept-Ranges: bytes
◎新增了POTIONS、PUT、DELETE、TRACE、CONNECT等新方法;
◎强化了缓存管理和控制;
◎支持维持持久连接,支持通知服务器弃用连接;也就是说TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive;
◎请求HTML文件的时候要求携带编码、字符集、cookie元数据等信息;
◎支持原始HTML请求的分块响应,利于传输大文件;
HTTP 1.1 改变了HTTP 协议的语义,默认使用持久连接。换句话说,除非明确告知(通过Connection: close 首部),否则服务器默认会保持连接打开。不过,这个功能也反向移植到了HTTP 1.0,可以通过Connection: Keep-Alive 首部来启用。实际上,如果你使用的是HTTP 1.1,从技术上说不需要Connection: Keep-Alive 首部,但很多客户端还是选择加上它。
1.4 HTTP 1.X的缺陷
- 连接无法复用
连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对大量小文件请求影响较大(没有达到最大窗口请求就被终止)。 ◎HTTP/1.0 传输数据时,每次都需要重新建立连接,增加延迟。 ◎HTTP/1.1 加入 keep-alive 可以复用一部分连接,当页面上有大量元素时,这样的等待会造成页面内容的顺序加载,为了提高吞吐量,现在浏览器会对每个域名至多打开6个连接,并且重用它们。然而这样的提速仍不满足当前的性能要求,为此还有切分域名域(Sharding Dominant Domains)等优化方法。 - Head-Of-Line Blocking(HOLB)
导致带宽无法被充分利用。HOLB是指一系列包(package)因为第一个包被阻塞;当页面中需要请求很多资源的时候,HOLB(队头阻塞)会导致在达到最大请求数量时,剩余的资源需要等待其他资源请求完成后才能发起请求。 ◎HTTP 1.0:下个请求必须在前一个请求返回后才能发出,request-response对按序发生。显然,如果某个请求长时间没有返回,那么接下来的请求就全部阻塞了。 ◎HTTP 1.1:尝试使用 pipeling 来解决,即浏览器可以一次性发出多个请求(同个域名,同一条 TCP 链接)。但 pipeling 要求返回是按序的,那么前一个请求如果很耗时(比如处理大图片),那么后面的请求即使服务器已经处理完,仍会等待前面的请求处理完才开始按序返回。所以,pipeling 只部分解决了 HOLB。 1.5 HTTP 2.0:改进传输性能 随着我们越来越多地把应用(社交媒体、电子邮件、新闻和视频,以及个人的生活与工作内容)部署到Web 上,HTTP 的问题也出现了。今天,用户和Web 开发者都迫切想要通过HTTP 1.1 达到一种几近实时的响应速度和协议性能,而要满足这个需求,仅靠在原协议基础上修修补补是不够的。
2015 年,HTTP/2 发布。HTTP/2 是现行 HTTP 协议(HTTP/1.x)的替代,但它不是重写,HTTP 方法/状态码/语义都与 HTTP/1.x 一样。HTTP/2 基于 SPDY3,专注于性能,最大的一个目标是在用户和网站间只用一个连接(connection),主要有如下功能:
◎使用虚拟的流传输消息,解决了HTTP一个连接中应用层的队头阻塞的问题;
◎使用了二进制协议,不再是纯文本,避免文本歧义,缩小了请求体积;
◎实现了多路复用,提高了连接的利用率,在拥塞控制方面有了更好的能力提升;
◎使用HPACK首部压缩方案压缩头部信息,大大节约了带宽;
◎增强了安全性,使用HTTP/2,要求必须至少用TLS1.2;
◎允许服务器主动向客户端推送数据; 在 HTTP/2 中引入了多路复用的技术。多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。大家可以直观感受下 HTTP/2 比 HTTP/1 到底快了多少。有关HTTP/2的原理实现资料可见文末的参考资料。 目前腾讯云CDN也已支持HTTP2,只需在官网控制台对加速域名进行配置,即可完成对资源的http2支持,不需要源站支持http2。
2.HTTP3
虽然 HTTP/2 解决了很多之前旧版本的问题,但是它还是存在一个巨大的问题,主要是底层支撑的 TCP 协议造成的。上文提到 HTTP/2 使用了多路复用,一般来说同一域名下只需要使用一个 TCP 连接。但当这个连接中出现了丢包的情况,那就会导致 HTTP/2 的表现情况反倒不如 HTTP/1 了。因为在出现丢包的情况下,整个 TCP 都要开始等待重传,也就导致了后面的所有数据都被阻塞了。但是对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。
那么可能就会有人考虑到去修改 TCP 协议,其实这已经是一件不可能完成的任务了。因为 TCP 存在的时间实在太长,已经充斥在各种设备中,并且这个协议是由操作系统实现的,更新起来不大现实。基于这个原因,Google 就更起炉灶搞了一个基于 UDP 协议的 QUIC 协议,并且使用在了 HTTP/3 上,HTTP/3 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC。
由于HTTP/3还处于草案阶段,这里只对HTTP/3功能更做一个整体的介绍,下面是整体的架构图:
上面我们谈到到了 head-of-line blocking 的问题,这也是 HTTP3 最大改变的地方。它不使用 TCP 作为会话的传输层,而是使用 QUIC,一种新的互联网传输协议,除其他外,它在传输层引入了流作为最优先的传输。QUIC 流共享相同的 QUIC 连接,所以创建新的 QUIC 流不需要额外的握手和缓慢的启动,但是 QUIC 流是独立交付的,因此在大多数情况下,影响一个流的数据包丢失不会影响其他流,因为 QUIC 数据包封装在 UDP 数据包之上。
与 TCP 相比,使用 UDP 提供了更多的灵活性,并且使 QUIC 实现安装在用户空间(user-space)中ーー对协议实现的更新不像 TCP 那样与操作系统更新绑定在一起。使用 QUIC,HTTP 级别的流可以简单地映射到 QUIC 流之上,从而获得 HTTP/2的所有好处,而不会出现“head-of-line blocking”。
QUIC 还将典型的 3-way TCP 握手与 TLS 1.3 的握手相结合。组合这些步骤意味着默认情况下提供了加密和身份验证,并且还支持更快的连接建立。换句话说,即使 HTTP 会话中的初始请求需要一个新的 QUIC 连接,在数据开始流动之前产生的延迟也低于使用 TLS 的 TCP。
◎底层采用了UDP,通过在用户空间的QUIC协议保证了传输的可靠性;
◎引入了Connection ID,不再需要向TCP那样基于IP和端口进行绑定连接,支持连接迁移,也就是说,从移动网络,切换到WIFI,可以继续使用同一个连接;
◎头部压缩算法由HPACK替换为了QPACK,以便能够支持乱序发送,优化压缩率;
◎QUIC包含了一个内嵌的TLS1.3,因此支持1-RTT快速建立连接;
3.CDN中QUIC实践
腾讯云CDN当前已支持HTTP3,您可在官网产品文档中找到QUIC内测申请链接,通过内测审核后,只需要将域名接入到官网控制台,开启QUIC功能,即可完成对资源的HTTP3支持,不需要源站做任何改动,当前支持的QUIC版本有H3-Q050,Q046,Q043。访问流程如下所示: 3.1 协议协商 一般情况下,Chrome浏览器和服务器端协商使用QUIC协议要经过如下步骤:
-
客户端发出tcp请求 -
服务端如果支持quic可以通过响应头alt-svc告知客户端 -
客户端同时发起tcp连接和quic连接竞赛 -
一旦quic建立连接获胜则采用quic协议发送请求 -
如遇网络或服务器不支持quic/udp,客户端标记quic为broken -
传输中的请求通过tcp重发
Accept-Ranges: bytes
alt-svc: h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Connection: keep-alive
alt-svc 主要包含以下信息:
◎quic:监听的端口;
◎ma:有效时间,单位是秒,承诺在这段时间内都支持 QUIC;
◎版本号:QUIC 的迭代很快,这里列出所有支持的版本号。
在完成域名接入后,使用Chrome访问需要启动QUIC,chrome版本88.0.4324.182(正式版本)默认支持的QUIC协议是Q050: wireshark抓包分析:
[1] Web性能权威指南 [2] 一文读懂 HTTP/2 及 HTTP/3 特性 [3] HTTP/3 原理与实践 [4] HTTP探索之路 - HTTP1/HTTP2/QUIC [5] HTTP/3:让传输效率再一次起飞 | QUIC [6] HTTP3 协议
关注腾讯云CDN公众号,技术干货一手掌握!
|