quic协议go语言 quit协议( 二 )


这就出现了两个握手延迟:
1)TCP 三次握手导致的 TCP 连接建立的延迟;
2)TLS 完全握手需要至少 2 个 RTT 才能建立,简化握手需要 1 个 RTT 的握手延迟 。
对于很多短连接场景,这样的握手延迟影响很大,且无法消除 。
队头阻塞主要是 TCP 协议的可靠性机制引入的 。TCP 使用序列号来标识数据的顺序,数据必须按照顺序处理,如果前面的数据丢失,后面的数据就算到达了也不会通知应用层来处理 。
另外 TLS 协议层面也有一个队头阻塞,因为 TLS 协议都是按照 record 来处理数据的,如果一个 record 中丢失了数据,也会导致整个 record 无法正确处理 。
概括来讲,TCP 和 TLS1.2 之前的协议存在着结构性的问题 , 如果继续在现有的 TCP、TLS 协议之上实现一个全新的应用层协议 , 依赖于操作系统、中间设备还有用户的支持 。部署成本非常高,阻力非常大 。
所以 QUIC 协议选择了 UDP,因为 UDP 本身没有连接的概念,不需要三次握手,优化了连接建立的握手延迟,同时在应用程序层面实现了 TCP 的可靠性 , TLS 的安全性和 HTTP2 的并发性 , 只需要用户端和服务端的应用程序支持 QUIC 协议,完全避开了操作系统和中间设备的限制 。
0RTT 建连可以说是 QUIC 相比 HTTP2 最大的性能优势 。那什么是 0RTT 建连呢?
这里面有两层含义:
传输层 0RTT 就能建立连接;
加密层 0RTT 就能建立加密连接 。
TCP 的拥塞控制实际上包含了四个算法:慢启动,拥塞避免 , 快速重传,快速恢复 [22] 。
QUIC 协议当前默认使用了 TCP 协议的 Cubic 拥塞控制算法 [6] , 同时也支持 CubicBytes, Reno, RenoBytes, BBR, PCC 等拥塞控制算法 。
从拥塞算法本身来看,QUIC 只是按照 TCP 协议重新实现了一遍 , 那么 QUIC 协议到底改进在哪些方面呢?主要有如下几点 。
【可插拔】:
什么叫可插拔呢?就是能够非常灵活地生效,变更和停止 。体现在如下方面:
1)应用程序层面就能实现不同的拥塞控制算法,不需要操作系统,不需要内核支持 。这是一个飞跃,因为传统的 TCP
拥塞控制 , 必须要端到端的网络协议栈支持,才能实现控制效果 。而内核和操作系统的部署成本非常高,升级周期很长,这在产品快速迭代,网络爆炸式增长的今天,显然有点满足不了需求;
2)即使是单个应用程序的不同连接也能支持配置不同的拥塞控制 。就算是一台服务器,接入的用户网络环境也千差万别,结合大数据及人工智能处理,quic协议go语言我们能为各个用户提供不同的但又更加精准更加有效的拥塞控制 。比如 BBR 适合,Cubic 适合;
3)应用程序不需要停机和升级就能实现拥塞控制的变更,我们在服务端只需要修改一下配置,reload 一下 , 完全不需要停止服务就能实现拥塞控制的切换 。
STGW 在配置层面进行了优化,我们可以针对不同业务,不同网络制式,甚至不同的 RTT,使用不同的拥塞控制算法 。
【单调递增的 Packet Number】:
TCP 为了保证可靠性 , 使用了基于字节序号的 Sequence Number 及 Ack 来确认消息的有序到达 。
QUIC 同样是一个可靠的协议 , 它使用 Packet Number 代替了 TCP 的 sequence number,并且每个 Packet Number 都严格递增 , 也就是说就算 Packet N 丢失了,重传的 Packet N 的 Packet Number 已经不是 N,而是一个比 N 大的值 。而 TCP 呢 , 重传 segment 的 sequence number 和原始的 segment 的 Sequence Number 保持不变 , 也正是由于这个特性,引入了 Tcp 重传的歧义问题 。

推荐阅读