1、QUIC介绍
(1)QUIC(Quick UDP Internet Connections)协议
是一种全新的基于UDP的web开发协议。可以用一个公式大致概括:
TCP + TLS + HTTP2 = UDP + QUIC + HTTP2’s API
从公式可看出:QUIC协议虽然是基于UDP,但它不但具有TCP的可靠性、拥塞控制、流量控制等,且在TCP协议的基础上做了一些改进,比如避免了队首阻塞;另外,QUIC协议具有TLS的安全传输特性,实现了TLS的保密功能,同时又使用更少的RTT建立安全的会话。
(2)QUIC协议的主要目的
是为了整合TCP协议的可靠性和UDP协议的速度和效率。
QUIC的维基百科页面的介绍:
QUIC是快速UDP网络连接(英语:Quick UDP Internet Connections)的缩写,这是一种实验性的传输层网络传输协议,由Google公司开发,在2013年实现。QUIC使用UDP协议,它在两个端点间创建连接,且支持多路复用连接。在设计之初,QUIC希望能够提供等同于SSL/TLS层级的网络安全保护,减少数据传输及创建连接时的延迟时间,双向控制带宽,以避免网络拥塞。Google希望使用这个协议来取代TCP协议,使网页传输速度加快,计划将QUIC提交至互联网工程任务小组(IETF),让它成为下一代的正式网络规范。
(3)QUIC的特性
1)低延迟连接的建立 (Connection Establishment Latency)
这对已建立的连接很有好处。
众所周知,建立一个TCP连接需要进行三次握手,这意味着每次连接都会产生额外的RTT,从而给每个连接增加了显著的延迟(如下图1所示)。
另外,如果还需要TLS协商来创建一个安全的、加密的https连接,那么就需要更多的RTT,无疑会产生更大的延迟(如下图所示)。
首次,QUIC协议可以在1个RTT中启动一个连接并且获取完成握手所需的必要信息。
QUIC 1 RTT
如果连接的是一个新的服务器,这时候client是没有server的任何信息的,当然也不知道用那种密钥交换算法,没有公钥信息,就不可能实现0 RTT握手,所以,对于新的QUIC连接至少需要1 RTT才能完成握手。
在QUIC中,服务器的配置是完全静态的,而且配置是有过期时间的,由于服务器配置是静态的,因而不是每个连接都需要重新进行签名操作,一个签名可以适用于多个连接。
另外,QUIC采用了两级密钥机制:初始密钥和会话密钥。QUIC在握手过程中使用Diffie-Hellman 算法协商初始密钥。初始密钥协商完毕后,服务器会提供一个临时随机数,会马上再协商会话密钥,这样可以保证密钥的前向安全性,之后可以在通信的过程中就实现对密钥的更新。接收方意识到有新的密钥要更新时,会尝试用新旧两种密钥对数据进行解密,直到成功才会正式更新密钥,否则会一直保留旧密钥有效。
具体握手过程如图(图片引用daveywu的文章)所示:
QUIC 0 RTT
客户端在缓存了ServerConfig的情况下,客户端根据缓存的ServerConifg获取到密钥交换算法及公钥,同时生成一个全新的密钥,直接向服务器发送full Client hello消息,开始正式握手,消息中包括客户端选择的公开数。服务器收到full Client hello,不同意回复REJ;同意连接,则根据客户端的公开数计算出初始密钥,回复SHLO消息。
客户端和服务器根据临时公开数和初始密钥,各自基于SHA-256算法推导出会话密钥。双方更换会话密钥通信,初始密钥已无用,至此,QUIC握手过程结束。
2)改进的拥塞控制 (Improved Congestion Control)
QUIC协议当前默认使用TCP协议的Cubic拥塞控制算法。看似QUIC协议只是吧TCP的拥塞算法重新实现了一遍,其实不然。QUIC协议在TCP拥塞算法基础上做了些改进:
1.可插拔
应用程序层面就能实现不同的拥塞控制算法,不需要操作系统或内核支持。
单个应用程序的不同连接也能支持配置不同的拥塞控制。
不需要停机和升级就能实现拥塞控制的变更。
2.单调递增的Packet Number
- QUIC并没有使用TCP的基于字节序号及ACK来确认消息的有序到达,QUIC使用的是Packet Number,每个Packet Number严格递增,所以如果Packet N丢失了,重传Packet N的Packet Number已不是N,而是一个大于N的值。 这样就很容易解决TCP的重传歧义问题。
3.更多的ACK块
- QUIC ACK帧支持256个ACK块,相比TCP的SACK在TCP选项中实现,有长度限制,最多只支持3个ACK块
4.精确计算RTT时间
- QUIC ACK包同时携带了从收到包到回复ACK的延时,这样结合递增的包序号,能够精确的计算RTT。
3)无队头阻塞的多路复用 (Multiplexing without head-of-line blocking)
HTTP2的最大特性就是多路复用,而HTTP2最大的问题就是队头阻塞。
首先了解下为什么会出现队头阻塞。比如HTTP2在一个TCP连接上同时发送3个stream,其中第2个stream丢了一个Packet,TCP为了保证数据可靠性,需要发送端重传丢失的数据包,虽然这时候第3个数据包已经到达接收端,但被阻塞了。这就是所谓的队头阻塞。
而QUIC多路复用可以避免这个问题,因为QUIC的丢包、流控都是基于stream的,所有stream是相互独立的,一条stream上的丢包,不会影响其他stream的数据传输。
4)前向纠错 (Forward Error Correction)
QUIC使用了FEC(前向纠错码)来恢复数据,FEC采用简单异或的方式,每发送一组数据,包括若干个数据包后,并对这些数据包依次做异或运算,最后的结果作为一个FEC包再发送出去。接收方收到一组数据后,根据数据包和FEC包即可以进行校验和纠错。比如:10个包,编码后会增加2个包,接收端丢失第2和第3个包,仅靠剩下的10个包就可以解出丢失的包,不必重新发送,但这样也是有代价的,每个UDP数据包会包含比实际需要更多的有效载荷,增加了冗余和CPU编解码的消耗。
5)连接迁移 (Connection Migration)
TCP的连接是基于4元组的,而QUIC使用64为的Connection ID进行唯一识别客户端和服务器的逻辑连接,这就意味着如果一个客户端改变IP地址或端口号,TCP连接不再有效,而QUIC层的逻辑连接维持不变,仍然采用老的Connection ID。