QUIC 之类的可靠传输协议

互联网是一个分组(或者称为数据包)交换网络,其中传输的数据的基本单位是数据包。互联网中时时刻刻在发生的是距离有限的两个路由节点之间通过物理链路的数据包交换。那互联网中远距离复杂环境下的数据传输究竟如何完成的呢?它们正是借助于多次路由节点间直接的这种数据交换完成的。直觉上就让人觉得这种数据传输不是那么的可靠,不像电话网络连接那样。实际上互联网的数据传输确实不是百分之百的可靠,互联网上传输的数据天然地可能出现丢失,乱序,重复等等问题,但目前来看,绝大多数情况下,互联网还是比较有效。

互联网有效性的一个保证即是数据的可靠传输协议,如 TCP。TCP 对于当今的互联网是如此的重要,以至于整个网络协议栈被以 TCP/IP 来指代。通常情况下传输层协议及之下的协议由内核层实现,由硬件设备实现,之上的协议的数据,是我们平常写的应用程序可以比较方便的拿到的数据。TCP 在内核实现了一套复杂的可靠传输的字节流的语义,而 UDP 在发送时,是在数据包的前面简单的加个 IP 头部等就发送出去,接收时简单的剔除掉 IP 头部就抛给应用层的数据包。除了 TCP,互联网的可靠传输协议也多有基于 UDP 实现的,毕竟这类协议运行在用户空间,不管是部署还是更新,都要方便得多,比如 RUDP,UDT 等,当然还有 QUIC。

不管是 TCP,还是基于 UDP 并运行于用户空间的可靠传输协议,它们要解决的问题都是类似的,解决问题的方法也多有相似之处,在分析这些协议时也可以从类似的几个角度入手。

提供给应用方的操作。可靠传输协议提供给应用方的操作,通常包含:

  • 等待连接/接受连接的 listen/accept
  • 建立连接的 connect
  • 发送数据的 send/write
  • 接收数据的 receive/read
  • 关闭连接的 close/shutdown

可靠传输协议的连接的生命周期,通常包含:

  • 建立连接。
  • 数据传输及传输控制。
  • 断开连接。

断开连接的过程,通常主要涉及资源的清理和容错等,不太容易成为为了优化传输效率和安全性而开发的新协议的关注重点。而建立连接和数据传输控制方面,则是各种新方法新手段层出不穷。

连接建立过程主要为了协商传输参数及协议安全性而存在,不同的可靠传输协议有不同的看法及选择,如 TCP 的 3 次握手,UDT 则是 4 次握手,这是其一,即一般的连接握手过程需要经过几个 RTT。

数据传输过程中多一个 RTT,少一个 RTT 对于传输数据量很大的情况,可能没有太大的影响,但对于当今互联网中大量存在的数据量不大,如 REST API 访问这种请求则有着显著的影响,于是一些较新的协议会有减少连接建立过程中的 RTT 的尝试。为了减少连接建立过程的 RTT,一般来说有几种方法:一是尝试增加状态减少整体建连开销,即第一次连接建立耗时较长,后续再建立连接时,耗时减少,如 TLS 的会话恢复,TCP 的 Fast Open 优化,QUIC 的 0 RTT 建连等;二是尝试在建连的握手包中发送应用数据,如TCP 的 Fast Open 优化,QUIC 的 0 RTT 建连等;三是合并多个层次的协议的连接建立协商,如 QUIC 的合并可靠传输协议的协议协商和为了安全性的 TLS 的协议协商等;四是每次建立连接之后,试图多传一些数据,甚至是并发地传数据,比如 HTTP/2 的连接复用,QUIC 的连接复用等;五新的连接标识及连接维护方法,如 QUIC 的连接迁移特性。

我们写代码时,都讨厌状态,能少一个状态就少一个状态。状态几乎难免要增加不同代码和程序逻辑的耦合,增加部署维护成本,降低并发性,降低伸缩性等,然而为了更有效的网络数据传输,许许多多的协议将状态引入进来了。

然后是数据传输控制过程。无论哪种可靠传输协议,为了实现有效的可靠传输,发送缓冲区,接收缓冲区,数据包的接收确认,丢包/超时重传,快速重传,发送滑动窗口,接收滑动窗口,拥塞窗口拥塞控制等等几乎都是必不可少的。

数据传输过程主要由数据发送方控制,数据发送方依据接收方的接收能力,对于网络环境的探测感知,以及发送方的发送能力对发送过程进行控制。接收缓冲区和接收窗口代表数据接收方的数据接收能力,发送方的发送缓冲区代表发送方的发送能力,拥塞控制和拥塞窗口则代表发送方对于网络环境状态的感知,发送方主要综合考虑接收窗口和拥塞窗口,来控制发送窗口的大小。

为了探测网络状况,类似于 TCP 的 CUBIC 算法几乎总是无法避免的,慢启动,拥塞避免,快速重传,丢包/超时重传等。为了充分利用当前网络环境的网络带宽,慢启动过程的初始拥塞窗口可以适当地调整的比之前大一些,如 UDT 的做法。为了更精确地感知网络状态和接收方的接收能力的变化,如 RTT 等,QUIC 引入了单调递增的 Seqno,Ack Delay 时间,更多的 Ack 等特性,TCP 的数据包中总是会携带有接收窗口的大小,还有 HTTP/2 和 QUIC 中的 WINDOW_UPDATE 等。为了尽可能避免重传,FEC 也常常作为一种优化手段。探测到网络状况之后,对于传输更精细的控制,则可以专门再来探讨。

坚持原创技术分享,您的支持将鼓励我继续创作!