HTTP/2作錯了什麼?剛剛輝煌2年就要被棄用了!?

GitHub 19k Star 的Java工程師成神之路,不來了解一下嗎!git

GitHub 19k Star 的Java工程師成神之路,真的不來了解一下嗎!github

GitHub 19k Star 的Java工程師成神之路,真的真的不來了解一下嗎!瀏覽器

最近一段時間以來,關於HTTP/3的新聞有不少,愈來愈多的國際大公司已經開始使用HTTP/3了。安全

因此,HTTP/3已是箭在弦上了,全面使用只是個時間問題,那麼,做爲一線開發者,咱們也是時候瞭解下到底什麼是HTTP/3,爲何須要HTTP/3了。性能優化

因而,我準備開始寫這篇文章,可是要想把HTTP/3的事情說清楚,必定繞不過的問題就是HTTP/2,因此寫着寫着,篇幅愈來愈多,因而我就把他們分紅了上下兩篇。服務器

這一篇咱們主要來回顧下HTTP/2,而後再來重點看一下HTTP/2存在哪些問題,爲何要被棄用。網絡

HTTP/2 輝煌不在?

雖然HTTP/2標準在2015年5月就以RFC 7540正式發表了,而且多數瀏覽器在2015年末就支持了。tcp

可是,真正被普遍使用起來要到2018年左右,可是也是在2018年,11月IETF給出了官方批准,承認HTTP-over-QUIC成爲HTTP/3。post

2018年的時候,我寫過一篇文章介紹《HTTP/2究竟是什麼?》,那時候HTTP/2仍是個新技術,剛剛開始有軟件支持,短短兩年過去了,如今HTTP/3已經悄然而至了。性能

根據W3Techs的數據,截至2019年6月,全球也僅有36.5%的網站支持了HTTP/2。因此,可能不少網站還沒開始支持HTTP/2,HTTP/3就已經來了。

因此,對於不少網站來講,或許直接升級HTTP/3是一個更加正確的選擇。

回顧 HTTP/2

在閱讀本文以前,強烈建議你們先閱讀下《HTTP/2究竟是什麼?》這篇文章,這裏面介紹了HTTP的歷史,介紹了各個版本的HTTP協議的誕生的背景。

當你讀到這裏的時候,我默認你們對HTTP/2有了必定的基本瞭解。

咱們知道,HTTP/2的誕生,主要是爲了解決HTTP/1.1中的效率問題,HTTP/2中最核心的技術就是多路複用技術,即容許同時經過單一的HTTP/2.0鏈接發起多重的請求-響應消息。

同時還實現了二進制分幀、header壓縮、服務端推送等技術。

從HTTP/1.0誕生,一直到HTTP/2,在這24年裏,HTTP協議已經作過了三次升級,可是有一個關鍵的技術點是不變的,那就是這全部的HTTP協議,都是基於TCP協議實現的。

流水的HTTP,鐵打的TCP。這是由於相對於UDP協議,TCP協議更加可靠。

雖然在HTTP/1.1的基礎上推出HTTP/2大大的提高了效率,可是仍是有不少人認爲這只是個"臨時方案",這也是爲何剛剛推出沒多久,業內就開始大力投入HTTP/3的研發與推廣了。

而這背後的深層次緣由也正是由於他仍是基於TCP協議實現的。TCP協議雖然更加可靠,可是仍是存在着必定的問題,接下來具體分析下。

HTTP/2 問題

隊頭阻塞

隊頭阻塞翻譯自英文head-of-line blocking,這個詞並不新鮮,由於早在HTTP/1.1時代,就一直存在着隊頭阻塞的問題。

可是不少人在一些資料中會看到有論點說HTTP/2解決了隊頭阻塞的問題。可是這句話只對了一半。

只能說HTTP/2解決了HTTP的隊頭阻塞問題,可是並無解決TCP隊頭阻塞問題!

若是你們對於HTTP的歷史有必定的瞭解的話,就會知道。HTTP/1.1相比較於HTTP/1.0來講,最主要的改進就是引入了持久鏈接(keep-alive)。

