一文搞定http1.0 http1.1 http2(SPDY) http3.0(QUIC)核心原理

各版本 http 主要特点总结

版本特点总结

  • http1.0
    • TCP 频繁重建:频繁创建 TCP 连接的短连接模式(一个请求+一个响应就需要创建一个 TCP 连接)
  • http1.1
    • Consistent Connection 长连接: 强制开启长连接模式,TCP 信道可重用
    • pipelining: 支持流水线处理,可以允许先不等 response 回来,直接继续发送 request
    • cache control: 解决 1.0 缓存效率不高的问题
    • 分块传输编码 chunked: 支持分块则可以将一些大文件分段发送,减少等待时间
  • http2.0
    • 二进制分帧传输
    • header 压缩和 header cache
    • server push
  • http3.0/QUIC
    • 0 RTT 建立安全连接:基于 DH 秘钥交换算法,双方配合随机数协商出统一秘钥,然后开始加密传输。
    • 连接迁移:基于 UDP 实现,不依赖 TCP 四元组,QUIC 有自己的 connection ID,即使网络四元组变化了,仍然可以维持连接
    • 网络层无队头阻塞问题:TCP 本身也有队头阻塞问题,由于其需要有序处理 stream,一个流中网络包丢失阻塞会影响其他 stream 的处理,基于 UDP 的乱序处理,可以保证不同的请求之间隔离影响。
    • 新实现的拥塞控制:因为替换成 UDP 了,所以需要提供新实现的基于 UDP 的拥塞控制能力
    • 前向纠错:UDP 只有差错监测,没纠错,QUIC 通过一些数据冗余在应用层提供了类似 TCP 的纠错能力
    • 特性热插拔:因为核心能力都在用户态实现的,不依赖内核,调整拥塞控制算法等行为都变得更为简单

请求响应模型

历史

从问题出发加深理解

http1.1

持久连接和 1.0 中 keep alive 模式一样吗?

不一样的。http1.1 的 keep alive 由 Connection: keep alive 的 header 信息来控制。是基于心跳来维持长连接的。http1.1 的持久连接则是协议层面强制启用,只有当一侧主动断开的时候,连接才会断开。

pipelining 和 multiplexing 的区别

其实前文已经放图了,pipelining 是会有队头阻塞(HOL blocking)的问题的,本质上信道上的请求是按序发送和返回的。后面的 response 必须等前面的 response 成功。如果第一个 response 很慢的话,所有的请求都会被阻塞,而多路复用 multiplexing 就没这个问题

cache control 的引入解决 1.0 的什么问题?

1.0 只有 expire 和 pragma 两个参数控制缓存。其中 expire 是服务器告诉客户端需要设置的缓存过期时间。以下情况老的缓存交互方式没法解决:

  • 没有修改过的缓存内容支持复用:客户端上某个资源保存的缓存时间过期了,但这时候其实服务器并没有更新过这个资源。需要可以避免缓存失效而导致重复获取内容的方式。http 1.1 可以依靠 Last Modified 和 ETag 头部信息来处理。Etag 针对缓存资源生成一个唯一标识。

http 1.1 和 1.0 的 cache 头部信息一起存在时优先级怎样?

以 cache control 的为准

分块传输编码与 Content-Length 的关系

http1.1 中,客户端通过头部信息 Content-Length 来判断服务端是否已经发送了完整的数据。

  • 实际内容比 Content-Length 长:客户端截断数据
  • 实际内容比 Content-Length 短:客户端继续 pending 等待数据
  • 一致:结束连接

启用分块传输的话,Transfer-Encoding: chunked,那么就会禁用 Content-Length,因为大小是不确定的。最后一个分块的长度为 0,表示结束。

tips: HTTP2.0 中没有分块传输了,是基于二进制分帧传输了,自然也就没用 Transfer-Encoding 和 Content-Length 这些标记了

http 2.0

http2.0 和 google SPDY 协议什么关系?

spdy 先出来,http2.0 的主要特点基本上来源于 SPDY

http2.0 是否还有缺点?

有的,所以后来有 QUIC 和 http3.0,主要缺点如下。其实很多问题来源于 TCP 协议本身

  • 建连开销大:底下是基于 TCP 的,建连的开销是比较大的。随着 HTTPS 的流行,TLS+HTTP2.0 在频繁的通信下,仍然有较多的开销。TCP 握手(1 次 RTT)+TLS1.2(2 次 RTT)就总共需要 3RTT。在小数据量交互场景下,这个开销会占到总时间非常高的比重。即使用 TLS1.3 也还是最少要 2 次 RTT,而在 http3.0 中就引入了 0 RTT
  • **TLS 和 HTTP 之间融合不紧密有延迟:**HTTPS 协议本质是 HTTP over TLS,两个协议层之间交互会有额外开销

http3.0/QUIC

UDP 不是不可靠吗?QUIC 如何保证可靠性?

UDP 确实不可靠,但是为了保证可靠的机制,QUIC 在应用层(用户态)都实现了保证可靠的机制,例如 ACK 确认、重传、流控、纠错等。TCP 有的能力,QUIC 都有,还更好

如何理解 http3 协议改造的核心动机与本质工作?

仔细看了 HTTP3/QUIC 的原理和特点后,你会发现他们做的事情实际上就是“在用户态实现一个更好的 TCP+TLS+HTTP 整合协议”。主要还是 TCP 历史包袱重,强依赖内核,很多东西也不太好调整。基于 UDP 这个比较纯净、轻量的协议上重新实现重传、拥塞控制、安全等协议则可以更好的完成性能优化的目标。总结下他的本质工作主要是:

  • 更少的 RTT、高性能传输
  • 实现安全通信
  • 对 TCP 协议取其精华弃其糟粕

参考资料