Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/3 及 HTTP 发展史 #33

Open
Yuanfang-fe opened this issue Jun 2, 2021 · 0 comments
Open

HTTP/3 及 HTTP 发展史 #33

Yuanfang-fe opened this issue Jun 2, 2021 · 0 comments

Comments

@Yuanfang-fe
Copy link
Owner

Yuanfang-fe commented Jun 2, 2021

HTTP/2没用多久,HTTP/3就出来了,那让我们来看下 HTTP/3 带来了哪些新东西(解决了哪些问题)以及回顾下之前版本的优缺点。

版本 产生时间 内容 发展现状
HTTP/0.9 1991年 不涉及数据包传输,规定客户端和服务器之间通信格式,只能GET请求 没有作为正式的标准
HTTP/1.0 1996年 传输内容格式不限制,增加PUT、PATCH、HEAD、 OPTIONS、DELETE命令 正式作为标准
HTTP/1.1 1997年 持久连接(长连接)、节约带宽、HOST域、管道机制、分块传输编码 2015年前使用最广泛
HTTP/2 2015年 多路复用、服务器推送、头信息压缩、二进制协议等 逐渐覆盖市场

HTTP/0.9 和 HTTP/1.0 就不去探讨了,年代久远并且早就抛弃不用了,

HTTP/1.1

引入了持久连接(keep-alive),即在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。

先看个请求的例子,注意:图中的资源都在同一个域名下面
image

从上图中我们可以得到以下信息:

  • Connection ID 有多组,每组都有好几行,组与组之间可以是并行的
  • 相同的Connection ID 是串行的,也就是上一个请求返回了才会返回下一个

对于Connection ID,谷歌的开发人员是这么解释的:

The new Connection ID Network Panel column in Canary can help indicate to you that a TCP connection was reused instead of handshaking and establishing a new one.

翻译过来意思就是:

chrome devtools 中新的Connection ID 网络面板列可以帮助向您表明 TCP 连接被重用,而不是握手和建立新连接。

那猜测下请求应该是开了长连接,看了下确实都开启了长连接。如图:
image

除了长连接,HTTP 1.1 还加入了管道机制,管道机制允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。

HTTP1 0 vs HTTP1 1 (2)

但是新的问题也出现了,因为服务器必须按请求的顺序,逐个将文件发送到服务端, 如果一个响应返回发生了延迟,那么其后续的响应都会被延迟,直到队头的响应送达。这就是所谓的HTTP队头阻塞。

HTTP/2

HTTP/2 废弃了管道机制,创新性的引入了帧、消息和数据流的概念。一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成。客户端和服务端可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端重新组合。

  • 数据流: 已建立的连接内的双向字节流,可以承载一条或多条消息。
  • 消息: 与逻辑请求或响应消息对应的完整的一系列帧。
  • 帧: HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流。

这些概念的关系总结如下:

  • 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
  • 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。
  • 每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。
  • 帧是最小的通信单位,承载着特定类型的数据,例如 HTTP 标头、消息负载等等。 来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

http2 0

在这里关于流、消息、帧的逻辑关系要理解清楚,因为它很重要。
比如请求一个 a.js 和 b.js 文件, 会产生2个流 stream1、stream2。stream1 中的消息可以拆分为 Request Message1和 Response Message。 Request Message里面包含的是 HEADERS Frame(请求头),Response Message里头 和 数据是分开的,分别为HEADERS Frame(响应头)、DATA Frame。DATA Frame 可能有一个也可能有多个。
stream2 同理。

HTTP2 (4)

因为客户端与服务端之间是乱序发送的,简单来说就是谁反应快谁先发。

将 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP 2 最重要的一项增强。
事实上,这个机制会在整个网络技术栈中引发一系列连锁反应,从而带来巨大的性能提升,让我们可以:

  • 并行交错地发送多个请求,请求之间互不影响。
  • 并行交错地发送多个响应,响应之间互不干扰。
  • 使用一个连接并行发送多个请求和响应。
  • 不必再为绕过 HTTP/1.x 限制而做很多工作(请参阅针对 HTTP/1.x 进行优化,例如级联文件、image sprites 和域名分片。
  • 消除不必要的延迟和提高现有网络容量的利用率,从而减少页面加载时间。
  • 等等…

HTTP2 解决了HTTP1.1的 http队头阻塞问题,也就是服务端不用根据客户端请求的顺序来按需发送文件数据。可以交错的发送响应。效率快了很多

HTTP/3

HTTP2 看起来狠不戳啊,为什么才出现了短短两三年,HTTP/3 就出来了呢,要知道从HTTP1.1 到HTTP2 可是花了10多年的时间,是新时代的美国程序员也开始内卷了吗?

TCP 是基于不可靠的网路实现可靠传输,网络是存在丢包问题的,而为了给这个不靠谱的队友擦屁股,TCP 增加了重传机制,如果其中的某一个数据包没有按照顺序到达,接收端会一直保持连接等待数据包返回,这时候就会阻塞后续请求。这就发生了TCP队头阻塞。

tcp-chain-streams (2)

在 HTTP/2 不同数据流的帧是组合成一条链传输,如果链上的某一段出现丢包,那么由于TCP的重传机制,后面的数据传输都会被阻塞

归根结底是TCP的机制导致了TCP队头阻塞,HTTP/3 采用了新的QUIC协议,将数据流分开,有点类似HTTP1.1的长连接。

当我们在这个连接上建立两个不同的数据流时,它们互相独立。也就是说,如果一个数据流丢包了,只有那个数据流必须停下来,等待重传。

下面是两个端点间的示意图,黄色与蓝色是两个独立的数据流。

QUIC-chain-streams

那什么是QUIC?

QUIC 底层是基于UDP,虽然UDP不提供可靠的传输,但QUIC在基于UDP之时增加了一层带来可靠性的层。它提供了数据包重传、拥塞控制、调整传输节奏(pacing)以及其他一些TCP中存在的特性。

只要连接没有中断,从QUIC一端传输的数据迟早会出现在另一端。

QUIC 还有什么好处?

快速握手

QUIC提供0-RTT和1-RTT的连接建立,这意味着QUIC在最佳情况下不需要任何的额外往返时间便可建立新连接。其中更快的0-RTT仅在两个主机之间建立过连接且缓存了该连接的“秘密”(secret)时可以使用。

早期数据(Early data)

QUIC允许客户端在0-RTT的情况下直接捎带数据。这使得客户端能尽早向对方传送数据,当然也使得服务器能更快地发回数据响应。

参考:
https://http3-explained.haxx.se/zh/why-quic/why-h2
http://www.alloyteam.com/2020/05/14385/
https://network.51cto.com/art/202012/634943.htm
https://http3-explained.haxx.se/zh/zh

@Yuanfang-fe Yuanfang-fe changed the title HTTP/3 新特性 HTTP/3 及 HTTP 发展史 Jun 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant