HTTP1 HTTP2 HTTP3/QUIC | 青训营笔记

391 阅读4分钟

这是我参与[第三届青训营-后端场]笔记创作活动的第5篇笔记 ac22cf608c5373efa5090c8e374fab7.png

HTTP1

  • 队头阻塞:HTTP1是请求响应的模式,所以如果前一个请求阻塞了,后一个请求也会被阻塞,这是HTTP队头阻塞。
  • 传输效率低:如果传输的http报文数据少,容易出现头大体小的问题。
  • 明文传输:可读性强,对开发者来说可以高效的进行调试,但是容易泄露。(可以使用TLS加密)

HTTP2

  • 队头阻塞:不存在HTTP队头阻塞,但存在TCP队头阻塞。多个请求流复用同一条tcp连接,但接收方仍需要顺序接收,如果前面有报文片段丢失了,那么需等待重传,后续请求也会被阻塞。
  • 多路复用:HTTP2增加了一个流的概念,每个请求对应一个流ID,客户端流ID的奇数,服务端流ID是偶数。可以多条流同时存在连接上,不同流的报文可以乱序,同一个流的报文必须顺序串行。
  • 头部压缩:HPACK算法。服务端和客户端各自维护索引表。索引表包括静态表和动态表。静态表保存无需更新的头部字段。动态表是随着编解码随时更新的。

35fc22d22c50dea2f7b2e631c975258.png 如果要头部字段查表查到了,则可以使用索引代替头部字段的key-value,否则需要发送完整的头部字段并更新到索引表中。

  • 二进制帧协议:分为头部帧header和数据帧body。 (HTTP2不存在起始行,起始行的版本号,状态码,方法,URI等都变为了伪头部例如:authority,:method,:status)

de995b2d55479c78e3a269765cbb0c8.png

如图流ID是31bits,而客户端的流ID是奇数,所以一个连接客户端可以发送2^30个请求。如果流ID达到最大值后,可以发送GPAWAY帧,新创建一个TCP连接,流ID重新计数。

6b0b56f5b76f41c866b1ac7b4fdbda3.png

此外,可以发送RSTSREAM停止流的发送和接收,但不会断开TCP连接。

ade958d3a6d7f6d14c5349cc83c9233.png
流状态转化图

  • PushServer:向一个服务器请求一个页面后,服务器可以主动将页面包含的资源也推送给客户端。

HTTP3/QUIC

  • 基于UDP实现:选择UDP作为传输层协议,然后把tcp的连接管理,拥塞控制,流量控制,重传等搬过来,实现可靠传输,并且是可拔插的。
  • 解决队头阻塞:QUIC存在流的概念,但是如果一个流发送了丢包,不会阻塞到其他流,因为传输层使用的是UDP无连接的协议。
  • 加密握手次数减少:将密钥交换的步骤也加入到hello报文中。 TLS1.3+ 1646277581843.png
  • 快速启动:无需三次握手,TLS握手最多也只需要3次握手,并且TLS也支持0RTT

image.png (1)客户端:生成随机数 a,选择公开的大数 G 和 P,计算 A=a*G%P,将 A 和 G 发送给服务器,也就是 Client Hello 消息

(2)客户端:客户端直接使用缓存的 ServerConfig 计算通信密钥 initKEY = aB = ab*G%P,加密发送应用数据

(3)服务器:根据 Client Hello 消息计算通信密钥 initKEY = bA = ba*G%P

(4)服务器:生成随机数 c,计算 C=c*G%P,使用 initKey 加密 C,发送给客户端,也就是 Server Hello 消息

(5)客户端:使用 initKey 解码获取 C,计算会话密钥 sessionKey = aC = ac*G%P,加密发送应用数据 2

(6)服务器:计算会话密钥 sessionKey = cA = ca*G%P,解密获取应用数据 2

客户端缓存的 ServerConfig 是服务器静态配置的,是可以长期使用的。客户端通过 ServerConfig 实现 0-RTT 握手,使用会话密钥 sessionKey 保证通信数据的前向安全。

  • 可靠传输 QUIC传输单位有包和帧。包面向的是连接,帧面向的是流。多个帧组成一个流,对应一个请求。多个帧被打包成一个包进行传输。

b3205aedb7855264a9abec0edb7914a.png

ed97b4c7e457e9838a231af933ada1f.png

PKN和SACK机制。

image.png 与tcp一样,存在seq和ack机制,不同的是,QUIC包的序号会一直递增。

顺序接收:由于QUIC的包是一直递增的,无法通过包序号来进行顺序接收。QUIC在每个帧都有一个字段 stream offset,可以通过这个偏移量来对包进行顺序重组。

91a454b983afe859c70dbf23c0c8bb4.png

流量控制:跟tcp一样通过滑动窗口实现。但滑动窗口分为了connection和stream两个层面的窗口。每个stream都有一个窗口与之对应,只限制单个流,connection是面向整个连接的窗口,限制所有数据流的窗口。

image.png connection可用窗口的大小就是20+30+10=60

拥塞控制,超时重传,快速重传都跟TCP差不多,这里不做赘述。

连接迁移:一个TCP连接是通过四元组标识的,如果IP发生了变化,那么连接就会失效。QUIC使用了一个64位连接ID标识一个连接,这样即使切换了网络改变了IP地址,连接依旧正常。