合格前端需瞭解的知識 --- HTTP系列之隊頭阻塞(閱讀時常5分鐘)

 

簡單聊下前端日常接觸的HTTP協議

前言

2020年已過半,近期爲了準備面試,重新學習了HTTP的部分知識點,以下是我個人對HTTP協議發展的理解,通過近期學習整理的筆記。

 

HTTP是一個屬於應用層的面向對象的協議,主要特點概括主要有5點:

1、無狀態:協議對於事務處理無記憶能力,每次客戶端發起請求,都會新開一個TCP連接。

2、支持客戶/服務器模式。

3、簡單快速:客戶端請求只需發送請求方法和路徑。

4、靈活:允許任意類型的數據對象,使用Content-Type加以標記。

5、無連接:TCP不可複用,即服務器處理完客戶請求並收到應答後,斷開連接,節省傳輸時間。

 

我將着重對無狀態、無連接涉及到的點進行一些講解。

1、無狀態

對於無狀態,就需要扯到Cookie和Session了,他們是對HTTP協議無狀態的補充和改良。爲什麼這麼說呢?

在理解無狀態的定義之後,我們可以舉個例子:

在我們訪問需要權限的內容時,如果沒有Cookie和Session來存儲客戶端首次輸入的用戶名和密碼,那麼在接下來每一次訪問時,都需要重新輸入,這一項就已經非常繁瑣了。

 

2、無連接

對於無連接,我們分HTTP不同版本進行講述,以下幾點內容也是面試中經常會問到的:

首先在HTTP 0.9版本中,每次請求都需要新開一個TCP連接,是不可複用的,這非常的消耗性能。

因此在HTTP 1.0版本,引入了Keep-Alive 持久連接的概念,使用Connection: Keep-Alive的首部來操作TCP的持久連接,有效的解決了TCP連接不可複用的問題,減少性能損耗。

但是,他也存在一定的問題,在HTTP 1.0中其實默認的是短鏈接,沒有正式規定Connection: Keep-Alive操作,這時HTTP 1.1版本出現了。

 

pipelining 管道技術

對於HTTP 1.1版本,不僅繼承了HTTP 1.0的特點,且克服了諸多在HTTP 1.0上的性能問題,不僅正式規定了Connection: Keep-Alive的操作,而且通過pipelining管道技術實現一次性發送多個請求,以提高吞吐和性能,如下圖(ps:在網上找的圖),左圖爲普通長連接的的請求TCP請求過程,右圖爲通過pipelining管道技術實現的一次性發送多個請求。

 

 

隊頭阻塞

然而,pipelining管道技術有隊頭阻塞問題,即服務器在接收響應時,要求必須按照發送請求的順序返回。若第一個請求被堵塞了,則後面的請求即使處理完畢了,也需要等待,如下圖。

 

 

數據分幀

就在這時,光芒照在了HTTP 2.0上,HTTP 2.0 over TCP出現了,它通過數據分幀 — 多個請求複用一個TCP連接(最多6個),然後每個request-response都被拆分成若干個frame幀發送,這樣即使一個請求被阻塞了,也不會影響其他請求,如下圖,其實它只解決了一部分問題~

 

 

ps:如果隊頭阻塞的粒度是http request級別,那麼HTTP/2 over TCP的確解決了HTTP 1.1中的問題。但是在HTTP 2.0 over TCP版本都是基於TCP實現。因此,HTTP 2.0 over TCP並沒有解決數據傳輸層的隊頭阻塞問題。

 

如上圖所示,當第一個數據包發生丟包的時候,TCP協議會發生阻塞會進行數據重傳。雖然TCP有快速重傳等機制來緩解這個問題,但是隻能緩解,無法完全避免。

 

那麼如何解決傳輸層的隊頭阻塞問題呢?

因爲應用層無法解決傳輸層的問題,因此需要重新設計和實現傳輸層,接下來我們看看Google橫空出世的HTTP 2.0 over QUIC怎麼解決這個問題。

 

UDP

HTTP 2.0 over QUIC也可以稱爲HTTP 3.0,它使用UDP實現了一個可靠的多路複用傳輸層。我們所知的UDP是面向數據報文的,數據包之間沒有約束(這也帶來了一定的安全性問題,詳見UDP協議及其安全隱患),QUIC就是充分利用這個特性解決傳輸層的隊頭阻塞問題的。當然,QUIC的協議實現有非常多的細節,而這方面Google確實做得非常好,如果你想進一步瞭解,可以關注他們的開源實現

 

小結

1、HTTP 0.9版本,TCP不可複用,耗性能。

2、HTTP 1.0版本,引入Keepei-Alive概念,實爲短連接,未正名。

3、HTTP 1.1版本,爲長連接,正名Keep-Alive,引入pipelining 管道技術,但有隊頭阻塞問題。

4、HTTP 2.0 over TCP版本,啓用數據分幀,只解決粒度級別爲http request的隊頭阻塞。

5、HTTP 2.0 over QUIC即HTTP 3.0版本,啓用UDP協議真正的解決傳輸層的隊頭阻塞問題。

https://zhuanlan.zhihu.com/p/148381179

 

 

典型的HTTP工作模式是點對點的,其中包括2個參與者,即客戶端和服務器,儘管還可以引入其它參與者,如正向代理,反向代理,但其本質上還是點到點的。其它角色或扮演客戶端,或服務器,或二者,充當中間人蔘與到HTTP的通訊中,HTTP協議本身僅通過特定頭字段標記【Via】是否通過中間人轉發,並不改變點到點通訊的本質。
進一步,在HTTP/1.1中客戶端發送請求,服務器迴應客戶端的請求,客戶端發送的每一個請求,需要等待服務器迴應後才能發送下一個請求,即所有請求在一個FIFO隊列裏,如果隊頭請求意外阻塞,這樣就會造成隊頭阻塞。即如果隊頭的請求響應時間太長,會影響後面的請求的處理。類比現實中,去銀行辦理業務,隊列前面有個行動遲緩的老太太,崩不崩潰?
在HTTP/1.1中有3個方法可以緩解,但不能解決隊頭阻塞問題。

管道,即可以併發多個請求,無需等待上一個請求返回,即現在的FIFO的長度可以>1。但它仍然期待按發送次序收到響應消息,如果某個先發請求阻塞,則後繼報文即使處理也不能發出,所以仍然存在隊頭阻塞問題。管道僅在理想情況下,提高收發效率。而且目前瀏覽器,服務器對管道支持得不好,可以認爲是廢棄技術。
併發TCP連接,對於同一個域名,瀏覽器允許同時開6-8個TCP連接,因爲每個TCP連接獨立,所以某個TCP中的HTTP請求阻塞,不影響其它TCP連接,所以雖然隊頭阻塞仍然存在,但因爲存在多個獨立的TCP連接,所以隊頭阻塞問題得到一定程度的緩解。
域名分片Domain Sharding,即多個域名映射到一個IP,即可以併發6*域名的連接,進一步緩解了隊頭阻塞的負面影響。
HTTP/2解決了用流和分幀的方式HTTP的隊頭阻塞問題。
HTTP/3解決了用UDP+QUIC解決了TCP隊頭阻塞的問題。
https://blog.csdn.net/weixin_45462681/article/details/113519269

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章