瀏覽器允許的並發請求資源數是什麼意思?

IE 6789 以及chrome ,firefox 這些瀏覽器,允許的並發請求資源數是什麼情況?以前覺得好像IE 6是2個並發,求助知乎,想得到更詳細更正確的答案。這樣有助於理解前端性能上的一些問題。


@納米黑客 和 @bombless 的答案分別從前後端答覆了。我再補充和整理一下吧。

這個問題實際上涉及非常多的考慮和因此而發生的優化技術:

首先,是基於埠數量和線程切換開銷的考慮,瀏覽器不可能無限量的並發請求,因此衍生出來了並發限制和HTTP/1.1的Keep alive。 所以,IE6/7在HTTP/1.1下的並發才2,但HTTP/1.0卻是4。 而隨著技術的發展,負載均衡和各類NoSQL的大量應用,基本已經足以應對C10K的問題。 但卻並不是每個網站都懂得利用domain hash也就是多域名來加速訪問。因此,新的瀏覽器加大了並發數的限制,但卻仍控制在8以內。

後端的保護@bombless 已經說得很全面了,補充一小點就是瀏覽器即使放棄保護自己,將所有請求一起發給伺服器,也很可能會引發伺服器的並發閾值控制而被BAN,而另外一個控制在8以內的原因也是keep alive技術的存在使得瀏覽器復用現有連接和伺服器通信比創建新連接的性能要更好一些。

所以,瀏覽器的並發數其實並不僅僅只是良知的要求,而是雙方都需要保護自己的默契,並在可靠的情況下提供更好的性能。

稍微跑跑題據說有益身心健康。

=================== 我是健康的分割線 ========================

前端技術的逐漸成熟,還衍生了domain hash, cookie free, css sprites, js/css combine, max expires time, loading images on demand等等技術。這些技術的出現和大量使用都和並發資源數有關。

  1. 按照普通設計,當網站cookie信息有1 KB、網站首頁共150個資源時,用戶在請求過程中需要發送150 KB的cookie信息,在512 Kbps的常見上行帶寬下,需要長達3秒左右才能全部發送完畢。 儘管這個過程可以和頁面下載不同資源的時間並發,但畢竟對速度造成了影響。 而且這些信息在js/css/images/flash等靜態資源上,幾乎是沒有任何必要的。 解決方案是啟用和主站不同的域名來放置靜態資源,也就是cookie free。
  2. 將css放置在頁面最上方應該是很自然的習慣,但第一個css內引入的圖片下載是有可能堵塞後續的其他js的下載的。而在目前普遍過百的整頁請求數的前提下,瀏覽器提供的僅僅數個並發,對於進行了良好優化甚至是前面有CDN的系統而言,是極大的性能瓶頸。 這也就衍生了domain hash技術來使用多個域名加大並發量(因為瀏覽器是基於domain的並發控制,而不是page),不過過多的散布會導致DNS解析上付出額外的代價,所以一般也是控制在2-4之間。 這裡常見的一個性能小坑是沒有機制去確保URL的哈希一致性(即同一個靜態資源應該被哈希到同一個域名下),而導致資源被多次下載。
  3. 再怎麼提速,頁面上過百的總資源數也仍然是很可觀的,如果能將其中一些很多頁面都用到的元素如常用元素如按鈕、導航、Tab等的背景圖,指示圖標等等合併為一張大圖,並利用css background的定位來使多個樣式引用同一張圖片,那也就可以大大的減少總請求數了,這就是css sprites的由來。
  4. 全站的js/css原本並不多,其合併技術的產生卻是有著和圖片不同的考慮。 由於cs/js通常可能對dom布局甚至是內容造成影響,在瀏覽器解析上,不連貫的載入是會造成多次重新渲染的。因此,在網站變大需要保持模塊化來提高可維護性的前提下,js/css combine也就自然衍生了,同時也是minify、compress等對內容進行多餘空格、空行、注釋的整理和壓縮的技術出現的原因。
  5. 隨著cookie free和domain hash的引入,網站整體的打開速度將會大大的上一個台階。 這時我們通常看到的問題是大量的請求由於全站公有header/footer/nav等關係,其對應文件早已在本地緩存里存在了,但為了確保這個內容沒有發生修改,瀏覽器還是需要請求一次伺服器,拿到一個304 Not Modified才能放心。 一些比較大型的網站在建立了比較規範的發布制度後,會將大部分靜態資源的有效期設置為最長,也就是Cache-Control max-age為10年。 這樣設置後,瀏覽器就再也不會在有緩存的前提下去確認文件是否有修改了。 超長的有效期可以讓用戶在訪問曾訪問過的網站或網頁時,獲得最佳的體驗。 帶來的複雜性則體現在每次對靜態資源進行更新時,必須發布為不同的URL來確保用戶重新載入變動的資源。
  6. 即使是這樣做完,仍然還存在著一個很大的優化空間,那就是很多頁面瀏覽量很大,但其實用戶直接很大比例直接就跳走了,第一屏以下的內容用戶根本就不感興趣。 對於超大流量的網站如淘寶、新浪等,這個問題尤其重要。 這個時候一般是通過將圖片的src標籤設置為一個loading或空白的樣式,在用戶翻頁將圖片放入可見區或即將放入可見區時再去載入。 不過這個優化其實和並發資源數的關係就比較小了,只是對一些散布不合理,或第一頁底部的資源會有一定的幫助。 主要意圖還是降低帶寬費用。