所謂的持久鏈接就是:在一個TCP鏈接上能夠傳送多個HTTP請求和響應,減小了創建和關閉鏈接的消耗和延遲。

引入了持久鏈接以後,在性能方面,HTTP協議有了明顯的提高。

另外,HTTP/1.1容許在持久鏈接上使用請求管道,是相對於持久鏈接的又一性能優化。

所謂請求管道,就是在HTTP響應到達以前,能夠將多條請求放入隊列,當第一條HTTP請求經過網絡流向服務器時,第二條和第三條請求也能夠開始發送了。在高時延網絡條件下,這樣作能夠下降網絡的環回時間,提升性能。

可是,對於管道鏈接仍是有必定的限制和要求的,其中一個比較關鍵的就是服務端必須按照與請求相同的順序回送HTTP響應。

這也就意味着,若是一個響應返回發生了延遲,那麼其後續的響應都會被延遲,直到隊頭的響應送達。這就是所謂的HTTP隊頭阻塞

可是HTTP隊頭阻塞的問題在HTTP/2中獲得了有效的解決。HTTP/2廢棄了管道化的方式,而是創新性的引入了幀、消息和數據流等概念。客戶端和服務器能夠把 HTTP 消息分解爲互不依賴的幀,而後亂序發送,最後再在另外一端把它們從新組合起來。

由於沒有順序了,因此就不須要阻塞了,就有效的解決了HTTP對隊頭阻塞的問題。

可是,HTTP/2仍然會存在TCP隊頭阻塞的問題,那是由於HTTP/2其實仍是依賴TCP協議實現的。

TCP傳輸過程當中會把數據拆分爲一個個按照順序排列的數據包,這些數據包經過網絡傳輸到了接收端,接收端再按照順序將這些數據包組合成原始數據,這樣就完成了數據傳輸。

可是若是其中的某一個數據包沒有按照順序到達,接收端會一直保持鏈接等待數據包返回,這時候就會阻塞後續請求。這就發生了TCP隊頭阻塞

HTTP/1.1的管道化持久鏈接也是使得同一個TCP連接能夠被多個HTTP使用,可是HTTP/1.1中規定一個域名能夠有6個TCP鏈接。而HTTP/2中,同一個域名只是用一個TCP鏈接。

因此,在HTTP/2中,TCP隊頭阻塞形成的影響會更大,由於HTTP/2的多路複用技術使得多個請求實際上是基於同一個TCP鏈接的,那若是某一個請求形成了TCP隊頭阻塞,那麼多個請求都會受到影響。

TCP握手時長

一提到TCP協議,你們最早想到的必定是他的三次握手與四次關閉的特性。

由於TCP是一種可靠通訊協議,而這種可靠就是靠三次握手實現的,經過三次握手,TCP在傳輸過程當中能夠保證接收方收到的數據是完整,有序,無差錯的。

可是,問題是三次握手是須要消耗時間的,這裏插播一個關於網絡延遲的概念。

網絡延遲又稱爲 RTT(Round Trip Time)。他是指一個請求從客戶端瀏覽器發送一個請求數據包到服務器,再從服務器獲得響應數據包的這段時間。RTT 是反映網絡性能的一個重要指標。

咱們知道,TCP三次握手的過程客戶端和服務器之間須要交互三次,那麼也就是說須要消耗1.5 RTT。

另外,若是使用的是安全的HTTPS協議,就還須要使用TLS協議進行安全數據傳輸,這個過程又要消耗一個RTT(TLS不一樣版本的握手機制不一樣,這裏按照最小的消耗來算)

那麼也就是說,一個純HTTP/2的鏈接,須要消耗1.5個RTT,若是是一個HTTPS鏈接,就須要消耗3-4個RTT。

而具體消耗的時長根據服務器和客戶端之間的距離則不盡相同,若是比較近的話,消耗在100ms之內,對於用來講可能沒什麼感知,可是若是一個RTT的耗時達到300-400ms,那麼,一次鏈接創建過程總耗時可能要達到一秒鐘左右,這時候,用戶就會明顯的感知到網頁加載很慢。

