写点什么

从 HTTP 到 HTTP/3 的发展简史

2020 年 11 月 19 日

从HTTP到HTTP/3的发展简史

本文最初发布于 scorpil.com 网站,经原作者授权由 InfoQ 中文站翻译并分享。


虽然 HTTP/3 规范仍处于起草阶段,但最新版本的 Chrome 浏览器已经默认支持它了。Chrome 拥有约 70%的浏览器市场份额,所以,可以说 HTTP/3 已经进入主流世界。



这一基础协议的最新修订版旨在让 Web 更加高效、安全并缩短内容交付延迟。从某些角度来说,它是 HTTP2 的完善:通过使用新的专用协议 QUIC 替换基础 TCP 协议来解决和之前类似的目标。


想要弄明白 QUIC 的优点,最好的办法是讲清楚 TCP 作为 HTTP 请求的传输方式有哪些不足之处。


为此,我们将从头开始细细道来。


HTTP:起源


1991 年,当蒂姆·伯纳斯·李爵士设计出一个简单的单行超文本交换协议时,TCP 已经是一个古老而可靠的协议了。前者的原始定义文档(也就是后人熟知的 HTTP 0.9)特别提到 TCP 是首选的(尽管并非唯一的)传输协议:


注意:HTTP 当前运行在 TCP 上,但也可以运行在任何面向连接的服务上。


当然,HTTP 的这个概念验证版本与我们现在所知道和喜欢的 HTTP 几乎没有相似之处。没有标头,也没有状态码。典型的请求只有GET/path而已。响应仅包含 HTML,且 TCP 连接关闭就会结束。


由于浏览器尚未流行,因此用户需要直接阅读 HTML。可以用它链接到其他资源,但是在这个 HTML 早期版本中存在的所有标签都不会异步请求其他资源。一个 HTTP 请求就传递了一个完整的、自给自足的页面。


HTTP/1.0 出现


在随后几年中,互联网迎来爆炸式的发展,尽管传输 HTML 仍然是 HTTP 的主要特色,但它逐渐发展成一种可扩展且灵活的通用协议。HTTP 的三大重要更新奠定了这一演变的基础:


  • 方法的引入使客户能确定其想要执行操作的类型。例如,引入 POST 是为了允许客户端将数据发送到服务器以处理和存储;

  • 状态码为客户端提供了一种确认服务器已成功处理请求的方法——如果处理失败,则可以用它了解发生了哪种错误;

  • 标头增加了将结构化文本元数据附加到可以修改客户端或服务器行为的请求和响应上的功能。例如,编码和内容类型头使 HTTP 不仅可以传输 HTML,还可以传输任何类型的负载。“压缩”标头允许客户端和服务器协商支持的压缩格式,从而减少了通过连接传输的数据量。


同时,HTML 也不断进化,支持了图像、样式和其他链接资源。


现在,浏览器需要执行多个请求来显示一个网页,而原始的“按请求连接”架构是做不到的。建立和终止 TCP 连接涉及大量的数据包来回交换,因此在延迟开销方面相对昂贵。网页不见得一定由单个文本文件组成,但是随着每页请求数量的增加,延迟也随之增加。


下图说明了每建立一个新的 TCP 连接涉及多少请求开销。



TCP 连接需要三个请求才能建立连接,四个请求可以完全关闭


人们创建了一个“连接”标头来解决这个问题。客户端发送带有“connection:keep-alive”标头的请求,以表明意图为后续请求保持 TCP 连接的打开状态。如果服务器理解此标头并同意遵守该标头,则其响应还将包含“connection:keep-alive”标头。


这样,双方都保持 TCP 通道打开并使用它进行后续通信,直到任何一方决定关闭它为止。随着 SSL/TLS 加密技术的发展,这一点变得更加重要,因为协商加密算法和交换加密密钥需要在每个连接上增加一个请求/响应周期。



单个 TCP 连接可以通过“connection:keep-alive”标头重用于多个请求


