HTTP/1.x 中的連線管理
連線管理是 HTTP 中的一個關鍵主題:建立和維護連線在很大程度上影響了網站和 Web 應用程式的效能。在 HTTP/1.x 中,有幾種模型:短時連線、持久連線和HTTP 流水線。
HTTP 主要依靠 TCP 作為其傳輸協議,在客戶端和伺服器之間提供連線。在初期,HTTP 使用單一模型來處理此類連線。這些連線是短時連線:每次需要傳送請求時都會建立一個新連線,並在收到響應後關閉。
這種模型天生就限制了效能:開啟每個 TCP 連線都是一個資源消耗大的操作。客戶端和伺服器之間必須交換多條訊息。當需要傳送請求時,網路延遲和頻寬會影響效能。現代網頁需要許多請求(十幾個或更多)才能提供所需的資訊量,這證明了這種早期模型的效率低下。
HTTP/1.1 中建立了兩種較新的模型。持久連線模型保持連線在連續請求之間開啟,減少了開啟新連線所需的時間。HTTP 流水線模型更進一步,它在不等待響應的情況下發送多個連續請求,大大減少了網路延遲。

注意:HTTP/2 添加了其他連線管理模型。
重要的是,HTTP 中的連線管理適用於兩個連續節點之間的連線,它是逐跳的,而不是端到端的。客戶端與其第一個代理之間的連線模型可能與代理與目標伺服器(或任何中間代理)之間的模型不同。涉及定義連線模型的 HTTP 標頭,例如Connection和Keep-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 請求都可以進行流水線操作:只有冪等方法,即GET、HEAD、PUT和DELETE,才能安全地重播。如果發生故障,可以重複流水線內容。
如今,每個符合 HTTP/1.1 標準的代理和伺服器都應該支援流水線,儘管許多在實踐中都有侷限性:這是沒有現代瀏覽器預設啟用此功能的一個重要原因。
域名分片
注意:除非您有非常具體的即時需求,否則請不要使用這種已棄用的技術;請改用 HTTP/2。在 HTTP/2 中,域名分片不再有用:HTTP/2 連線能夠很好地處理並行非優先請求。域名分片甚至會損害效能。大多數 HTTP/2 實現使用一種稱為連接合並的技術來恢復最終的域名分片。
由於 HTTP/1.x 連線是序列化請求的,即使沒有任何排序,如果沒有足夠大的可用頻寬,它也無法達到最佳狀態。作為解決方案,瀏覽器會為每個域開啟多個連線,並行傳送請求。以前預設是 2 到 3 個連線,但現在已增加到更常見的 6 個並行連線。如果嘗試超過這個數量,可能會觸發伺服器端的DoS保護。
如果伺服器希望網站或應用程式響應更快,伺服器可以強制開啟更多連線。例如,它可以將所有資源拆分到多個域,而不是將所有資源放在同一個域(例如www.example.com)上,例如www1.example.com、www2.example.com、www3.example.com。這些域中的每一個都解析到同一個伺服器,Web 瀏覽器將為每個域開啟 6 個連線(在我們的示例中,將連線提升到 18 個)。此技術稱為域名分片。

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