初識 QUIC 協議


初識 QUIC 協議

QUIC 概述

QUIC 全稱 quick udp internet connection,快速 UDP 互聯網連接(和英文 quick 諧音,簡稱“快”),是使用 UDP 進行多路並發傳輸的協議。QUIC 協議最初是由 Google 開發並使用在 Chrome 中的新一代 Web 協議。之后被 IETF 的 QUICWG 工作組接管,目前發布的版本為 24th。

QUIC 協議是一個包含傳輸層、安全墊片和應用層的復合協議族。QUIC 協議基於 UDP 協議,在此之上實現了可控有序到達、擁塞控制、流量控制等傳輸層功能; 提供了對於包和連接的完整性和機密性功能;提供了 http3.0 等的應用層功能。

隨着移動互聯網快速發展以及物聯網的逐步興起,網絡交互的場景越來越豐富,網絡傳輸的內容也越來越龐大,用戶對網絡傳輸效率和 Web 響應速度的要求也越來越高。

與現在廣泛應用的 HTTP2+TCP+TLS 協議組合相比,QUIC 具有如下優勢:

  1. 減少了 TCP 三次握手及 TLS 握手時間;
  2. 改進的擁塞控制;
  3. 避免隊頭阻塞的多路復用;
  4. 連接遷移;
  5. 前向冗余糾錯

QUIC 協議基本結構

QUIC 協議是基於 UDP 的協議,其最基本包的格式為 UDP 報文(package),由 package number 來提供有序到達的功能。 在一個 QUIC 報文之中,有多個獨立功能的 QUIC 幀(frame),每一個幀都 用於實現不同的功能,比如傳輸幀,錯誤幀,校驗幀等。

在報文和幀的基礎之上,QUIC 協議構成了一個雙方共享連接狀態的有狀態協議, 因此有連接(connection)的概念。通過 connection id 來區別不同的 QUIC 連接。 QUIC 連接具有完整的生命周期(建立、撤銷、關閉等)。

在連接之上,QUIC 協議使用了連接復用的概率,在連接之上建立了多個有狀態的流(steam), 每一個流也是具有獨立狀態的。每一個流對應了上層的不同應用,比如 id 為 1 的流用於負責握手協議和密碼學參數的協商。

+---------+---------+---------+
| stream1 | stream2 | stream3 |
+---------+---------+---------+
|         connection          |
+-----------------------------+
| packages (frame1 || frame2 )|
+-----------------------------+

QUIC 核心特性

減去不必要的RTT,連接建立延時低

0RTT 建連可以說是 QUIC 相比 HTTP2 最大的性能優勢。那什么是 0RTT 建連呢?這里面有兩層含義:

  1. 傳輸層 0RTT 就能建立連接;
  2. 加密層 0RTT 就能建立加密連接;

QUIC 0RTT

比如上圖左邊是 HTTPS 的一次完全握手的建連過程,需要 3 個 RTT。就算是 Session Resumption,也需要至少 2 個 RTT。

而 QUIC 呢?由於建立在 UDP 的基礎上,同時又實現了 0RTT 的安全握手,所以在大部分情況下,只需要 0 個 RTT 就能實現數據發送,在實現前向加密的基礎上,並且 0RTT 的成功率相比 TLS 的 Sesison Ticket 要高很多。

改進的擁塞控制

TCP 的擁塞控制實際上包含了四個算法:慢啟動、擁塞避免、快速重傳、快速恢復。其中TCP中擁塞控制是被編譯進內核中的,如果想要更改就需要改變內核參數,但是想要對已有的擁塞控制算法進行更改就需要重新編譯內核,Linux 4.9 中引入了基於時延的擁塞控制算法 BBR,這打破了以往是靠丟包驅動的擁塞控制算法。

