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协议的发展历程 #13

Open
zoro-web opened this issue Aug 2, 2020 · 0 comments
Open

HTTP协议的发展历程 #13

zoro-web opened this issue Aug 2, 2020 · 0 comments

Comments

@zoro-web
Copy link
Owner

zoro-web commented Aug 2, 2020

HTTP 1.0

  1. 引入了请求头和响应头
  2. 提供了 Cache 机制、用户代理、状态码等一些基础信息

问题:连接效率低下,传输速度低

HTTP1.1

  1. 增加持久连接Connection: keep-alive
  2. 增加了 Host 字段,用来表示当前的域名地址,这样服务器就可以根据不同的 Host 值做不同的处理。
  3. 引入 Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持。
  4. 引入Cookie

问题:对带宽的利用率不理想
原因:

  1. TCP 的慢启动
  2. 同时开启了多条 TCP 连接,那么这些连接会竞争固定的带宽
  3. HTTP/1.1 队头阻塞的问题——在一个管道(一个TCP连接)中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态

知识点: 慢启动和 TCP 连接之间相互竞争带宽是由于 TCP 本身的机制导致的,而队头阻塞是由于 HTTP/1.1 的机制导致的。

HTTP2.0

针对http1.1的缺点,HTTP2.0 的解决方案为:一个域名只使用一个TCP长连接和消除队头阻塞问题

  1. 多路复用——引入二进制分帧层
    • 经过二进制分帧层处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器
    • 服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息
    • 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层
    • 同样,二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器
    • 浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求
  2. 可以设置请求的优先级
  3. 服务器推送
  4. 头部压缩

问题:TCP的队头阻塞
例子:在 HTTP/2 中,多个请求是跑在一个 TCP 管道中的,如果其中任意一路数据流中出现了丢包的情况,那么就会阻塞该 TCP 连接中的所有请求,不同于 HTTP/1.1,使用 HTTP/1.1 时,浏览器为每个域名开启了 6 个 TCP 连接,如果其中的 1 个 TCP 连接发生了队头阻塞,那么其他的 5 个连接依然可以继续传输数据。所以随着丢包率的增加,HTTP/2 的传输效率也会越来越差。有测试数据表明,当系统达到了 2% 的丢包率时,HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。

思考: 既然TCP 协议存在队头阻塞和建立连接延迟等缺点,那我们是不是可以通过改进 TCP 协议来解决这些问题呢?
答案是:非常困难
原因:TCP 协议僵化

  1. 中间设备的僵化
    • 互联网是由多个网络互联的网状结构,为了能够保障互联网的正常工作,我们需要在互联网的各处搭建各种设备,这些设备就被称为中间设备
    • 这些中间设备有很多种类型,并且每种设备都有自己的目的,这些设备包括了路由器、防火墙、NAT、交换机等。它们通常依赖一些很少升级的软件,这些软件使用了大量的 TCP 特性,这些功能被设置之后就很少更新了
    • 如果我们在客户端升级了 TCP 协议,但是当新协议的数据包经过这些中间设备时,它们可能不理解包的内容,于是这些数据就会被丢弃掉。这就是中间设备僵化,它是阻碍 TCP 更新的一大障碍。
  2. 受限于操作系统
    • TCP 协议都是通过操作系统内核来实现的,应用程序只能使用不能修改。通常操作系统的更新都滞后于软件的更新,因此要想自由地更新内核中的 TCP 协议也是非常困难的

HTTP 3.0

既然无法通过修改TCP协议来解决问题,那思路就是绕过 TCP 协议,因为中间设备的僵化,这些设备只认 TCP 和 UDP,所以选择在UDP协议的基础再实现一套功能

  1. 基于 UDP 实现了类似于 TCP 的多路数据流、传输可靠性等功能,称之为 QUIC 协议
  • 实现了类似 TCP 的流量控制、传输可靠性的功能——UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
  • 集成了 TLS 加密功能
  • 实现了 HTTP/2 中的多路复用功能——消除TCP队头阻塞
  • 实现了快速握手功能

挑战

  1. 从目前的情况来看,服务器和浏览器端都没有对 HTTP/3 提供比较完整的支持
  2. 部署 HTTP/3 也存在着非常大的问题。因为系统内核对 UDP 的优化远远没有达到 TCP 的优化程度,这也是阻碍 QUIC 的一个重要原因。
  3. 中间设备僵化的问题。这些设备对 UDP 的优化程度远远低于 TCP,据统计使用 QUIC 协议时,大约有 3%~7% 的丢包率。
  4. 因为动了底层协议,所以 HTTP/3 的增长会比较缓慢,这和 HTTP/2 有着本质的区别。
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