FE.BASE-HTTP3知識筆記

seasonley發表於2021-12-26

雖然 HTTP/3 確實有一些有前途的新概念,但遺憾的是,它們對大多數網頁和使用者的影響可能相對有限(但對一小部分可能至關重要)。HTTP/3 的設定和使用(正確)也非常具有挑戰性,因此在配置新協議時要小心。

第 1 部分:HTTP/3 歷史和核心概念

對http2的誤解\不能落地的期望

HTTP/2 與 HTTP/3 協議棧比較
(HTTP/2 與 HTTP/3 協議棧比較)
協議分層是為了重用,其中TCP協議確保完整傳輸。提出QUIC(https://www.rfc-editor.org/rf...)協議是因為早期 TCP並沒有真正考慮到最大效率。

  • TCP 需要“握手”,每個往返時間 (RTT) 可能需要 100 毫秒以上,導致明顯的延遲
  • TCP 將它傳輸的所有資料視為單個“檔案”或位元組流,會有隊頭 (HoL) 阻塞(如果一個檔案TCP包丟失,那麼所有其他檔案也將延遲,直到這些資料包被恢復。)

基本概念

直接在HTTP/2優化非常困難,所以我們重新構想並實現了一個更高階的 TCP 版本,並將其稱為 QUIC。因為我們想讓 QUIC 更容易部署,所以我們通過 UDP 執行它。

我們對 HTTP/3 的主要功能(更快的連線設定、更少的 HoL 阻塞、連線遷移等)感到興奮,實際上都來自 QUIC。

QUIC 使用 UDP,因此設計 HTTP/3 主要是因為希望它能讓它們更容易部署,因為UDP幾乎被網際網路上的所有裝置所知並已實現.

在 UDP 之上,QUIC 基本上重新實現 TCP 的功能。QUIC 是絕對可靠的,它使用對接收到的資料包重傳的確認來確保丟失的資料包仍然到達。QUIC 還建立了一個連線並有一個高度複雜的握手

QUIC 還使用所謂的流量控制擁塞控制機制來防止傳送方或接收方過載,但這也會使 TCP 比原始 UDP 慢。

TLS、TCP 和 QUIC 握手持續時間
(TLS、TCP 和 QUIC 握手持續時間)

鑑於這種向永遠線上的 TLS(尤其是網路流量)的明顯演變,QUIC 的設計者決定將這一趨勢提升到一個新的水平也就不足為奇了。他們並沒有簡單地為 HTTP/3 定義明文模式,而是選擇將加密深深植根於 QUIC 本身,它打破了協議棧中協議之間典型的清晰分離。
與 TCP + TLS 不同,QUIC 還在資料包頭和有效載荷中加密其傳輸層後設資料
(與 TCP + TLS 不同,QUIC 還在資料包頭和有效載荷中加密其傳輸層後設資料。)

優缺點

優點

  • QUIC 對其使用者更安全。

    沒有辦法執行明文 QUIC,因此攻擊者和竊聽者監聽的選項也更少。(最近的研究表明HTTP/2 的明文選項是多麼危險。)

  • QUIC 的連線建立速度更快。

    對於 TLS-over-TCP,兩種協議都需要自己單獨的握手,而 QUIC 將傳輸和加密握手合二為一,節省了往返(見上圖)。

  • QUIC 可以更容易地進化。

    因為它是完全加密的,網路中的中介軟體不能再像使用 TCP 那樣觀察和解釋其內部工作原理。因此,它們也不會因為更新失敗而在較新版本的 QUIC 中(意外地)中斷。如果我們想在未來為 QUIC 新增新功能,我們“只需要”更新終端裝置,而不是所有的中介軟體。

缺點

  • 許多網路會猶豫是否允許 QUIC。

    公司可能希望在他們的防火牆上阻止它,因為檢測不需要的流量變得更加困難。ISP 和中間網路可能會阻止它,因為不再容易獲得諸如平均延遲和資料包丟失百分比之類的指標,從而使檢測和診斷問題變得更加困難。這一切都意味著 QUIC 可能永遠不會普遍可用。

  • QUIC 具有更高的加密開銷。

    QUIC 使用 TLS 加密每個單獨的資料包,而 TLS-over-TCP 可以同時加密多個資料包。對於高吞吐量場景,這可能會使 QUIC 變慢。

  • QUIC 使網路更加集中。
    我經常遇到的抱怨是,“谷歌正在推動 QUIC,因為它讓他們可以完全訪問資料,同時不與其他人共享任何資料”。我大多不同意這一點。首先,與 TLS-over-TCP 相比,QUIC 不會向外部觀察者隱藏更多(或更少!)使用者級資訊(例如,您正在訪問哪些 URL)(QUIC 保持現狀)。

特性

解決HoL 阻塞

解決傳輸層的 HoL 阻塞是 QUIC 的主要目標之一。與 TCP 不同,QUIC 非常清楚它正在複用多個獨立的位元組流。

QUIC 允許 HTTP/3 繞過隊頭阻塞問題
(QUIC 允許 HTTP/3 繞過隊頭阻塞問題。)

QUIC 支援連線遷移

TCP協議下沒有任何機制允許客戶端讓伺服器知道它已經更改了 IP,所以每次網路更改都意味著無法再使用現有的 TCP 連線。重新啟動 TCP 連線會產生嚴重影響(等待新的握手、重新啟動下載、重新建立上下文)。

為了解決這個問題,QUIC 引入了一個名為連線識別符號 (CID)的新概念。每個連線都在 4 元組頂部分配了另一個編號,用於在兩個端點之間唯一標識它。為了防止跟蹤,每次使用新網路時,QUIC 都會更改 CID。

QUIC 使用多個協商連線識別符號 (CID) 來防止使用者跟蹤
(QUIC 使用多個協商連線識別符號 (CID) 來防止使用者跟蹤)

在 TCP 中,連線由四個引數定義(客戶端 IP 地址 + 客戶端埠 + 伺服器 IP 地址 + 伺服器埠),當端點改變網路時,這些引數會改變。因此,有時需要重新啟動這些連線,從而導致停機。QUIC 向混合中新增了另一個引數,稱為連線 ID。QUIC 客戶端和伺服器都知道哪些連線 ID 對映到哪些連線,因此對網路變化更加健壯。

QUIC 靈活且可擴充套件

  1. QUIC 幾乎完全加密的事實意味著,如果我們想部署更新版本的 QUIC,我們只需要更新端點(客戶端和伺服器),而不是所有中介軟體。
  2. QUIC 不使用單個固定的資料包頭來傳送所有協議後設資料。相反,QUIC 具有較短的資料包標頭,並在資料包有效載荷內使用各種“幀”(類似於微型專用資料包)來傳達額外資訊。例如,有一個ACK框架(用於確認)、一個NEW_CONNECTION_ID框架(用於幫助建立連線遷移)和一個STREAM框架(用於攜帶資料),如下圖所示。QUIC 使用單獨的幀來傳送後設資料,而不是一個大的固定資料包頭。
  3. QUIC 使用自定義 TLS 擴充套件來攜帶所謂的傳輸引數。這些允許客戶端和伺服器為 QUIC 連線選擇配置。這意味著他們可以協商啟用哪些功能(例如,是否允許連線遷移、支援哪些擴充套件等)併為某些機制(例如,支援的最大資料包大小、流量控制限制)傳達合理的預設值。
  4. 大多數實現目前是在“使用者態”中完成的(與 TCP 不同,後者通常在“核心態”中完成)。

雖然 QUIC 現在已經標準化,但它確實應該被視為QUIC 1 ,並且有明確的意圖來建立版本 2 和更快的版本。

第 2 部分:HTTP/3 效能特性

QUIC 和 HTTP/3 確實具有巨大的 Web 效能潛力,但主要用於慢速網路上的使用者。如果您的普通訪問者使用的是快速有線或蜂窩網路,他們可能不會從新協議中受益太多。

擁塞控制

效能的一個方面是關於傳輸協議如何有效地使用網路的全部(物理)頻寬(即大致每秒可以傳送或接收多少資料包)。這反過來會影響頁面資源的下載速度。有些人聲稱 QUIC 在某種程度上比 TCP 好得多,但事實並非如此。

連線不知道它可以安全或公平地預先使用多少頻寬,並且該頻寬會隨著使用者加入、離開和使用網路而變化。為了解決這個問題,TCP 將通過使用稱為擁塞控制的機制不斷嘗試發現可用頻寬。
TCP 擁塞控制的簡化示例,從 10 個資料包的傳送速率開始
(TCP 擁塞控制的簡化示例,從 10 個資料包的傳送速率開始)

儘管 TCP 的擁塞控制使其穩健,但這也意味著需要一段時間才能達到最佳傳送速率,具體取決於 RTT 和實際可用頻寬。對於網頁載入,這種慢啟動方法還會影響諸如FCP(首次內容繪製)等指標,因為在前幾次往返中只能傳輸少量資料(幾十到幾百 KB)。

並非QUIC不使用擁塞控制,實際上使用與 TCP 非常相似的頻寬管理技術。它也從較低的傳送速率開始,並隨著時間的推移而增長,使用確認作為衡量網路容量的關鍵機制。擁塞控制演算法今天仍在大力發展,例如,我們可能需要調整一些東西以充分利用 5G

QUIC的延遲確認頻率擴充套件提議

雖然預設情況下,QUIC 每收到 2 個資料包都會傳送一個確認,但此擴充套件允許端點確認,例如,每 10 個資料包。這已被證明可以為衛星和非常高頻寬的網路帶來很大的速度優勢,因為傳輸確認資料包的開銷降低了。為 TCP 新增這樣的擴充套件需要很長時間才能被採用,而對於 QUIC 來說,部署起來要容易得多。

擁塞控制演算法不是特定於 TCP 或 QUIC 的;它們可以被任何一種協議使用,事實上,大多數生產級 QUIC 實現都對CubicBBR進行了自定義實現。

0-RTT 連線設定

由於TCP設計成不依賴TLS下使用,導致不支援在握手期間傳送非TCP內容。導致在我們可以傳送第一個 HTTP 請求之前至少需要兩次往返的握手等待時間開銷,這是低效的。

QUIC 從一開始就考慮到了 TLS,因此在單一機制中結合了傳輸和加密握手。這意味著 QUIC 握手總共只需要一次往返即可完成,這比 TCP + TLS 1.3 少一次往返。

TLS、TCP 和 QUIC 握手持續時間
(TCP + TLS 與 QUIC 連線設定)

雖然最壞的情況(TCP + TLS 1.2,(a))QUIC 比 TCP 快兩個甚至三個往返,但是現代 TCP + TLS 1.3 也“只”進行兩次往返(很少顯示(b))

會話恢復和 0-RTT 經常被錯誤解釋為 QUIC 特定功能的事情。實際上,這些實際上是TLS 功能,它們已經以某種形式出現在 TLS 1.2 中,現在在TLS 1.3中完全成熟。

QUIC 使用0-RTT的更快連線設定實際上更多的是微優化,而不是革命性的新功能。與最先進的 TCP + TLS 1.3 設定相比,它最多可以節省一次往返。在第一次往返中實際可以傳送的資料量還受到許多安全考慮因素的限制。因此,如果您的使用者使用延遲非常高的網路(例如,RTT 超過 200 毫秒的衛星網路),或者您通常不傳送大量資料,則此功能將大放異彩。在其他情況下,您最多隻能獲得幾十毫秒,如果您已經在使用 CDN,則甚至更少。

UDP 和 TLS 效能
QUIC 使用 UDP 和重加密使它比 TCP 慢一點(但情況正在改善),是因為TCP和UDP通常直接在OS”快速核心中實現。相比之下,TLS 和 QUIC 的實現大多在較慢的使用者空間中。
TCP 和 QUIC 之間的實現差異
(TCP 和 QUIC 之間的實現差異)
對於 TCP,這些開銷遠低於 UDP,這主要是因為從歷史上看,TCP 的使用比 UDP 多得多。但在過去的五年中,大多數作業系統也為UDP新增了優化選項

其次,QUIC 有很多開銷,因為它單獨加密每個資料包。實踐中,優化的加密庫和允許批量加密 QUIC 資料包標頭的巧妙方法。最近,Google QUIC 堆疊最優化的版本目前比 TCP + TLS 慢約 20%

第 3 部分:實用的 HTTP/3 部署選項

對頁面和資源的更改

如果您已經在使用 HTTP/2,那麼在遷移到 HTTP/3 時您可能不需要對頁面或資源進行任何更改!

伺服器和網路

這些實現主要處理 HTTP/3 和 QUIC 的東西;它們本身並不是真正成熟的網路伺服器。

Pythonaioquic
Goquic-go
Rust(quiche)[https://github.com/cloudflare...] (Cloudflare), Quinn, Neqo (Mozilla)
C and C++mvfst (Facebook), MsQuic, (Microsoft), (Google), ngtcp2, LSQUIC (Litespeed), picoquic, quicly (Fastly)

開箱即用的完整 Web 伺服器的部分列表以及它們當前的 HTTP/3 支援如下:

  • Apache

    支援目前尚不清楚。什麼都沒有宣佈。它可能還需要 OpenSSL。(但請注意,有一個Apache Traffic Server實現。)

  • NGINX

    這是一個自定義實現。這是相對較新的,並且仍然是高度實驗性的。預計將在 2021 年底合併到主線 NGINX。這是相對較新的,並且仍然是高度實驗性的。請注意,還有一個補丁可以在 NGINX 上執行 Cloudflare的quic庫,目前可能更穩定。

  • Node.js

    這在內部使用 ngtcp2 庫。它被 OpenSSL 進度阻止,儘管他們計劃切換到 QUIC-TLS fork 以更快地獲得一些工作

  • IIS

    目前尚不清楚IIS支援,也沒有公佈任何內容。不過,它可能會在內部使用 MsQuic 庫。

  • Hypercorn

    這種整合aioquic,與實驗的支援。

  • Caddy

    這使用 quic-go,完全支援。

  • H2O

    這個用得很快,完全支援。

  • Litespeed

    這使用 LSQUIC,完全支援。

客戶端

大多數流行的瀏覽器已經(實驗性的)HTTP/3 支援!

瀏覽器對 HTTP/3 的支援相當成熟

參考資料

[HTTP/3 From A To Z: Core Concepts (Part 1)
](https://www.smashingmagazine....)

HTTP/3: Performance Improvements (Part 2)

[HTTP/3: Practical Deployment Options (Part 3)
](https://www.smashingmagazine....)

相關文章