總的來說,各類技術都是為了能讓用戶更快的看到頁面進行下一步操作,但卻不必將寶貴的資源浪費在沒有必要的重複請求、不看的內容上。


首先,請允許我精簡了一下題目……

其次,我的答案跑題了,請看討論和@bombless 的答案……

瀏覽器的並發請求數目限制是針對同一域名的。

意即,同一時間針對同一域名下的請求有一定數量限制。超過限制數目的請求會被阻塞,這就是為什麼會有zhimg.com, http://twimg.com 之類域名的原因。

(這是其中一個原因,另一個主要原因是,向 http://zhihu.com 請求資源會把 http://zhihu.com 下本地的所有 cookie 發送過去,這是請求圖片,js等資源不需要的,會造成很大的浪費,詳情見http://webmasters.stackexchange.com/questions/26753/why-do-big-sites-host-their-images-css-on-external-domains)

如圖,有的請求會持續很長時間,如果把 img, css, js... 都放到 http://zhihu.com 一個域名下面,其他請求就遲遲無法完成,瀏覽者看來就是『卡住了』。而把圖片放到 http://zhimg.com 之後,css和圖片就可以並發請求了。

具體不同瀏覽器這個限制的數目

圖片來自http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/以下文章中有更詳細的說明:

  1. http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/

  2. http://www.feelcss.com/browser-concurrent-requests.html

以及 stackoverflow 中的相關問題

  1. http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser
  2. http://webmasters.stackexchange.com/questions/26753/why-do-big-sites-host-their-images-css-on-external-domains


我想對@納米黑客 的答案基於自己對 HTTP / TCP / IP 整個協議棧的理解做一點補充。

羅列一下瀏覽器這麼決定可能有什麼考慮

  1. 由於 TCP 協議的限制,PC 端只有65536個埠可用以向外部發出連接,而操作系統對半開連接數也有限制以保護操作系統的 TCPIP 協議棧資源不被迅速耗盡,因此瀏覽器不好發出太多的 TCP 連接,而是採取用完了之後再重複利用 TCP 連接或者乾脆重新建立 TCP 連接的方法。

  2. 如果採用阻塞的套接字模型來建立連接,同時發出多個連接會導致瀏覽器不得不多開幾個線程,而線程有時候算不得是輕量級資源,畢竟做一次上下文切換開銷不小。

  3. 這是瀏覽器作為一個有良知的客戶端在保護伺服器。就像乙太網的衝突檢測機制,客戶端在使用公共資源的時候必須要自行決定一個等待期。當超過2個客戶端要使用公共資源時,強勢的那個邪惡的客戶端可能會導致弱勢的客戶端完全無法訪問公共資源。從前迅雷被噴就是因為它不是一個有良知的客戶端,它作為 HTTP 協議客戶端沒有考慮到伺服器的壓力,作為 BT 客戶端沒有考慮到自己回饋上傳量的義務。

另外關於@余天升 在@納米黑客 的答案評論中提到的RFC-2616裡面8.1.4 Practical Considerations。

在46頁:

Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy. A proxy SHOULD use up to 2*N connections to another server or proxy, where N is the number of simultaneously active users. These guidelines are intended to improve HTTP response times and avoid congestion.

的確是。貼個無關鏈接:https://www.ibm.com/developerworks/cn/web/wa-lo-comet/#N10194

補充:半開連接指的是 TCP 連接的一種狀態,當客戶端向伺服器端發出一個 TCP 連接請求,在客戶端還沒收到伺服器端的回應並發回一個確認的數據包時,這個 TCP 連接就是一個半開連接。

若伺服器到超時以後仍無響應,那麼這個 TCP 連接就等於白費了,所以操作系統會本能的保護自己,限制 TCP 半開連接的總個數,以免有限的內核態內存空間被維護 TCP 連接所需的內存所浪費。


推薦閱讀:

有哪些利於前端新手練習、理解JS的獨立小項目?
如何知道瀏覽器當前執行的JS代碼的位置?
如何使用自己的編程能力提高生活質量?
各位前端大神能不能通俗的說一下PostCSS到底能做什麼?對於手寫css的優勢在哪?
airbnb 的 Hypernova 跟已有的 Universal JS 解決方案相比有哪些優勢?

TAG:前端開發 | JavaScript | HTTP |