-
Quic 全称 quick udp internet connection,“快速 UDP 互联网连接”,(和英文 quick 谐音,简称“快”)是由 google 提出的使用 udp 进行多路并发传输的协议。
2018 年,互联网标准化组织 IETF 提议将“HTTP over QUIC”更名为“HTTP/3”并获得批准,HTTP/3 。
Quic 相比现在广泛应用的 http2+tcp+tls 协议有如下优势:
- 减少了 TCP 三次握手及 TLS 握手时间。
- 改进的拥塞控制。
- 避免队头阻塞的多路复用。
- 连接迁移。
- 前向冗余纠错。
我们知道,UDP速度足够快,但不够可靠;TCP足够可靠,但三次握手确认逻辑会使得网络连接不够快。
那么这时我们会产生四个问题:
- 传统的TCP/IP协议存在什么问题?为什么Http2还未落定就开始推QUIC?
- QUIC为什么不在网络栈中单独发明一个协议,而是要基于UDP去做?
- 基于UDP的QUIC是安全可靠的吗?怎么做到的呢?
- 业内QUIC的使用情况如何?以及面临哪些挑战?
一、传统的TCP/IP协议存在什么问题?
为什么Http2还未落定就开始推QUIC?
发展 TCP 当时的场景和现在主流场景不同,TCP诞生背景是需要保证可靠性、拥塞控制。
现在互联网+的场景比如直播,对于时延的要求性是很高的,但TCP对时间的追求没有那么苛刻。
“TCP+TLS”握手一共需要在客户端和服务端进行4个来回,一共需要4个RTT(RTT:数据发送完到收到确认信号的时间)。
附:一个RTT的时间可以使用 ping 命令进行估算,比如我们打开终端执行如下命令:
ping www.baidu.com
RTT约为70ms,4个RTT即280ms。
TCP连接建立后,从启动到满带宽传输有一个慢启动的过程,传输多个文件就要建立多个TCP连接,慢启动会影响上传速度。
HTTP 1.1 时提出了复用连接
的概念,比如如果我们要传两个文件:
- index.html
- index.js
当传index.html TCP没有中断时,我再传输 index.js 可以复用传输 index.html 时建立的TCP连接。
但这还是存在一个问题:传输多个文件均是串行传输
。
再 HTTP2 为了解决串行传输
的问题,提出了多路复用
的概念,多路复用
允许同时去传输两个文件,可以并行去发送 index.html
和 index.js
,但同时又带来了TCP队头阻塞
的问题。
所以可以这么理解:TCP诞生在网络基建不那么完善的现实背景下,通过网络协议实现了可靠传输,但TCP设计非常容易导致在弱网环境下表现不好。
当前网络基建相对完善,从硬件水平上可以大概率保证网络传输不丢包,那么网络协议该如何与时俱进呢?实现既高效、有尽可能可靠呢?
二、QUIC为什么要基于UDP去做?
QUIC为什么不在网络栈中单独发明一个协议,而是要基于UDP去做?
主要有两点原因:
- 设计一个轮子比较难,花费时间
- 传输层协议都是写在操作系统内核中的,修改操作系统内核并部署到所有电脑里,是个工程量非常大的事情
基于上面两点原因,QUIC属于应用层的产物,而非传输层。
三、基于UDP的QUIC是安全可靠的吗?
怎么做到的呢?
Google 的 QUIC 是一种基于 UDP 的低延迟互联网传输协议,该协议常用于游戏、流媒体和 VoIP 服务。
IP和UDP均没有做可靠保证,所以UDP层相当于什么都没有做,只是把数据透传到QUIC的应用层。
但是难道说基于UDP的QUIC就是不可靠的吗?其实不是。
我们从上面的图中罗列一下 QUIC 做了哪些事情:
- Congestion control Loss recovery:恢复丢失的包
- TLS
- Multistreaming:多路复用
可以看到左边TCP做的事情,QUIC也都进行了实现:
那相比TCP,QUIC有什么优点呢?
(一)通过减少往返次数(RTT),以缩短连接建立时间
QUIC提供了0-RTT和1-RTT的连接建立,这也就是说QUIC在最好的情况下不需要额外的往返时间便可以建立新的连接。
两者中更快的是0-RTT,仅在在两个主机之间建立过连接且缓存了该连接的秘钥时可以使用。
那这时我们可能会有一个疑问,设计TCP的祖师爷肯定也知道 RTT次数 越少,传输越快,那还为什么设计3次握手?
发送端(Client)和接收端(Server)总共发起的 3 次request就叫做 3 次握手。
关于TCP syn的理论相信大家已经很熟了,我这里引用网上的一个段子,来说明TCP为什么是3次握手,而不是2次握手或者4次握手。
三次握手:
1 | “喂,你听得到吗?” |
两次握手:
1 | “喂,你听得到吗……吗……吗?” |
那为什么基于UDP的QUIC协议也是可靠的呢?
主要原因是QUIC在应用层处理了类似TCP传包的流程,只是在建立连接时无需再等待多次RTT。
可以这么理解:
TCP时代,网络基建不够优秀,建立连接要相当谨慎,网络通路是有限的资源,在发包阶段就要保证可靠性。
QUIC时代,网络基建相当完善,建立连接不再那么苛刻,可以有效地优化弱网的传输流程。
(二)独立的数据流避免阻塞问题
还是以传输 index.html
和 index.js
为例,QUIC协议开辟两条数据流传分别传输这两组数据,不会因为一条链路的阻塞导致整个链路的瘫痪。
四、业内QUIC的使用情况和挑战如何呢?
QUIC面临的挑战:
1 | a. 路由封杀UDP 443端口(这正是QUIC部署的端口) |
目前业内腾讯、BIGO、豆瓣、Facebook、快手均已进行QUIC协议的接入,在直播推拉流、视频传输有着显著地收效。
有趣地是因为QUIC本身是应用层的协议,且QUIC协议目前处于草案阶段,所以目前业内接入QUIC时,基本会采用两个做法:
- 自研QUIC,结合自身业务深度定制,比如腾讯的TQUIC
- 接入AB test,根据网络环境和使用场景动态切换网络协议
虽然QUIC各个特性看上去很美好,但需要客户端/服务端的网络协议栈都支持QUIC协议。截止目前,除iOS 15 在指定接口NSURLSession 及限制条件前提下,支持了HTTP3,其他系统及主流网络库均不支持QUIC。
思考心得
学完QUIC协议,回想我过去工作中和协议相关的事情,我发现其实本质都是相近的。
比如客户端旧版本不支持的pb,后台新版本下发旧版本也解析不了,无法支持。放在QUIC这类网络协议上就是:如果旧版本浏览器或者操作系统不支持解析协议,发送方单方面是推动不了的,必须 Server 与 Client 达成协议。
又或者客户端会针对不同的业务采取 短轮询、长轮询又或者是长连接的业务逻辑,本质就是根据业务场景选择不同的 C-S 沟通方案,QUIC的诞生也是解决 C-S 的沟通效率等问题。
又比如客户端同步用户信息时,也会遇到网络中丢包、重传等问题,客户端采用的 sequence提升与merge 方案与 TCP保证传输可靠性 方案基本一致。
可以这么说:无论是TCP还是QUIC,从诞生到发展一直是在解决现实问题,可以算是Google的一个业务模块,和我们开发一个和网络优化相关的需求类似。