卧虎藏龙

Presentation 📽️ HTTPopen in new window

之前简单的介绍过,HTTP 是一种允许浏览器与服务器通信的协议,浏览器使用 HTTP 协议作为应用层协议,用来封装请求的文本信息。可是这 HTTP 的江湖,可不止这一角,不夸张的说,这里面卧虎藏龙呀。这还得从盘古开天辟地讲起...

HTTP知识图谱

HTTP/0.9

被设计用来在网络之间传递 HTML 超文本的内容,所以被称为超文本传输协议。基于请求响应模式,从客户端发出请求,服务器返回数据。当时简单的需求决定了它的局限:

  • 只有请求行
  • 服务器也没有返回头信息
  • 返回的文件内容(HTML)以 ASCII 字符流来传输

HTTP/1.0

在浏览器中展示的不单是 HTML 文件了,还包括了 JavaScript、CSS、图片、音频、视频等不同类型的文件。因此支持多种类型的文件下载是 HTTP/1.0 的一个核心诉求,而且文件格式不仅仅局限于 ASCII 编码,还有很多其他类型编码的文件。为此 http1.0 新增:

  • 请求头/响应头(浏览器和服务器的通信语言)
// 请求头-结束的形式
accept: text/html
accept-encoding: gzip, deflate, br
accept-Charset: ISO-8859-1,utf-8
accept-language: zh-CN,zh
User-Agent: xxx
// 响应头-最终返回的形式
content-encoding: br
content-type: text/html; charset=UTF-8
  • 响应行状态码
  • Cache

HTTP/1.1

  • 默认持久连接

  • 不成熟的管线化

    HTTP/1.1 中试图通过管线化的技术来解决队头阻塞的问题。 HTTP/1.1 中的管线化是指将多个 HTTP 请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。

  • 虚拟主机

    一个 IP 对应一个物理主机,物理主机绑定多个虚拟主机,每个虚拟主机都有自己的单独的域名,这些单独的域名都公用同一个 IP 地址。HTTP/1.1 的请求头中增加了 Host 字段,用来表示当前的域名地址,这样服务器就可以根据不同的 Host 值做不同的处理。

  • Chunk transfer 返回固定大小数据包可以在响应头设置Content-Length: 404告知浏览器;HTTP/1.1 通过引入 Chunk transfer 机制来解决动态内容无法确定大小的问题。服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。

  • 客户端 Cookie

  • 安全机制

HTTP/2

即使使用了很多优化手段:增加了持久连接; 浏览器为每个域名最多同时维护 6 个 TCP 持久连接; 使用 CDN 的实现域名分片机制。 HTTP/1.1 的主要问题在于无法充分利用带宽,1000M 宽度理论下载速度是 12.5M/s,实际上只有 2.5M/s。限制在于:

  • TCP 慢启动,慢启动是 TCP 为了减少网络拥塞的一种策略。每次传输数据包的大小成倍增加的
  • 竞争带宽,发生在多条 TCP 连接之间,影响关键资源的下载。
  • 队头阻塞,同一时刻只能处理一个请求

为了解决这些问题,HTTP2 特性就应运而生

  • 一个域名使用一个 TCP 长连接

  • 多路复用

    在 HTTP 协议的下层加上二进制分帧层,请求数据经过处理后,转换成带上对应 ID 的帧,请求数据分帧传输。同理,响应数据应如是,这就实现了数据的随意发送、资源的并行传输。

  • 设置请求优先级

  • 服务器推送

  • 头部压缩

HTTP/3

HTTP2 的局限主要在 TCP 协议上:

  • TCP 队头阻塞——丢包需要等待重传

    因为只有一个 TCP 连接,所以随着丢包率的增加,HTTP/2 的传输效率也会越来越差。有测试数据表明,当系统达到了 2% 的丢包率时,HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。

  • TCP 建立连接的延时 网络延迟又称为 RTT(Round Trip Time)。从浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为 RTT,RTT 是反映网络性能的一个重要指标。

    TCP 连接的建立最少需要经过三次握手阶段,在传输数据之前,我们需要花掉 3 ~ 4 个 RTT。如果浏览器和服务器的物理距离较近,那么 1 个 RTT 的时间可能在 10 毫秒以内,也就是说总共要消耗掉 30 ~ 40 毫秒。如果服务器相隔较远,那么 1 个 RTT 就可能需要 100 毫秒以上了,这种情况下整个握手过程需要 300 ~ 400 毫秒。

由于中间设备的僵化,更换 TCP 协议的阻力很大,于是 HTTP3 基于 UDP 设计了 QUIC 协议: HTTP3

  • 提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
  • 集成了 TLS 加密功能。
  • 同一物理连接上可以有多个独立的逻辑数据流,解决了 TCP 中队头阻塞的问题。

Think

  • 为什么是 HTTP2 而不是 HTTP1.2?
  • 那为什么是 HTTP2 而不是 HTTP2.0?