HTTP/1.x 中的連線管理

連線管理是 HTTP 中的一個關鍵主題:建立和維護連線在很大程度上影響了網站和 Web 應用程式的效能。在 HTTP/1.x 中,有幾種模型:短時連線持久連線HTTP 流水線

HTTP 主要依靠 TCP 作為其傳輸協議,在客戶端和伺服器之間提供連線。在初期,HTTP 使用單一模型來處理此類連線。這些連線是短時連線:每次需要傳送請求時都會建立一個新連線,並在收到響應後關閉。

這種模型天生就限制了效能:開啟每個 TCP 連線都是一個資源消耗大的操作。客戶端和伺服器之間必須交換多條訊息。當需要傳送請求時,網路延遲和頻寬會影響效能。現代網頁需要許多請求(十幾個或更多)才能提供所需的資訊量,這證明了這種早期模型的效率低下。

HTTP/1.1 中建立了兩種較新的模型。持久連線模型保持連線在連續請求之間開啟,減少了開啟新連線所需的時間。HTTP 流水線模型更進一步,它在不等待響應的情況下發送多個連續請求,大大減少了網路延遲。

Compares the performance of the three HTTP/1.x connection models: short-lived connections, persistent connections, and HTTP pipelining.

注意:HTTP/2 添加了其他連線管理模型。

重要的是,HTTP 中的連線管理適用於兩個連續節點之間的連線,它是逐跳的,而不是端到端的。客戶端與其第一個代理之間的連線模型可能與代理與目標伺服器(或任何中間代理)之間的模型不同。涉及定義連線模型的 HTTP 標頭,例如ConnectionKeep-Alive,都是逐跳標頭,它們的值可以由中間節點更改。

一個相關主題是 HTTP 連線升級的概念,其中 HTTP/1.1 連線升級到不同的協議,例如 TLS/1.0、WebSocket,甚至明文 HTTP/2。這種協議升級機制在其他地方有更詳細的文件。

短時連線

HTTP 的原始模型,也是 HTTP/1.0 中的預設模型,是短時連線。每個 HTTP 請求都在自己的連線上完成;這意味著在每個 HTTP 請求之前都會發生 TCP 握手,並且這些請求是序列化的。

TCP 握手本身很耗時,但 TCP 連線會根據其負載進行調整,隨著更多持續(或熱)連線而變得更高效。短時連線沒有利用 TCP 的這種效率特性,並且透過在新連線(冷連線)上傳輸而使效能從最佳狀態下降。

此模型是 HTTP/1.0 中使用的預設模型(如果沒有Connection標頭,或者其值設定為close)。在 HTTP/1.1 中,此模型僅在傳送Connection標頭且其值為close時使用。

注意:除非處理的是不支援持久連線的非常老的系統,否則沒有令人信服的理由使用此模型。

持久連線

短時連線有兩個主要缺點:建立新連線所需的時間很長,並且底層 TCP 連線的效能只有在使用一段時間後(熱連線)才會變好。為了緩解這些問題,持久連線的概念被設計出來,甚至在 HTTP/1.1 之前。這也可以稱為保持活動連線

持久連線是保持開啟一段時間的連線,可以用於多個請求,從而省去了新的 TCP 握手,並利用了 TCP 的效能增強功能。此連線不會永遠保持開啟狀態:空閒連線會在一段時間後關閉(伺服器可以使用Keep-Alive標頭來指定連線應保持開啟的最短時間)。

持久連線也有缺點;即使空閒,它們也會消耗伺服器資源,並且在高負載下,可能會發生DoS 攻擊。在這種情況下,使用非持久連線(一旦空閒就關閉)可以提供更好的效能。

HTTP/1.0 連線預設不是持久的。將Connection設定為除close之外的任何值(通常是retry-after)都會使它們持久。

在 HTTP/1.1 中,永續性是預設的,並且不再需要該標頭(但通常會將其作為一種防禦措施新增,以防需要回退到 HTTP/1.0 的情況)。

HTTP 流水線

注意:現代瀏覽器中預設不啟用 HTTP 流水線

  • 有錯誤的代理仍然很常見,它們會導致 Web 開發人員無法預見和輕鬆診斷的奇怪和不穩定的行為。
  • 流水線正確實現起來很複雜:傳輸資源的尺寸、將使用的有效往返時間 (RTT)以及有效頻寬,都會直接影響流水線帶來的改進。如果不瞭解這些,重要的訊息可能會被不重要的訊息延遲。重要性的概念甚至在頁面佈局過程中也會演變!因此,HTTP 流水線在大多數情況下只會帶來微不足道的改進。
  • 流水線受到隊頭阻塞的影響。

由於這些原因,流水線已被更好的演算法(HTTP/2 使用的多路複用)所取代。

預設情況下,HTTP 請求是順序發出的。只有在收到當前請求的響應後,才會發出下一個請求。由於它們受到網路延遲和頻寬限制的影響,這可能會導致伺服器“看到”下一個請求之前出現顯著延遲。

流水線是在同一持久連線上傳送連續請求,而無需等待響應的過程。這避免了連線的延遲。理論上,如果將兩個 HTTP 請求打包到同一個 TCP 訊息中,效能也可以提高。典型的MSS(最大分段大小)足夠大,可以包含幾個簡單的請求,儘管 HTTP 請求的大小需求仍在不斷增長。

並非所有型別的 HTTP 請求都可以進行流水線操作:只有冪等方法,即GETHEADPUTDELETE,才能安全地重播。如果發生故障,可以重複流水線內容。

如今,每個符合 HTTP/1.1 標準的代理和伺服器都應該支援流水線,儘管許多在實踐中都有侷限性:這是沒有現代瀏覽器預設啟用此功能的一個重要原因。

域名分片

注意:除非您有非常具體的即時需求,否則請不要使用這種已棄用的技術;請改用 HTTP/2。在 HTTP/2 中,域名分片不再有用:HTTP/2 連線能夠很好地處理並行非優先請求。域名分片甚至會損害效能。大多數 HTTP/2 實現使用一種稱為連接合並的技術來恢復最終的域名分片。

由於 HTTP/1.x 連線是序列化請求的,即使沒有任何排序,如果沒有足夠大的可用頻寬,它也無法達到最佳狀態。作為解決方案,瀏覽器會為每個域開啟多個連線,並行傳送請求。以前預設是 2 到 3 個連線,但現在已增加到更常見的 6 個並行連線。如果嘗試超過這個數量,可能會觸發伺服器端的DoS保護。

如果伺服器希望網站或應用程式響應更快,伺服器可以強制開啟更多連線。例如,它可以將所有資源拆分到多個域,而不是將所有資源放在同一個域(例如www.example.com)上,例如www1.example.comwww2.example.comwww3.example.com。這些域中的每一個都解析到同一個伺服器,Web 瀏覽器將為每個域開啟 6 個連線(在我們的示例中,將連線提升到 18 個)。此技術稱為域名分片

Without domain sharding, a client requests six images from a domain with a maximum of two requests taking place in parallel. With domain sharding, the images are available from two domains and the client can run four requests in parallel, downloading the images in less time.

總結

改進的連線管理可以大大提升 HTTP 的效能。使用 HTTP/1.1 或 HTTP/1.0,使用持久連線(至少直到它空閒)可以實現最佳效能。然而,流水線的失敗導致了更高階連線管理模型的設計,這些模型已整合到 HTTP/2 中。

另見