升級TCP是否可行?

基於上面咱們提到的這些問題,不少人提出來講:既然TCP存在這些問題,而且咱們也知道這些問題的存在,甚至解決方案也不難想到,爲何不能對協議自己作一次升級,解決這些問題呢?

其實,這就涉及到一個"協議僵化"的問題。

這樣講,咱們在互聯網上瀏覽數據的時候,數據的傳輸過程實際上是極其複雜的。

咱們知道的,想要在家裏使用網絡有幾個前提,首先咱們要經過運行商開通網絡,而且須要使用路由器,而路由器就是網絡傳輸過程當中的一箇中間設備。

中間設備是指插入在數據終端和信號轉換設備之間,完成調製前或解調後某些附加功能的輔助設備。例如集線器、交換機和無線接入點、路由器、安全解調器、通訊服務器等都是中間設備。

在咱們看不到的地方,這種中間設備還有不少不少,一個網絡須要通過無數箇中間設備的轉發才能到達終端用戶。

若是TCP協議須要升級,那麼意味着須要這些中間設備都能支持新的特性,咱們知道路由器咱們能夠從新換一個,可是其餘的那些中間設備呢?尤爲是那些比較大型的設備呢?更換起來的成本是巨大的。

並且,除了中間設備以外,操做系統也是一個重要的因素,由於TCP協議須要經過操做系統內核來實現,而操做系統的更新也是很是滯後的。

因此,這種問題就被稱之爲"中間設備僵化",也是致使"協議僵化"的重要緣由。這也是限制着TCP協議更新的一個重要緣由。

因此,近些年來,由IETF標準化的許多TCP新特性都因缺少普遍支持而沒有獲得普遍的部署或使用!

放棄TCP?

上面提到的這些問題的根本緣由都是由於HTTP/2是基於TPC實現致使的,而TCP協議自身的升級又是很難實現的。

那麼,剩下的解決辦法就只有一條路,那就是放棄TCP協議。

放棄TCP的話,就又有兩個新的選擇,是使用其餘已有的協議,仍是從新創造一個協議呢?

看到這裏,聰明的讀者必定也想到了,創造新的協議同樣會受到中間設備僵化的影響。近些年來,由於在互聯網上部署遭遇很大的困難,創造新型傳輸層協議的努力基本上都失敗了!

因此,想要升級新的HTTP協議,那麼就只剩一條路能夠走了,那就是基於已有的協議作一些改造和支持,UDP就是一個絕佳的選擇了。

總結

由於HTTP/2底層是採用TCP協議實現的,雖然解決了HTTP隊頭阻塞的問題,可是對於TCP隊頭阻塞的問題卻無能爲力。

TCP傳輸過程當中會把數據拆分爲一個個按照順序排列的數據包,這些數據包經過網絡傳輸到了接收端,接收端再按照順序將這些數據包組合成原始數據,這樣就完成了數據傳輸。

可是若是其中的某一個數據包沒有按照順序到達,接收端會一直保持鏈接等待數據包返回,這時候就會阻塞後續請求。這就發生了TCP隊頭阻塞

另外,TCP這種可靠傳輸是靠三次握手實現的,TCP三次握手的過程客戶端和服務器之間須要交互三次,那麼也就是說須要消耗1.5 RTT。若是是HTTPS那麼消耗的RTT就更多。

而由於不少中間設備比較陳舊,更新換代成本巨大,這就致使TCP協議升級或者採用新的協議基本沒法實現。

因此,HTTP/3選擇了一種新的技術方案,那就是基於UDP作改造,這種技術叫作QUIC。

那麼問題來了,HTTP/3是如何使用的UDP呢?作了哪些改造?如何保證鏈接的可靠性?UDP協議就沒有僵化的問題了嗎?

這些問題咱們在下一篇中深刻分析。敬請期待!

參考資料:

https://http3-explained.haxx.se/

https://baike.baidu.com/item/中間設備/3688874

https://time.geekbang.org/column/article/150159

https://juejin.cn/post/6844903853985366023

https://time.geekbang.org/column/article/279164

相關文章
相關標籤/搜索