浏览器原理与实现-学习6-http1/2/3

123 阅读4分钟

http1

http0.9特点

  • 只有一个请求行,并没有HTTP 请求头和请求体。
  • 服务器也没有返回头信息
  • 是返回的文件内容是以 ASCII 字符流来传输的

http1.0

  • 引入了请求头和响应头
    • 客户端告诉服务端:返回什么类型的文件、采取什么形式的压缩、提供什么语言的文件以及文件的具体编码。
      • accept: text/htmlaccept-encoding: gzip, deflate, braccept-Charset: ISO-8859-1,utf-8accept-language: zh-CN,zh
    • 服务端返回支持的压缩类型,文件语言和格式
      • content-encoding: brcontent-type: text/html; charset=UTF-8
  • 引入状态码
  • Cache 机制,用来缓存已经下载过的数据
  • 增加了用户代理UserAgent获取客户端的基础信息

http1.1

  • 改进了tcp持久连接
    • 优化了频繁建立和断开连接的开销
  • 尚未成熟的HTTP 管线化
    • 原因:当新的tcp请求,需要等待前面的完成,如果前面一直卡主就会发生队头阻塞
    • 管线化是指将多个 HTTP 请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。
  • 提供虚拟主机的支持,新增host字段区分同一域名下的那一台主机
  • 对动态内容的支持
    • 在1.0里文件都是有明确的Content-length:100
    • 很多文本其实是动态生成,无法告诉客户端具体的大小
    • Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。
  • 客户端 Cookie、安全机制

http2

http1.1的缺点,宽带使用率不高

  1. tcp慢启动,为了避免启动暂用太多资源,策略是先慢后快
  2. 多个tcp会互相竞争资源,当网速不足时,部分tcp会进行降速处理
  3. http队头阻塞
    • 管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。

解决方案

  • 多路复用
    • 一个域名只保留一个tcp,只有一次慢启动,也不存在资源竞争
    • 对头阻塞是通过把所有数据分帧传输,服务端选择性返回
  • 多路复用原理
    1. 在http 和 tcp中间 加入了 二进制分帧层
    2. http层数据会被转化为 一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器
    3. 服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息。
    4. 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
    5. 二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。
    6. 浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求。

其他特征

  • 支持请求设置优先级
  • 服务器推送
  • 头部压缩

http3

tcp的缺陷

  • 依然没有解决tcp层面包的队头阻塞问题,而且http2一个域名只有一个tcp,当丢包严重更容易导致全停顿
  • tcp 连接耗时
    • 3次握手需要1.5个RTT,ssl 握手1-2RTT,共需要3-4个RTT
    • Round Trip Time
      • 浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为 RTT
  • TCP 协议僵化,升级tcp版本很难
    • 中间设备的僵化
      • 早期很多硬件和软件都对tcp做了定制或优化
    • 操作系统只对tcp做了优化比较多

解决方案-QUIC

  • 实现了类似 TCP 的流量控制、传输可靠性的功能。
    • 虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
  • 集成了 TLS 加密功能。
    • 集成了 TLS1.3
  • 实现了 HTTP/2 中的多路复用功能。
    • 实现了在同一物理连接上可以有多个独立的逻辑数据流。实现了数据流的单独传输
  • 实现了快速握手功能。
    • 0-RTT 或者 1-RTT 来建立连接

http3面临的困难

  1. 服务端和客户端对http3的支持不够
  2. 各个操作系统对UDP的优化没有TCP那么完善和成熟
  3. 中间设备不怎么支持UDP,导致丢包率高

参考

time.geekbang.org/column/intr…