什麼是隊頭阻塞以及如何解決

前言

一般咱們提到隊頭阻塞,指的多是TCP協議中的隊頭阻塞,可是HTTP1.1中也有一個相似TCP隊頭阻塞的問題,下面各自介紹一下。瀏覽器

TCP隊頭阻塞

隊頭阻塞(head-of-line blocking)發生在一個TCP分節丟失,致使其後續分節不按序到達接收端的時候。該後續分節將被接收端一直保持直到丟失的第一個分節被髮送端重傳併到達接收端爲止。該後續分節的延遲遞送確保接收應用進程可以按照發送端的發送順序接收數據。這種爲了達到徹底有序而引入的延遲機制很是有用,但也有不利之處。性能優化

假設在單個TCP鏈接上發送語義獨立的消息,好比說服務器可能發送3幅不一樣的圖像供Web瀏覽器顯示。爲了營造這幾幅圖像在用戶屏幕上並行顯示的效果,服務器先發送第一幅圖像的一個斷片,再發送第二幅圖像的一個斷片,而後再發送第三幅圖像的一個斷片;服務器重複這個過程,直到這3幅圖像所有成功地發送到瀏覽器爲止。服務器

要是第一幅圖像的某個斷片內容的TCP分節丟失了,客戶端將保持已到達的不按序的全部數據,直到丟失的分節重傳成功。這樣不只延緩了第一幅圖像數據的遞送,也延緩了第二幅和第三幅圖像數據的遞送。網絡

HTTP隊頭阻塞

上面用瀏覽器請求圖片資源舉例子,但實際上HTTP自身也有相似TCP隊頭阻塞的狀況。要介紹HTTP隊頭阻塞,就須要先講講HTTP的管道化(pipelining)。性能

HTTP管道化是什麼

HTTP1.1 容許在持久鏈接上可選的使用請求管道。這是相對於keep-alive鏈接的又一性能優化。在相應到達以前,能夠將多條請求放入隊列,當第一條請求發往服務器的時候,第二第三條請求也能夠開始發送了,在高延時網絡條件下,這樣作能夠下降網絡的環回時間,提升性能。優化

非管道化與管道化的區別示意 ui

HTTP管道化產生的背景

在通常狀況下,HTTP遵照「請求-響應」的模式,也就是客戶端每次發送一個請求到服務端,服務端返回響應。這種模式很是容易理解,可是效率並非那麼高,爲了提升速度和效率,人們作了不少嘗試:google

  • 最簡單的狀況下,服務端一旦返回響應後就會把對應的鏈接關閉,客戶端的多個請求其實是串行發送的。
  • 除此以外,客戶端能夠選擇同時建立多個鏈接,在多個鏈接上並行的發送不一樣請求。可是建立更多鏈接也帶來了更多的消耗,當前大部分瀏覽器都會限制對同一個域名的鏈接數。
  • 從HTTP1.0開始增長了持久鏈接的概念(HTTP1.0的Keep-Alive和HTTP1.1的persistent),可使HTTP可以複用已經建立好的鏈接。客戶端在收到服務端響應後,能夠複用上次的鏈接發送下一個請求,而不用從新創建鏈接。
  • 現代瀏覽器大多采用並行鏈接與持久鏈接共用的方式提升訪問速度,對每一個域名創建並行地少許持久鏈接。
  • 而在持久鏈接的基礎上,HTTP1.1進一步地支持在持久鏈接上使用管道化(pipelining)特性。管道化容許客戶端在已發送的請求收到服務端的響應以前發送下一個請求,藉此來減小等待時間提升吞吐;若是多個請求能在同一個TCP分節發送的話,還能提升網絡利用率。可是由於HTTP管道化自己可能會致使隊頭阻塞的問題,以及一些其餘的緣由,現代瀏覽器默認都關閉了管道化。

HTTP管道化的限制

  1. 管道化要求服務端按照請求發送的順序返回響應(FIFO),緣由很簡單,HTTP請求和響應並無序號標識,沒法將亂序的響應與請求關聯起來。
  2. 客戶端須要保持未收到響應的請求,當鏈接意外中斷時,須要從新發送這部分請求。
  3. 只有冪等的請求才能進行管道化,也就是隻有GET和HEAD請求才能管道化,不然可能會出現意料以外的結果

HTTP管道化引發的請求隊頭阻塞

前面提到HTTP管道化要求服務端必須按照請求發送的順序返回響應,那若是一個響應返回延遲了,那麼其後續的響應都會被延遲,直到隊頭的響應送達。cdn

如何解決隊頭阻塞

如何解決HTTP隊頭阻塞

對於HTTP1.1中管道化致使的請求/響應級別的隊頭阻塞,可使用HTTP2解決。HTTP2不使用管道化的方式,而是引入了幀、消息和數據流等概念,每一個請求/響應被稱爲消息,每一個消息都被拆分紅若干個幀進行傳輸,每一個幀都分配一個序號。每一個幀在傳輸是屬於一個數據流,而一個鏈接上能夠存在多個流,各個幀在流和鏈接上獨立傳輸,到達以後在組裝成消息,這樣就避免了請求/響應阻塞。blog

固然,即便使用HTTP2,若是HTTP2底層使用的是TCP協議,仍可能出現TCP隊頭阻塞。

如何解決TCP隊頭阻塞

TCP中的隊頭阻塞的產生是由TCP自身的實現機制決定的,沒法避免。想要在應用程序當中避免TCP隊頭阻塞帶來的影響,只有捨棄TCP協議。

好比google推出的quic協議,在某種程度上能夠說避免了TCP中的隊頭阻塞,由於它根本不使用TCP協議,而是在UDP協議的基礎上實現了可靠傳輸。而UDP是面向數據報的協議,數據報之間不會有阻塞約束。

此外還有一個SCTP(流控制傳輸協議),它是和TCP、UDP在同一層次的傳輸協議。SCTP的多流特性也能夠儘量的避免隊頭阻塞的狀況。

總結

從TCP隊頭阻塞和HTTP隊頭阻塞的緣由咱們能夠看到,出現隊頭阻塞的緣由有兩個:

  1. 獨立的消息數據都在一個鏈路上傳輸,也就是有一個「隊列」。好比TCP只有一個流,多個HTTP請求共用一個TCP鏈接
  2. 隊列上傳輸的數據有嚴格的順序約束。好比TCP要求數據嚴格按照序號順序,HTTP管道化要求響應嚴格按照請求順序返回

因此要避免隊頭阻塞,就須要從以上兩個方面出發,好比quic協議不使用TCP協議而是使用UDP協議,SCTP協議支持一個鏈接上存在多個數據流等等。

相關文章
相關標籤/搜索