QUIC 全称 Quick UDP Internet Connection, 是谷歌公司研发的一种基于 UDP 协议的低时延互联网传输协议。在2018年IETF会议中,HTTP-over-QUIC协议被重命名为HTTP/3,并成为 HTTP 协议的第三个正式版本。本文将介绍QUIC协议的优势、特性和原理。
这是TCP的可靠性机制的特性。HTTP2是在一个TCP连接上并行发送多个资源,TCP队头阻塞将会导致所有资源的传输需要停等,对网络质量影响较大。
TCP的3次握手和4次挥手是其建立和断开连接的基本步骤,这无可避免的要消耗一次RTT。而现在主流的HTTPS协议,还需要2消耗两次RTT握手才能建立连接。
网络中间设备在传输TCP协议时设置了很多潜规则,例如部分防火墙只允许通过80和443端口;部分NAT网关在转换网络地址时会重写传输层头部,可能导致双方无法使用新的传输格式;部分中间代理有时候出于安全需要,删除一些它不认识的选项字段。因此升级基于TCP的网络协议时,就必须要考虑和兼容这些影响。
TCP是在操作系统内核和中间设备固件中实现的。要对TCP进行大更改,就必须要通信双方升级操作系统,中间设备更新固件。这基本难以大规模实现。
以上问题都来自于TCP传输层。基于TCP协议要再进一步提升网络协议,已举步维艰。这时,基于UDP协议实现的QUIC网络协议应运而生。
简单来说,QUIC协议就是基于UDP重新实现了一遍HTTP2的特性。
用一个等式来描述就是 QUIC = UDP + TLS + HTTP2
QUIC与HTTP2的网络层次对比如下图所示:
下面来分析其一些关键特性。
前面我们说过,TCP最少需要花费1RTT的时间来建立连接。下图3列分别描述了TLS1.2、TLS1.3和QUIC建立连接的成本。每1列分为上下两个图,上图表示首次建立连接所需成本,下图表示再次建立连接所需成本。
可以看到,TLS1.2下,首次建立连接,首先需要1次RTT建立连接(蓝色线),2次RTT交换密钥和加密策略(黑色线),然后开始通信。再次建立连接时,由于已缓存了密钥,因此少1次RTT。 TLS1.3和QUIC都采用了Diffie-Hellman密钥交换算法来交换密钥。该算法的优点是交换密钥只需要1次RTT。在QUIC下,只有首次建立连接交换密钥时消耗1RTT时间,再次连接时就是0RTT了。这已最大限度的减少握手延迟带来的影响。这个特性在连接延迟较大的移动网络上有较好的性能提升。
TCP下一个连接是以四元组标识的,即(SrcIp,SrcPort,DstIp,DstPort)。而QUIC连接是以客户端产生的一个64位随机数作为连接标识。当网络、端口发生改变或中断时,只要连接标识不改变,连接就不会中断。
TCP通过滑动窗口机制来保证可靠性以及进行流量控制。QUIC更新了其滑动窗口机制,并在Connection和Stream两个级别分别进行流控。
用公式表示就是: connection可用窗口 = stream1可用窗口 + stream2可用窗口 + streamN可用窗口
SDPY和HTTP2协议的多路复用,是让所有请求在一个TCP连接上传输。前面说过,TCP协议有队头阻塞问题,如果某个资源的某个包丢失了,由于TCP是保证时序的,就会在接收端形成队头阻塞。TCP协议无法区分各个资源的包是否关联,因此会停止处理所有资源,直到丢包恢复。
QUIC是基于UDP的,UDP不需要保证包的时序,因而不存在等待丢包恢复,不存在队头阻塞问题。如果某个资源的某个包丢失了,只会影响单个资源,其他资源会继续传输。
TCP协议栈是写在操作系统内核以及中间设备固件上的,对其更新升级,耗费的时间是以年为周期。 基于UDP协议栈的QUIC协议在应用层实现。应用软件的更新较为轻量,因此协议新特性的升级迭代周期是以月或周来计算。
我们可以用Chrome浏览器来访问QUIC网站,或者使用基于Chrome内核的浏览器也可以。目前较新版本的chrome浏览器已默认开启QUIC支持,如果你不确定当前浏览器是否开启QUIC支持,可以在地址栏输入chrome://flags/查看:
如何判断一个网站是否支持QUIC呢?一般可以通过其返回的header来判断:
当出现如上图这行alt-svc: quic=xxx时,即表示该网站支持QUIC。该行具体的含义是服务器在443端口开启了QUIC支持,最大缓存时间是2592000秒(30天),支持的QUIC版本号是44、43、39。 在浏览器输入chrome://net-internals/#quic可以查看当前chrome浏览器支持的QUIC版本以及其他信息。如下图所示,我的浏览器支持版本号39的QUIC。
当访问支持QUIC的网站时,可以打开开发者工具,在Protocol列可以查看其具体的协议,如下图所示:
这里显示的http/2+quic/39表示采用的是QUIC的版本号是39。从这里也可以看出,QUIC是在HTTP2基础上提供的一个增强的协议。如果QUIC无法访问,浏览器就会无缝fallback回HTTP2,保证用户的访问。
一般情况下,Chrome浏览器和服务器端协商使用QUIC协议要经过如下步骤:
在地址栏输入 chrome://net-internals/#alt-svc 可以查看QUIC连接的缓存情况,如下图所示:
标记为broken的域名就是竞速失败,fallback为HTTP2连接。 如果握手失败,chrome会将QUIC标记为broken,并fallback到TCP继续发送。5分钟后chrome会再次尝试让TCP和QUIC进行竞争。由于QUIC连接被标记为broken,所以禁止0RTT握手,如果握手再次失败,则冷到10分钟,再下次则是20分钟,以此类推。
目前较为热门的服务端开源组件是Caddy。它是一个用Go语言编写的通用web服务器,性能非常好。项目Github地址:https://github.com/mholt/caddy 大家可以按照Github说明进行安装。启动Caddy时加上-quic标记即可启用QUIC支持。 caddy -quic 启动后,通过netstat命令查看端口使用情况,可以见到caddy同时用TCP和UDP监听端口:
下面图表来自:https://cloud.tencent.com/developer/article/1155289
从上图的数据可以看出,QUIC的总体性能比HTTP2略有提升
从上图的数据可以看出,在弱网络、高丢包率的情况下,QUIC才能凸显其独特优势。
虽然目前Google制定的QUIC协议版本已实现并应用在自家的搜索产品和Chrome上,但IETF小组自身也创建了一个QUIC协议版本,并且与Google的原始提案有较大差异。为了区分两者,Google推出的QUIC被称为gQUIC,IETF制定的QUIC称为iQUIC(目前cloudflare已实现该套协议并提供了相应的SDK和工具)。而即使是Google自身,也在不断的对QUIC进行升级和改进,因此短期内QUIC不会称为一个成熟稳定的网络协议。
据W3Techs统计,截止到2018年底,全球排名前1000万的网站中,有31.2%已支持了HTTP2,而QUIC只有1.2%。HTTP2的优秀表现,以及全球各国对网络基础设施的建设,让QUIC协议暂无法显示其魅力。
不管是国外还是国内,TCP流量都占主流地位。因此网络运营商、云厂商和防火墙设备,在网络拥堵时可能会不同程度的丢弃部分UDP流量。常用端口(如http协议的80、443)上的UDP包经常会被防火墙认为是恶意访问直接屏蔽掉。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。