答案
不一定。
發的不同域名,肯定不復用。
發的同域名。若第一個請求與第二個請求並行發送,不復用。
發的同域名,並且是第一個請求完事了才發第二個請求。則看是否有 connection: keep-alive 請求頭,沒有則不復用。
發的同域名,第一個請求完了后發第二個請求,有 connection: keep-alive 請求頭。則復用同一個 TCP 連接。
補充說明
HTTP 1.1 里大概規范了幾項提高性能的手段:
- 持久連接 (keep-alive/persistent connection)
- 並行連接
- Pipelining
持久連接
每一個請求都會重新建立一個 TCP 連接,一旦響應返回,就關閉連接。 而建立一個連接,則需要進行三次握手。HTTP 1.1 出了一個請求頭 connection,默認 keep-alive,告訴服務器不關閉 TCP 連接。
並行連接
由於現代網頁通常包含了復數個(>=10)資源,而按照默認設定,一個連接中的每一個請求必須等待收到響應后才能發送下一個請求,所以如果復數的資源請求全部在一個連接 one by one 發送給服務器顯然會很慢,而為了彌補這一缺陷,瀏覽器通常會默認開啟多個 TCP 連接,然后再根據每個連接的狀態在其中依次發送數據請求,而且客戶端有權任意關閉超發的連接。各個瀏覽器允許的並行連接數大致是這樣的(From SO):
Firefox 2: 2
Firefox 3+: 6
Opera 9.26: 4
Opera 12: 6
Safari 3: 4
Safari 5: 6
IE 7: 2
IE 8: 6
IE 10: 8
Chrome: 6
由於 TCP 協議本身有慢啟動的特征,會隨着時間調諧連接的最大速度,因此在現代瀏覽器中持久連接和並行連接通常是搭配在一起使用的—— 一方面由於持久連接的存在,每個 TCP 連接已經處於調諧后的狀態,另一方面持久連接可以避免重新三次握手的開銷。
在 Chrome 中,頁面初始並行加載一堆靜態資源是會最大開 6 個 TCP 連接去並行運作,其后發 Ajax 請求則是復用之前的 TCP 連接。
Pipelining
按照 HTTP 1.1 的描述,還有種可以提升性能的方案是管道化,可以在一個 TCP 連接中並行執行多個請求並返回。
因為這項技術比較復雜,如何能在一個 TCP 中有序的處理所接收到的包,並且不會亂序返回,這在早期沒有規范,所以各大瀏覽器都沒有支持此功能,形同雞肋。
關於 HTTP 2
HTTP 2 為了性能做了不少努力,比如提供了規范以支持連接的多路復用。
如前文所說,在同一個 TCP 連接里面同時發生兩個請求響應就不是那么簡單。而 HTTP 2 正是提供了這樣的規范,可以給數據拆成包,並打上包的順序標簽以供 TCP 能正確認知接收的包的順序。
所以很多網絡優化的知識已經過時
- 因為“所有的 HTTP 2.0 的請求都在一個 TCP 鏈接上”,“資源合並減少請求”,比如 CSS Sprites ,多個 JS 文件、CSS 文件合並等手段沒有效果,或者說沒有必要。
- 因為“多路復用”,采用“cdn1.cn,cdn2.cn,cdn3.cn,打開多個 TCP 會話,突破瀏覽器對同一域名的鏈接數的限制”的手段是沒有必要的。因為因為資源都是並行交錯發送,且沒有限制,不需要額外的多域名並行下載。
- 因為“服務器推送”,內嵌資源(如base64的圖片)的優化手段也變得沒有意義了。而且使用服務器推送的資源的方式更加高效,因為客戶端還可以緩存起來,甚至可以由不同的頁面共享(依舊遵循同源策略)