QUIC 協議當前默認使用了 TCP 協議的 Cubic 擁塞控制算法,同時也支持 CubicBytes、Reno、RenoBytes、BBR、PCC 等擁塞控制算法。與 TCP 相比,QUIC 主要擁有以下特性:

  • 可插拔:QUIC 可以針對某個特殊場景使用不同的擁塞控制算法,且切換十分簡單。TCP 想要切換擁塞控制算法是針對全局的,需要更改內核參數,或者重新編譯內核,使得切換起來十分不便;
  • 單調遞增的 Packet Number:QUIC 的數據包是單調遞增的Packet Number。這幫助傳輸解決了重傳歧義,方便計算RTO,解決了TCP的隊頭阻塞。因為TCP的數據是流,確認機制是 seq和ack。QUIC使用 Packet Number 代替了 TCP 的 sequence number,並且每個 Packet Number 都嚴格遞增,也就是說就算 Packet N 丟失了,重傳的 Packet N 的 Packet Number 已經不是 N,而是一個比 N 大的值。

QUIC 協議測試實踐

安裝 go 環境,並且下載 quic-go 項目

# 配置 go 安裝環境,下載 quic-go 項目源碼
go env -w GO111MODULE=on
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
go get -v -t -u github.com/lucas-clemente/quic-go

(以下測試實踐基於開源項目 quic-go https://github.com/lucas-clemente/quic-go

測試 QUIC 的連接時長

編譯項目的測試代碼

# 編譯 quic-go 項目
cd ./quic-go/example
go build -o server main.go
go build -o client client/main.go

示例中采用了單向認證的方式,證書簽發的 CN=localhost。

開啟服務端

./server -bind ":8088" 
server GET localhost:8088/demo/tiles
server Responding with 200
server Peer closed session with error: Application error 0x100
server Connection 0xfc314d4e5df5d38b closed.

開啟客戶端

./client https://localhost:8088/demo/tiles
GET https://localhost:8088/demo/tiles
client Starting new connection to localhost ([::]:52586 -> 127.0.0.1:8088), source connection ID (empty), destination connection ID 0xfc314d4e5df5d38b, version TLS dev version (WIP)
Got response for https://localhost:8088/demo/tiles: &http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/3", ProtoMajor:3, ProtoMinor:0, Header:http.Header{}, Body:(*http3.body)(0xc000324a00), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Uncompressed:false, Trailer:http.Header(nil), Request:(*http.Request)(nil), TLS:(*tls.ConnectionState)(nil)}
Request Body:
<html><head><style>img{width:40px;height:40px;}</style></head><body><img src="/demo/tile?cachebust=0">...<img src="/demo/tile?cachebust=199"></body></html>
client Closing session with error: Application error 0x100
client Connection 0xfc314d4e5df5d38b closed.

運行結果:QUIC 單向認證

2

通過對比,可以得出結論:同等條件下 QUIC 比 HTTP2 傳輸的數據包少,時間更短。但在數據量較小時兩者相差不大,當大數據量、多次連接時 QUIC 更能體現出優勢。簡單測試單次的鏈接時間結果:連接→發送→接收→斷開:

grpc_simple: 28ms
grpc_single: 44ms
grpc_dul: 51ms
http_simple: 21ms
http_single: 32ms
http_dual: 38ms
quic_single: 35ms

測試 QUIC 在 Web 上的服務

首先需要去網上找到一個可以提供 QUIC 服務的網站,然后再使用上面的 client 去請求。如果正常,則可以成功獲取響應:

# 這里使用大佬的技術博客(已提供 QUIC 服務)作為請求地址
./client [https://liudanking.com](https://liudanking.com/)

運行后的部分截圖:

3

獲取響應后,可以在 Chrome 瀏覽器(版本號 64+)中開啟網絡狀態數據看板,並且請求上面的同一個地址,即可獲取到如下的 QUIC 交互截圖:

4

結論

QUIC 協議開創性的使用了 UDP 協議作為底層傳輸協議,通過各種方式減少了網絡延遲。

目前 QUIC 協議已經運行在一些較大的網站上,但現在還在標准化進程中,離大范圍普及還有較長的一段距離。期待 QUIC 協議規范能夠成為終稿,並在除了谷歌瀏覽器之外的其他瀏覽器和應用服務器中也能夠實現。


參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM