一文搞定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协议取其精华弃其糟粕
参考资料
- [微信] 浅谈浏览器Http的缓存机制
- HTTP 协议中的 Transfer-Encoding
- QUIC 0-RTT实现简析及一种分布式的0-RTT实现方案
- [微信] HTTP/3 原理实战