一次 HTTP 請求就需要一次 TCP 連接嗎?


一次 HTTP 請求就需要一次 TCP 連接嗎?

本文寫於 2021 年 2 月 9 日

太長不看版本:短連接需要,長連接不需要。

TCP 的連接與斷開

現代瀏覽器在與服務器建立了一個 TCP 連接后是否會在一個 HTTP 請求完成后斷開呢?

如果會,那什么情況下會斷開?

在 HTTP/0.9 版本中,HTTP 請求是以短連接進行的,因此在發送完 HTTP 的響應之后,服務器就會斷開 TCP 連接。

可是這樣是一件很耗資源、很耗時間的事情,所以在 1.0 版本中,新增了 keep-alive 字段,讓長連接被 HTTP 支持了(此時默認還是不會開啟長連接)。

所謂長連接,就是完成這個 HTTP 請求之后,不要斷開 HTTP 請求使用的 TCP 連接。好處是連接可以被重新使用,之后發送 HTTP 請求的時候就不需要重新建立 TCP 連接了,以及如果維持連接,那么 SSL 的開銷也可以避免。

好處如此之多,所以 HTTP/1.1 就把 Connection: keep-alive 頭寫進了標准,並且默認開啟持久連接。

你必須在請求中聲明:Connection: close 才會讓每次 HTTP 請求都重新建立 TCP 連接。

因此我們有了答案:

  1. 如果是「短連接」,那么一次 TCP 連接就只能對應一次 HTTP 請求;
  2. 如果是「長連接」,那么一次 TCP 連接就可以發送多個 HTTP 請求了。

可以一次性發送多個 HTTP 請求嗎?

在 HTTP/1.1 協議中存在一個問題:單個 TCP 連接在一個時刻只能處理一個請求。

也就是說你一個請求處理完了才能處理下一個請求。

這就要看看 Pipelining 了,所謂 pipe 就是管道,而 Pipelining 是 HTTP/1.1 規范中的字段,意為 HTTP 流水線(英語:HTTP pipelining)。

它能將多個 HTTP 請求整批提交,在發送過程中不需先等待服務器的回應。

但唯一的問題在於,這個東西在瀏覽器中是默認關閉的。

因為該技術存在很多問題:

  • 一些代理服務器不能正確的處理 HTTP Pipelining;
  • 正確的流水線實現是復雜的;
  • Head-of-line Blocking 連接頭阻塞:在建立起一個 TCP 連接之后,假設客戶端在這個連接連續向服務器發送了幾個請求。按照標准,服務器應該按照收到請求的順序返回結果,假設服務器在處理首個請求時花費了大量時間,那么后面所有的請求都需要等着首個請求結束才能響應。

但是,HTTP2 提供了 Multiplexing 多路傳輸特性,讓我們可以在一個 TCP 連接中同時完成多個 HTTP 請求。

所以,在 HTTP/1.1 時代,瀏覽器提高頁面加載效率的方法主要有下面兩種:

  • 維持和服務器已經建立的 TCP 連接,在同一連接上順序處理多個請求;
  • 和服務器建立多個 TCP 連接。

瀏覽器對同一 host 的 TCP 連接上限

假設我們還處在 HTTP/1.1 時代,那個時候沒有多路傳輸。

當瀏覽器拿到一個有幾十張圖片的網頁該怎么辦呢?

肯定不能只開一個 TCP 連接順序下載,那樣用戶肯定等的很難受。但是如果每個圖片都開一個 TCP 連接發 HTTP 請求,那電腦或者服務器都可能受不了——要是有 1000 張圖片的話總不能開 1000 個 TCP 連接吧。

所以瀏覽器允許我們對同一 host 開啟多個 TCP 連接,每個瀏覽器的數量是不一樣的。Chrome 最多允許對同一個 Host 建立六個 TCP 連接。

如果圖片都是 HTTPS 連接並且在同一個域名下,那么瀏覽器在 SSL 握手之后會和服務器商量能不能用 HTTP2,如果能的話就使用 Multiplexing 功能在這個連接上進行多路傳輸。

不過也未必會所有掛在這個域名的資源都會使用一個 TCP 連接去獲取,但是可以確定的是 Multiplexing 很可能會被用到。

如果發現用不了 HTTP2 呢?或者用不了 HTTPS(現實中的 HTTP2 都是在 HTTPS 上實現的,所以也就是只能使用 HTTP/1.1)呢?

那瀏覽器就會在一個 HOST 上建立多個 TCP 連接,連接數量的最大限制取決於瀏覽器設置。這些連接會在空閑的時候被瀏覽器用來發送新的請求。

如果所有的連接都正在發送請求呢?那其他的請求就只能等等了。

參考:

https://w.cnblogs.com/williamjie/p/11075565.html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Connection_management_in_HTTP_1.x
https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

(完)


免責聲明!

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



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