http 1.0 1.1 2 3
2023-07-03 12:06:21
HTTP 1.0
1.0 的 HTTP 版本,是一种无状态,无连接的应用层协议。 HTTP1.0 规定浏览器和服务器保持短暂的链接。
浏览器每次请求都需要与服务器建立一个 TCP 连接,服务器处理完成以后立即断开 TCP 连接(无连接),服务器不跟踪也每个客户单,也不记录过去的请求(无状态)。
这种无状态性可以借助 cookie/session 机制来做身份认证和状态记录。
存在的问题 无法复用连接,每次发送请求,都需要进行一次 TCP 连接,而 TCP 的连接释放过程又是比较费事的。这种无连接的特性会使得网络的利用率变低。
队头阻塞(head of line blocking),由于 HTTP1.0 规定下一个请求必须在前一个请求响应到达之前才能发送,假设前一个请求响应一直不到达,那么下一个请求就不发送,后面的请求就阻塞了。
不支持断点续传,也就是说,每次都会传送全部的页面和数据。
HTTP 1.1
长连接,HTTP1.1 增加 Connection 字段,对于同一个 host,通过设置 Keep-Alive 保持 HTTP 连接不断。避免每次客户端与服务器请求都要重复建立释放建立 TCP 连接。提高了网络的利用率。
如果客户端想关闭 HTTP 连接,可以在请求头中携带 Connection:false 来告知服务器关闭请求。
支持断点续传,通过使用请求头中的 Range 来实现。
可以使用管道传输,多个请求可以同时发送,但是服务器还是按照顺序,先回应 A 请求,完成后再回应 B 请求。要是 前面的回应特别慢,后面就会有许多请求排队等着。这称为「队头堵塞」。
HTTP2.0
二进制分帧,HTTP2.0 通过在应用层和传输层之间增加一个二进制分层帧,突破了 HTTP1.1 的性能限制,改进传输性能。
多路复用(链接共享)— 真并行传输
流(stream):已建立连接上的双向字节流;
消息:与逻辑消息对应的完整的一系列数据帧;
帧(frame):HTTP2.0 通信的最小单位,每个帧包含头部,至少也会标识出当前所属的流(stream_id)。
所有 HTTP2.0 通信都在一个 TCP 链接上完成,这个链接可以承载任意流量的双向数据流。
每个数据流以消息的形式发送,而消息由一或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的流标识符(Stream_id)重新封装。
多路复用(连接共享)可能会导致关键字被阻塞,HTTP2.0 里每个数据流都可以设置优先级和依赖,优先级高的数据流会被服务器优先处理和返回客户端,数据流还可以依赖其他的子数据流。
可见,HTTP2.0 实现了真正的并行传输,它能够在一个 TCP 上进行任意数量的 HTTP 请求。而这个强大的功能基于“二进制分帧”的特性。
头部压缩,在 HTTP1.X 中,头部元数据都是以纯文本的形式发送的,通常会给每个请求增加 500-8000 字节的负荷。比如 cookie,默认情况下,浏览器会在每次请求的时候,把 cookie 附在 header 上面发给服务器。
HTTP2.0 使用 encoder 来减少需要传输的 header 大小,通讯双方各自 cache 一份 header_files 表,既避免重复 header 的传输,又减少了需要传输的大小。
高效的压缩算法可以很大的压缩 header,减少发送包的数量从而降低延迟。
服务器推送,服务器除了最初请求的响应外,服务器还可以额外向客户端推送资源,而无需客户端明确的需求。
HTTP 3.0
基于 Google 的 QUIC,HTTP3 背后的主要思想是放弃 TCP,转而使用基于 UDP 的 QUIC 协议。
与 HTTP2 在技术上允许未加密的通信不同,QUIC 严格要求加密后才能建立连接。此外,加密不仅适用于 HTTP 负载,还适用于流经连接的所有数据,从而避免了一大堆安全问题。建立持久连接、协商加密协议,甚至发送第一批数据都被合并到 QUIC 中的单个请求/响应周期中,从而大大减少了连接等待时间。如果客户端具有本地缓存的密码参数,则可以通过简化的握手(0-RTT)重新建立与已知主机的连接。
为了解决传输级别的线头阻塞问题,通过 QUIC 连接传输的数据被分为一些流。流是持久性 QUIC 连接中短暂、独立的“子连接”。每个流都处理自己的错误纠正和传递保证,但使用连接全局压缩和加密属性。每个客户端发起的 HTTP 请求都在单独的流上运行,因此丢失数据包不会影响其他流/请求的数据传输。
总结
HTTP 1.0
无状态,无连接; 短连接:每次发送请求都要重新建立 tcp 请求,即三次握手,非常浪费性能; 无 host 头域,也就是 http 请求头里的 host; 不允许断点续传,而且不能只传输对象的一部分,要求传输整个对象。
HTTP 1.1
- 长连接,流水线,使用 connection:keep-alive 使用长连接;
- 请求管道化;
- 增加缓存处理(新的字段如 cache-control);
- 增加 Host 字段,支持断点传输等;
- 由于长连接会给服务器造成压力。
HTTP 2.0
- 二进制分帧;
- 多路复用(或连接共享),使用多个 stream,每个 stream 又分帧传输,使得一个 tcp 连接能够处理多个 http 请求;
- 头部压缩,双方各自维护一个 header 的索引表,使得不需要直接发送值,通过发送 key 缩减头部大小;
- 服务器推送(Sever push)。
HTTP 3.0
- 基于 google 的 QUIC 协议,而 quic 协议是使用 udp 实现的;
- 减少了 tcp 三次握手时间,以及 tls 握手时间;
- 解决了 http 2.0 中前一个 stream 丢包导致后一个 stream 被阻塞的问题;
- 优化了重传策略,重传包和原包的编号不同,降低后续重传计算的消耗;
- 连接迁移,不再用 tcp 四元组确定一个连接,而是用一个 64 位随机数来确定这个连接;
- 更合适的流量控制。