当时,许多 HTTP 改进都是自发出现的。当流行的浏览器或服务器应用程序需要新的 HTTP 功能时,它们会自己实现该功能,并希望其他各方也能效仿。具有讽刺意味的是,去中心化的 Web 需要一个中心化的管理机构来避免碎片化造成的不兼容问题。


该协议的最初创建者蒂姆·伯纳斯·李(TimBerners-Lee)意识到了这种危险,并于 1994 年成立了万维网联盟(W3C),该联盟与互联网工程任务组(IETF)一起致力于规范互联网的技术栈。作为为已有环境带来更多规范的第一步,他们记录了当时 HTTP 中最常用的一些功能,并将其命名为 HTTP/1.0 协议。


但是,由于这种“规范”描述的是多种多样的,通常在“实践”中用法不一致的技术,因此它从未获得过标准地位。相比之下,关于 HTTP 协议新版本的工作已经开始了。


HTTP/1.1 的标准化


HTTP/1.1 修复了 HTTP/1.0 的不一致之处,并调整了协议,使其在新的 Web 生态系统中具备更好的性能表现。新版引入的两个最关键的更改是默认使用持久 TCP 连接(保持活动状态)和 HTTP 管线化。


HTTP 管线化的意思就是客户端无需在发送后续 HTTP 请求之前等待服务器响应请求。此功能可以更有效地利用带宽并减少延迟,但它的改进空间甚至更大。HTTP 管线化仍要求服务器按照接收到的请求顺序进行响应,因此,如果管线化中的单个请求执行得很慢,则对客户端的所有后续响应都将相应地延迟下去。这个问题被称为线头阻塞。



由于首先请求了 large-picture.jpg,因此阻止了 style.css 的发布


在这个时候,Web 正在获得越来越多的交互功能。Web 2.0 指日可待,一些网页包含数十个甚至数百个外部资源。为解决线头阻塞,并降低页面加载速度,客户端会在每个主机上建立多个 TCP 连接。当然,连接开销并没有消失不见。实际上情况变得更糟了,因为越来越多的应用程序开始使用 SSL/TLS 加密 HTTP 通信。因此,大多数浏览器都设置了最大可能同时连接数的限制,以寻求微妙的平衡。


许多较大的 Web 服务已经意识到,现有的限制对于其交互极为繁重的 Web 应用程序来说太过严格,因此它们会通过多个域名分发其应用程序来“玩弄系统”。这种办法好歹起效了,但是解决方案根本谈不上优雅。


尽管存在一些缺点,但是 HTTP/1.0 和 HTTP/1.1 的简单性使它们获得了广泛的成功,并且十多年来,没有人认真地尝试过改变它们。


SPDY 和 HTTP/2


谷歌在 2008 年发布了 Chrome 浏览器,这种浏览器因其快速和创新而迅速流行。它使谷歌在互联网技术问题上获得了强大的话语权。在 2010 年代初期,谷歌在 Chrome 中增加了对其 Web 协议 SPDY 的支持。


HTTP/2 标准基于 SPDY,并进行了一些改进。HTTP/2 通过在单个打开的 TCP 连接上多路复用 HTTP 请求,解决了线头阻塞问题。这允许服务器以任何顺序响应请求,然后客户端可以在接收到响应时重新组合响应,从而在单个连接中加快整个交换的速度。



由于 HTTP/2 可以多路传输,因此在 large-picture.jpg 之前返回了 style.css


实际上,使用 HTTP/2 服务器甚至可以在请求之前就将资源提供给客户端!举个例子,如果服务器知道客户端很可能需要样式表来显示 HTML 页面,它可以将 CSS“推”到客户端,而无需等待相应的请求。虽然这从理论上讲是有益的,但此功能在实践中很少见,因为它需要服务器了解其服务的 HTML 结构,但这种情况很少发生。


除了请求正文以外,HTTP/2 还允许压缩请求标头,这进一步减少了通过网络传输的数据量。


