协议|从HTTP到HTTP/3的发展简史( 二 )


3
HTTP/1.1 的标准化
HTTP/1.1 修复了 HTTP/1.0 的不一致之处,并调整了协议,使其在新的 Web 生态系统中具备更好的性能表现。新版引入的两个最关键的更改是默认使用持久 TCP 连接(保持活动状态)和 HTTP 管线化。
HTTP 管线化的意思就是客户端无需在发送后续 HTTP 请求之前等待服务器响应请求。此功能可以更有效地利用带宽并减少延迟,但它的改进空间甚至更大。HTTP 管线化仍要求服务器按照接收到的请求顺序进行响应,因此,如果管线化中的单个请求执行得很慢,则对客户端的所有后续响应都将相应地延迟下去。这个问题被称为线头阻塞。
协议|从HTTP到HTTP/3的发展简史
文章插图
由于首先请求了 large-picture.jpg,因此阻止了 style.css 的发布
在这个时候,Web 正在获得越来越多的交互功能。Web 2.0 指日可待,一些网页包含数十个甚至数百个外部资源。为解决线头阻塞,并降低页面加载速度,客户端会在每个主机上建立多个 TCP 连接。当然,连接开销并没有消失不见。实际上情况变得更糟了,因为越来越多的应用程序开始使用 SSL/TLS 加密 HTTP 通信。因此,大多数浏览器都设置了最大可能同时连接数的限制,以寻求微妙的平衡。
许多较大的 Web 服务已经意识到,现有的限制对于其交互极为繁重的 Web 应用程序来说太过严格,因此它们会通过多个域名分发其应用程序来“玩弄系统”。这种办法好歹起效了,但是解决方案根本谈不上优雅。
尽管存在一些缺点,但是 HTTP/1.0 和 HTTP/1.1 的简单性使它们获得了广泛的成功,并且十多年来,没有人认真地尝试过改变它们。
4
SPDY 和 HTTP/2
谷歌在 2008 年发布了 Chrome 浏览器,这种浏览器因其快速和创新而迅速流行。它使谷歌在互联网技术问题上获得了强大的话语权。在 2010 年代初期,谷歌在 Chrome 中增加了对其 Web 协议 SPDY 的支持。
HTTP/2 标准基于 SPDY,并进行了一些改进。HTTP/2 通过在单个打开的 TCP 连接上多路复用 HTTP 请求,解决了线头阻塞问题。这允许服务器以任何顺序响应请求,然后客户端可以在接收到响应时重新组合响应,从而在单个连接中加快整个交换的速度。
协议|从HTTP到HTTP/3的发展简史
文章插图
由于 HTTP/2 可以多路传输,因此在 large-picture.jpg 之前返回了 style.css
实际上,使用 HTTP/2 服务器甚至可以在请求之前就将资源提供给客户端!举个例子,如果服务器知道客户端很可能需要样式表来显示 HTML 页面,它可以将 CSS“推”到客户端,而无需等待相应的请求。虽然这从理论上讲是有益的,但此功能在实践中很少见,因为它需要服务器了解其服务的 HTML 结构,但这种情况很少发生。
除了请求正文以外,HTTP/2 还允许压缩请求标头,这进一步减少了通过网络传输的数据量。
HTTP/2 解决了 Web 上的许多问题,但不是全部。在 TCP 协议级别上仍然存在类似类型的线头问题,而 TCP 仍然是 Web 的基础构建块。当 TCP 数据包在传输过程中丢失时,在服务器重新发送丢失的数据包之前,接收方无法确认传入的数据包。由于 TCP 在设计上不遵循 HTTP 之类的高级协议,因此单个丢失的数据包将阻塞所有进行中的 HTTP 请求的流,直到重新发送丢失的数据为止。这个问题在不可靠的连接上尤为突出,这在无处不在的移动设备时代并不罕见。
5
HTTP/3 革命
由于 HTTP/2 的问题不能仅靠应用程序层来解决,因此协议的新迭代必须更新传输层。但是,创建新的传输层协议并非易事。传输协议需要硬件供应商的支持,并且需要大多数网络运营商的部署才能普及。由于此事涉及的成本和工作量,运营商们不愿进行更新。以 IPv6 为例:它是 24 年前推出的,但如今距离获得普遍支持还有很远的距离。
幸运的是还有另一种选择。UDP 协议与 TCP 一样得到广泛支持,但前者足够简单,可以作为在其之上运行的自定义协议的基础。UDP 数据包是一劳永逸的:没有握手、持久连接或错误校正。HTTP3 背后的主要思想是放弃 TCP,转而使用基于 UDP 的 QUIC 协议。QUIC 以对 Web 环境有意义的方式添加了许多必要的功能(包括以前由 TCP 提供的功能,以及更多功能)。
与 HTTP2 在技术上允许未加密的通信不同,QUIC 严格要求加密后才能建立连接。此外,加密不仅适用于 HTTP 负载,还适用于流经连接的所有数据,从而避免了一大堆安全问题。建立持久连接、协商加密协议,甚至发送第一批数据都被合并到 QUIC 中的单个请求 / 响应周期中,从而大大减少了连接等待时间。如果客户端具有本地缓存的密码参数,则可以通过简化的握手(0-RTT)重新建立与已知主机的连接。