網路編程懶人入門(十):一泡尿的時間,快速讀懂QUIC協議

  • 2019 年 11 月 4 日
  • 筆記

1、TCP協議到底怎麼了?

現時的互聯網應用中,Web平台(準確地說是基於HTTP及其延伸協議的客戶端/伺服器應用)的數據傳輸都基於 TCP 協議。

但TCP 協議在創建連接之前需要進行三次握手(如下圖 1,更詳細原理請見《理論經典:TCP協議的3次握手與4次揮手過程詳解》),如果需要提高數據交互的安全性,既增加傳輸層安全協議(TLS),還會增加更多的更多握手次數(如下圖 2)。

▲ 圖 1 – TCP的三次握手原理圖

▲ 圖 2 – TLS的初始化握手原理圖

正如上面兩張圖裡演示的原理,TCP 協議連接建立的成本相對較高。

所以,一般的穩定網路傳輸都是通過TCP,但是在網路基建本身就已經越來越完善的情況下,TCP設計本身的問題便暴露了出來,特別是在弱網環境下,讓我們不得不考慮一些新的可能性。

(本文同步發佈於:http://www.52im.net/thread-2816-1-1.html

2、QUIC協議登場

和 TCP 相反,UDP 協議是無連接協議。客戶端發出 UDP 數據包後,只能「假設」這個數據包已經被服務端接收。這樣的好處是在網路傳輸層無需對數據包進行確認,但存在的問題就是為了確保數據傳輸的可靠性,應用層協議需要自己完成包傳輸情況的確認。

此時,QUIC 協議就登場了。

QUIC 是 Quick UDP Internet Connections 的縮寫,Google發明的新傳輸協議。

與 TCP 相比,QUIC 可以減少延遲。

QUIC 協議可以在 1 到 2 個數據包(取決於連接的伺服器是新的還是已知的)內,完成連接的創建(包括 TLS)(如下圖3所示)。

▲ 圖 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)連接平滑遷移,網路狀態的變更不會影響連接斷線。

從圖上可以看出,QUIC 底層通過 UDP 協議替代了 TCP,上層只需要一層用於和遠程伺服器交互的 HTTP/2 API。這是因為 QUIC 協議已經包含了多路復用和連接管理,HTTP API 只需要完成 HTTP 協議的解析即可。

有關QUIC的詳解請見:技術掃盲:新一代基於UDP的低延時網路傳輸層協議——QUIC詳解》。

3、QUIC協議的目標

QUIC 協議的主要目的,是為了整合 TCP 協議的可靠性和 UDP 協議的速度和效率。

一張圖看懂QUIC協議的優勢:

對於 Google 來說優化 TCP 協議是一個長期目標,QUIC 旨在創建幾乎等同於 TCP 的獨立連接,但有著低延遲,並對類似 SPDY 的多路復用流協議有更好的支援。 如果 QUIC 協議的特性被證明是有效的,這些特性以後可能會被遷移入後續版本的 TCP 和 TLS 協議(它們都有很長的開發周期)。

值得注意的是,雖然理論上來說,如果 QUIC 的特性被證明是有效的,這些特性以後可能會被遷移到後續版本的 TCP 協議中,但鑒於TCP協議長達幾十年在互聯網通訊里的壟斷地位,以及這麼多年積累下來的沉重歷史報復,想要根本性地優化或改進TCP協議,難度相當大(或許,有些事情,只能是想想而已,IPV6還喊了這麼多年呢,不是一樣沒普及。。。)。

4、QUIC協議這麼好,可以大規模切換為QUIC嗎?

理想和現實總是有一定的差距:雖然經過多年的推廣的應用,但QUIC協議目前仍未達到大量普及的階段,在 IETF上的QUIC 依然還是草稿,並且還存在Google QUIC與IETF QUIC兩類不穩定的協定。

而且,QUIC還面臨以下挑戰:

1)小地方,路由封殺UDP 443埠( 這正是QUIC 部署的埠);

2)UDP包過多,由於QS限定,會被服務商誤認為是攻擊,UDP包被丟棄;

3)無論是路由器還是防火牆目前對QUIC都還沒有做好準備。

5、QUIC協議實踐

Chrome 瀏覽器從 2014 年開始已經實驗性的支援了 QUIC 協議。可以通過在 Chrome 瀏覽器中輸入 chrome://net-internals/#quic 查看是否已經支援 QUIC 協議。如果還未支援,可以在 chrome://flags/#enable-quic 中進行開啟。

開始 Chrome 瀏覽器對 QUIC 協議的支援之後,可以在 chrome://net-internals/#quic 中查看到當前瀏覽器的 QUIC 一些連接。當然目前只有 Google 服務才支援 QUIC 協議(如 YouTube、 Google.com)。

Google 在 2015 年的一篇博文中分享了一些關於 QUIC 協議實現的結果,這些優勢在諸如 YouTube 的影片服務上更為突出:用戶報告通過 QUIC 協議在觀看影片的時候可以減少 30% 的重新緩衝時間。

6、我想試試QUIC協議,可以怎麼做?

目前支援 QUIC 協議的 web 服務只有 0.9 版本以後的 Caddy 。其他常用 web 服務如 nginx、apache 等都未開始支援。

整個 QUIC 協議比較複雜,想自己完全實現一套對筆者來說還比較困難。

所以先看看開源實現有哪些。

1)Chromium

這個是官方支援的。優點自然很多,Google 官方維護基本沒有坑,隨時可以跟隨 chrome 更新到最新版本。不過編譯 Chromium 比較麻煩,它有單獨的一套編譯工具。暫時不建議考慮這個方案。

2)proto-quic

從 chromium 剝離的一個 QUIC 協議部分,但是其 github 主頁已宣布不再支援,僅作實驗使用。不建議考慮這個方案。

3)goquic

goquic 封裝了 libquic 的 go 語言封裝,而 libquic 也是從 chromium 剝離的,好幾年不維護了,僅支援到 quic-36, goquic 提供一個反向代理,測試發現由於 QUIC 版本太低,最新 chrome 瀏覽器已無法支援。不建議考慮這個方案。

4)quic-go

quic-go 是完全用 go 寫的 QUIC 協議棧,開發很活躍,已在 Caddy 中使用,MIT 許可,目前看是比較好的方案。

那麼,對於中小團隊或個人開發者來說,比較推薦的方案是最後一個,即採用 caddy 來部署實現 QUIC。caddy 這個項目本意並不是專門用來實現 QUIC 的,它是用來實現一個免簽的 HTTPS web 伺服器的(caddy 會自動續簽證書)。而QUIC 只是它的一個附屬功能(不過現實是——好像用它來實現 QUIC 的人更多)。

從Github的技術趨勢來說,有關QUIC的開源資源越來越多,有興趣可以自已逐一研究研究:https://github.com/search?q=quic

7、本文小結

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

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