HTTP/2 解决了 Web 上的许多问题,但不是全部。在 TCP 协议级别上仍然存在类似类型的线头问题,而 TCP 仍然是 Web 的基础构建块。当 TCP 数据包在传输过程中丢失时,在服务器重新发送丢失的数据包之前,接收方无法确认传入的数据包。由于 TCP 在设计上不遵循 HTTP 之类的高级协议,因此单个丢失的数据包将阻塞所有进行中的 HTTP 请求的流,直到重新发送丢失的数据为止。这个问题在不可靠的连接上尤为突出,这在无处不在的移动设备时代并不罕见。


HTTP/3 革命


由于 HTTP/2 的问题不能仅靠应用程序层来解决,因此协议的新迭代必须更新传输层。但是,创建新的传输层协议并非易事。传输协议需要硬件供应商的支持,并且需要大多数网络运营商的部署才能普及。由于此事涉及的成本和工作量,运营商们不愿进行更新。以 IPv6 为例:它是 24 年前推出的,但如今距离获得普遍支持还有很远的距离。


幸运的是还有另一种选择。UDP 协议与 TCP 一样得到广泛支持,但前者足够简单,可以作为在其之上运行的自定义协议的基础。UDP 数据包是一劳永逸的:没有握手、持久连接或错误校正。HTTP3 背后的主要思想是放弃 TCP,转而使用基于 UDP 的 QUIC 协议。QUIC 以对 Web 环境有意义的方式添加了许多必要的功能(包括以前由 TCP 提供的功能,以及更多功能)。


与 HTTP2 在技术上允许未加密的通信不同,QUIC 严格要求加密后才能建立连接。此外,加密不仅适用于 HTTP 负载,还适用于流经连接的所有数据,从而避免了一大堆安全问题。建立持久连接、协商加密协议,甚至发送第一批数据都被合并到 QUIC 中的单个请求/响应周期中,从而大大减少了连接等待时间。如果客户端具有本地缓存​​的密码参数,则可以通过简化的握手(0-RTT)重新建立与已知主机的连接。


为了解决传输级别的线头阻塞问题,通过 QUIC 连接传输的数据被分为一些流。流是持久性 QUIC 连接中短暂、独立的“子连接”。每个流都处理自己的错误纠正和传递保证,但使用连接全局压缩和加密属性。每个客户端发起的 HTTP 请求都在单独的流上运行,因此丢失数据包不会影响其他流/请求的数据传输。



HTTP/3 将连接分为单独的流


UDP 是一种无状态协议(持久连接只是其之上的抽象),使 QUIC 能够支持一些很大程度上忽略了数据包传递复杂性的功能。例如,从理论上讲,客户端更改其 IP 地址中间连接(例如智能手机从移动网络跳转到家庭 wifi)时不应中断连接,因为该协议允许在不同 IP 地址之间迁移而无需重新连接。


QUIC 协议的所有现有实现当前都在用户空间,而不是 OS 内核中运行。由于客户端(例如浏览器)和服务器的更新通常比操作系统内核更新的频率更高,因此人们希望可以藉此更快地采用新功能。


HTTP/3 存在的问题


我认为 HTTP/3 标准虽然是向更快、更安全的互联网迈出的一大步,但它并不完美。它的某些问题是由其新颖性引起的,而其他一些问题似乎是该协议固有的。


TCP 协议已经存在了很长时间,对于路由器来说很容易理解。它具有清晰的未加密标记(用于建立和关闭连接),可用于跟踪和控制现有会话。在网络硬件学会了解新协议之前,它将把 QUIC 流量简单地看作独立的 UDP 数据包流,这将使网络配置更加棘手。


从客户端缓存“恢复”连接的能力使该协议很容易遭受重播攻击:在某些情况下,恶意攻击者可以重新发送以前捕获的数据包,这些数据包将被服务器解释为有效的,来自受害者的。像那些提供静态内容的 Web 服务器一样,许多 Web 服务器不会受到此类攻击的伤害。对于身处易受攻击环境的应用程序来说,必须要记住禁用 0-RTT 功能。


这就是 HTTP 到今天为止的故事。我认为 HTTP/3 是向前迈出的一大步,并且当然希望 HTTP/3 在不久的将来会被广泛采用。


