比较孤陋寡闻,只知道QUIC
TCP | QUIC | |
---|---|---|
握手延迟 | TCP需要三次握手+TLS握手 | 三次握手+TLS握手放在一起,实现0RTT |
头阻塞问题 | TCP丢失保文,会影响所有的应用数据包 | 基于UDP封装传输层Stream,Stream内部保序,Stream之间不存在相互影响 |
传输控制 | Seq二义性(重传)、SACK限制、RTT计算不准 | 吸取了TCP的问题,重新设计 |
连接迁移 | 五元祖实现连接标识 | 以一个 64 位的随机数作为 ID 来标识 |
实现层级 | 在传输层上实现 | 在应用层上实现 |
QUIC 流程简述
握手过程
连接机制
一条 TCP 连接是由五元组标识的,分别是源 IP、源端口、目的 IP、目的端口、协议号
而QUIC 自己的逻辑里面维护连接的机制,不再以五元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接
重传机制
TCP 为了保证可靠性,通过使用序号和应答机制,来解决顺序问题和丢包问题
在 TCP 里面存在超时的采样存在不准确的问题
- 发送一个包,发现没有返回,于是再发送,过一阵返回一个 ACK
- ACK的返回,让客户端知道这个包收到了。但是这个往返时间是在ACK的时间减去第一个包时间,还是减去第二个包时间?
QUIC 也有个序列号,是递增的。任何一个序列号的包只发送一次,下次就要加一了。但为了保证包内容的一致性,会存在一个offset的概念,offset是唯一的,如果某个offset对应的包没有就重发,通过这个offset拼接成一个完整的数据流
多路复用机制
HTTP 2.0 的多路复用问题
- HTTP/1.1可以使用多个TCP连接,但对连接数依然有限制,一次请求要等到连接中其他请求完成后才能开始(Pipeline机制也没能解决好这个问题),所以没有空闲连接的时候请求被阻塞,这是应用层的阻塞
- HTTP/2底层使用了一个TCP连接,上层虚拟了stream,HTTP请求跟stream打交道,无需等待前面的请求完成,这确实解决了应用层的队首阻塞问题
- 传输层的队首阻塞,TCP的应答是严格有序的,如果前面的包没到,即使后面的到了也不能应答,这样可能会导致后面的包被重传,窗口被"阻塞"在队首,这就是传输层的队首阻塞。 不管是HTTP/1.1还是HTTP/2
QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。但是,QUIC 是基于 UDP 的,一个连接上的多个 stream 之间没有依赖
流量控制
QUIC 的流量控制也是通过 window_update,来告诉对端它可以接受的字节数
QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发,中间的空档会等待到来或者重发即可,而窗口的起始位置为当前收到的最大 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存