和 TCP 相反,UDP 协议是无连接协议。客户端发出 UDP 数据包后,只能“假设”这个数据包已经被服务端接收。这样的好处是在网络传输层无需对数据包进行确认,但存在的问题就是为了确保数据传输的可靠性,应用层协议需要自己完成包传输情况的确认。

此时,QUIC 协议就登场了。

QUIC 是 Quick UDP Internet Connections 的缩写,谷歌发明的新传输协议。

与 TCP 相比,QUIC 可以减少延迟。

QUIC 协议可以在 1 到 2 个数据包(取决于连接的服务器是新的还是已知的)内,完成连接的创建(包括 TLS)(如下图3所示)。

JAVA deque实现 quic java实现_quic java

▲ 图 3  - QUIC 协议握手原理图

从表面上看:QUIC 非常类似于在 UDP 上实现的 TCP + TLS + HTTP/2。由于 TCP 是在操作系统内核和中间件固件中实现的,因此对 TCP 进行重大更改几乎是不可能的(TCP 协议栈通常由操作系统实现,如 Linux、Windows 内核或者其他移动设备操作系统。修改 TCP 协议是一项浩大的工程,因为每种设备、系统的实现都需要更新)。但是,由于 QUIC 建立在 UDP 之上,因此没有这种限制。QUIC 可以实现可靠传输,而且相比于 TCP,它的流控功能在用户空间而不在内核空间,那么使用者就不受限于 CUBIC 或是 BBR,而是可以自由选择,甚至根据应用场景自由调整优化。

QUIC 与现有 TCP + TLS + HTTP/2 方案相比,有以下几点主要特征:

1)利用缓存,显著减少连接建立时间;

2)改善拥塞控制,拥塞控制从内核空间到用户空间;

3)没有 head of line 阻塞的多路复用;

4)前向纠错,减少重传;

5)连接平滑迁移,网络状态的变更不会影响连接断线。

JAVA deque实现 quic java实现_UDP_02

从图上可以看出,QUIC 底层通过 UDP 协议替代了 TCP,上层只需要一层用于和远程服务器交互的 HTTP/2 API。这是因为 QUIC 协议已经包含了多路复用和连接管理,HTTP API 只需要完成 HTTP 协议的解析即可。