原文链接:


https://scorpil.com/post/the-long-road-to-http3/


2020 年 11 月 19 日 12:392110
用户头像
王强 技术是文明进步的力量

发布了 556 篇内容, 共 204.5 次阅读, 收获喜欢 1211 次。

关注

评论 1 条评论

发布
用户头像
http2 居然没有出关于隐私方面的加强。依然依靠 tls 协议,也就是我们常说的 https。继续做~
2020 年 11 月 20 日 09:08
回复
没有更多了
发现更多内容

Linux C/C++ 服务器/后端开发/后台开发学习路线

Linux服务器开发

C/C++ Linux服务器开发 Linux后台开发 Linux后端开发

IPFS怎么挖矿?怎么参与IPFS挖矿?

投资矿机v:IPFS1234

IPFS怎么挖矿 怎么参与IPFS挖矿

解Bug之路-主从切换”未成功”?

无毁的湖光

数据库 主从环境

从零开始写游戏服务器①:前期了解

Integer

c

c 语言思维地基搭建(vis2013编译+第一个c语言程序)

-jf.

四月日更

上来就问MySQL事务,瑟瑟发抖...

咔咔

MySQL 事务

Linux下使用简单的一条命令实现控制用户的目录访问权限

Machine Gun

Linux 网络安全 信息安全 linux 文件权限控制

面试阿里P6,却被MySQL难倒,二战阿里,挤进天猫团队(Java岗)

云流

Java 程序员 架构 面试

MySQL-技术专题-锁的介绍分析

李浩宇/Alex

MySQL lock 锁机制

真香!凭借这份Github上60K+star面试笔记,帮我搞定了字节跳动、阿里、华为、小米95%以上的Java面试题

Java成神之路

Java 程序员 架构 面试 编程语言

蚂蚁金服二面被血虐,鬼知道面试的我经历了什么?

Java成神之路

Java 程序员 架构 面试 编程语言

百度联合研究成果登上《自然》子刊 推动人才管理大数据智能化转型

百度大脑

百度 AI

你对JVM垃圾收集器了解多少?面试官夺命13问谁碰谁不迷糊啊!

北游学Java

Java JVM 垃圾回收

百度交易中台之订单系统架构浅析

百度Geek说

云计算 云原生 后端 云服务 架构·

webrtc 开启新特性

越努力,越幸运

第14期师资培训火热招生中尽享国赛智能车一手资料

百度大脑

人工智能

飞桨与宸曜科技完成兼容性认证

百度大脑

认证 飞桨

Python OpenCV 泛洪填充,取经之旅第 21 天

梦想橡皮擦

Python OpenCV 4月日更

Airtest入门及多设备管理总结

行者AI

自动化测试

MySQL查询优化必备

咔咔

MySQL 查询优化

一位阿里P8技术大牛的Java面试题总结,在GitHub上仅一天就获赞上万!

Java架构之路

Java 程序员 架构 面试 编程语言

学习笔记

山@支

AI开发降本提效之道:云智一体AI开发全栈模式

百度大脑

百度 AI 飞桨

什么是 Jenkins? 运用Jenkins持续集成

信码由缰

DevOps jenkins

如何保护您的SaaS应用程序?

龙归科技

网络安全 SaaS 远程工作 单点登录

聪明人的训练(八)

Changing Lin

4月日更

揭开MySQL索引神秘面纱

咔咔

MySQL 索引

MVCC:听说有人好奇我的底层实现

咔咔

MySQL MVCC

低代码平台想要实现复杂的业务流程,这4个条件不能少!

优秀

低代码

面试磕磕碰碰,辛得蚂蚁高级工程师的技术笔记指导,终获P7岗offer

Java成神之路

Java 程序员 架构 面试 编程语言

stream,source,track关系

越努力,越幸运

「中国技术开放日·长沙站」现场直播

「中国技术开放日·长沙站」现场直播

从HTTP到HTTP/3的发展简史-InfoQ