HTTP/2 和 HTTP/3 对比和相关知识解释
20 世纪 90 年代初,蒂姆-伯纳斯-李(Tim Berners-Lee)和他在欧洲核子研究中心(CERN)的团队共同制定了万维网的基础,定义了互联网的四个组成部分:
- 一种超文本文档格式(HTML)
- 数据传输协议(HTTP)
- 浏览超文本的网络浏览器(第一个浏览器,WorldWideWeb)
- 传输数据的服务器(httpd 的早期版本)
HTTP 重复使用现有的 TCP/IP 协议进行数据传输,HTTP 消息字节位于应用层,即下图中的浅蓝色部分。
HTTP/0.9
这是第一个 HTTP 草案。当时唯一的方法是 GET,没有标头和状态代码,唯一的数据格式是 HTML。与 HTTP/1.0 和 HTTP/1.1 一样,HTTP 消息也是 ASCII 文本结构。
HTTP/0.9 请求示例:
GET /mypage.html
响应示例:
<html>
A very simple HTML page
</html>
HTTP/1.0
该版本赋予了 HTTP 当前的结构,类似于备忘录,还引入了新的方法(HEAD 和 POST)、MIME 类型、状态代码和协议版本。
HTTP/1.0 请求示例:
GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
响应示例:
200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML>
A page with an image
<IMG SRC="/myimage.gif">
</HTML>
HTTP/1.1
该版本出现于 1997 年初,比前一版本晚了几个月。主要变化有
- 持久的 TCP 连接(keep-alive),节省了机器和网络资源。在前一版本中,每次请求都会打开一个新的 TCP 连接,并在响应后关闭。
- 主机标头,允许同一 IP 下有多个服务器。
- 编码、缓存、语言和 MIME 类型的标头约定。
HTTP/1.1 请求示例:
GET /api/fruit/orange HTTP/1.1
Host: www.fruityvice.com
Accept-Encoding: gzip, deflate, br
响应示例:
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Sun, 10 Mar 2024 20:44:25 GMT
Transfer-Encoding: chunked
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-store, must-revalidate, no-cache, max-age=0
Pragma: no-cache
X-Frame-Options: DENY
Content-Type: application/json
Expires: 0
{"name":"Orange","id":2,"family":"Rutaceae","order":"Sapindales","genus":"Citrus","nutritions":{"calories":43,"fat":0.2,"sugar":8.2,"carbohydrates":8.3,"protein":1.0}}
HTTP/2
2015 年,经过多年对互联网性能的观察和研究,在谷歌 SPDY 的基础上提出并创建了 HTTP/2。
其不同之处包括:在一个 TCP 数据包中复用多个报文;报文的二进制格式;报文头的 HPACK 压缩。
在 HTTP/1.1 中,两个请求不能同时使用同一个 TCP 连接–前一个请求结束后,后一个请求才能开始。这就是所谓的 “head-of-line” 阻塞。在下图中,考虑到只使用了一个 TCP 连接,请求 2 在响应 1 到达之前无法发送。
在 HTTP/2 中,这个问题通过流得到了解决,每个流对应一条信息。在一个 TCP 数据包中可以交错使用多个数据流。如果某个流因某种原因无法发送数据,其他流可以在 TCP 数据包中取而代之。
HTTP/2 数据流被划分为多个帧,每个帧包含:帧类型、所属数据流和长度(以字节为单位)。在下图中,彩色矩形表示 TCP 数据包,✉ 表示其中的 HTTP/2 帧。第一个和第三个 TCP 数据包携带不同流的帧。
在 HTTP/2 中,这个问题通过流得到了解决,每个流对应一条信息。在一个 TCP 数据包中可以交错使用多个数据流。如果某个流因某种原因无法发送数据,其他流可以在 TCP 数据包中取而代之。
HTTP/2 数据流被划分为多个帧,每个帧包含:帧类型、所属数据流和长度(以字节为单位)。在下图中,彩色矩形表示 TCP 数据包,✉ 表示其中的 HTTP/2 帧。第一个和第三个 TCP 数据包携带不同流的帧。
HTTP/3
HTTP/3 诞生于 2012 年由谷歌创建的新传输协议 QUIC。QUIC 被封装在 UDP 内,与 TCP 相比,它提出了:
- 减少建立连接和 TLS 验证的数据包往返次数;
- 在数据包丢失时,连接更有弹性;
- 解决 TCP 和 TLS 中存在的线头阻塞”head-of-line”问题。
HTTP/2 解决了 HTTP 的线头阻塞”head-of-line”问题,但 TCP 和 TLS 也存在这个问题。TCP 知道它需要发送的数据是连续的数据包序列,如果任何数据包丢失,就必须重新发送,以保持信息的完整性。对于 TCP,在丢失的数据包成功重新发送到目的地之前,不能发送后续数据包。
下图直观地解释了 HTTP/2 是如何做到这一点的。第二个数据包只有响应 1 的帧,但它的丢失会延迟响应 1 和响应 2,这意味着在这种情况下,不存在并行性。
为了解决 TCP 的head-of-line阻塞问题,QUIC 决定使用 UDP 作为其传输协议,因为 UDP 并不关心到达的保证。在 TCP 中,数据完整性是传输层的一部分,而在 QUIC 中,数据完整性的责任被转移到了应用层,信息帧可以不按顺序到达,而不会阻塞不相关的数据流。
与 TLS(SSL)有关的head-of-line 阻塞发生在 TCP 上,因为加密技术通常应用于整个信息内容,这意味着需要收到所有数据(所有数据包)才能进行解密。而 QUIC 的加密技术是针对每个 QUIC 数据包的,在数据包到达时进行解密,无需事先接收所有数据包。
TLS 与 TCP:
- 输入数据:A+B+C
- 加密数据: Crypt(A+B+C) = D+E+F
- 数据包D、E、F
- 接收:decrypt(D+E+F)
- A+B+C
使用 QUIC 的 TLS:
- 输入数据:A+B+C
- 加密数据: crypt(A) = X, crypt(B) = Y, crypt(C) = Z
- 数据包:X、Y、Z
- 接收:decrypt(X) + decrypt(Y) + decrypt(Z)
- A+B+C
对比表
HTTP/1.1 | HTTP/2 | HTTP/3 | |
---|---|---|---|
传输 协议 |
TCP, persistent connection |
TCP, persistent connection |
UDP, persistent connection |
Head-of-line 阻塞 |
HTTP/1.x HOL TCP HOL TLS HOL |
TCP HOL TLS HOL |
– |
信息格式 | ASCII text | binary | binary |
头部压缩 | – | HPACK | QPACK |
开始前 (握手)往返次数 |
3 1 from TCP +2 from TLS 1.2* |
2 1 from TCP +1 from TLS 1.3* |
0 0 from UDP +0 from TLS 1.3 with 0-RTT* |
连接识别 | source IP and port | source IP and port | connection ID**, resistant to IP changes |
加密技术 | optional; applied over the entire message |
optional; applied over the entire message |
embedded TLS 1.3; applied over each QUIC packet |
* TLS 1.2 要求加密握手需要 2 次往返,而 TLS 1.3 只需要 1 次,还可以选择 0-RTT(零往返时间恢复),即不需要先前的握手。但是,0-RTT 会导致replay attacks,因此并不安全。
根据一项研究,** QUIC 的连接 ID 可用于指纹识别,对用户隐私构成风险。
哪个版本最好?
目前最好的两个版本是 HTTP/2 和 HTTP/3。
HTTP/3 是为手机和卫星网络等不稳定连接而设计的。为了应对网络的不稳定性,QUIC 在数据流之间有很高的独立性,在数据包丢失时有很好的恢复能力。不过,HTTP/3 在性能上也有缺陷,主要表现在:1)由于 UDP 的使用率较低,路由器和操作系统在过去几十年中没有对 UDP 协议进行优化,因此它的速度比 TCP 慢;2)QUIC 使用的逐包加密技术需要更多的数学运算,效率不如 TCP 使用的全信息加密技术。此外,UDP 协议在某些网络中受到限制,以防止 UDP 泛洪攻击和 DNS 放大攻击等攻击。
在可靠和稳定的连接中,HTTP/2 的性能多次优于 HTTP/3。
一般来说,建议进行兼容性和性能测试,以确定哪个版本最合适,此外,服务器可以同时接受 HTTP/2 和 HTTP/3 连接,由客户端决定使用哪个版本。
本文文字及图片出自 HTTP/2 and HTTP/3 explained