天天看點

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

雖然http/2标準在2015年5月就以rfc 7540正式發表了,并且多數浏覽器在2015年底就支援了。

但是,真正被廣泛使用起來要到2018年左右,但是也是在2018年,11月ietf給出了官方準許,認可http-over-quic成為http/3。

2018年的時候,那時候http/2還是個新技術,剛剛開始有軟體支援,短短兩年過去了,現在http/3已經悄然而至了。

根據w3techs的資料,截至2019年6月,全球也僅有36.5%的網站支援了http/2。是以,可能很多網站還沒開始支援http/2,http/3就已經來了。

是以,對于很多網站來說,或許直接更新http/3是一個更加正确的選擇。

我預設大家對http/2有了一定的基本了解。

我們知道,http/2的誕生,主要是為了解決http/1.1中的效率問題,http/2中最核心的技術就是多路複用技術,即允許同時通過單一的http/2.0連接配接發起多重的請求-響應消息。

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

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

從http/1.0誕生,一直到http/2,在這24年裡,http協定已經做過了三次更新,但是有一個關鍵的技術點是不變的,那就是這所有的http協定,都是基于tcp協定實作的。

流水的http,鐵打的tcp。這是因為相對于udp協定,tcp協定更加可靠。

雖然在http/1.1的基礎上推出http/2大大的提升了效率,但是還是有很多人認為這隻是個"臨時方案",這也是為什麼剛剛推出沒多久,業内就開始大力投入http/3的研發與推廣了。

而這背後的深層次原因也正是因為他還是基于tcp協定實作的。tcp協定雖然更加可靠,但是還是存在着一定的問題,接下來具體分析下。

隊頭阻塞翻譯自英文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-2做錯了什麼?剛剛輝煌2年就要被棄用了!?

引入了持久連接配接之後,在性能方面,http協定有了明顯的提升。

另外,http/1.1允許在持久連接配接上使用請求管道,是相對于持久連接配接的又一性能優化。

所謂請求管道,就是在http響應到達之前,可以将多條請求放入隊列,當第一條http請求通過網絡流向伺服器時,第二條和第三條請求也可以開始發送了。在高時延網絡條件下,這樣做可以降低網絡的環回時間,提高性能。

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

但是,對于管道連接配接還是有一定的限制和要求的,其中一個比較關鍵的就是服務端必須按照與請求相同的順序回送http響應。

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

但是http隊頭阻塞的問題在http/2中得到了有效的解決。http/2廢棄了管道化的方式,而是創新性的引入了幀、消息和資料流等概念。用戶端和伺服器可以把 http 消息分解為互不依賴的幀,然後亂序發送,最後再在另一端把它們重新組合起來。

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

因為沒有順序了,是以就不需要阻塞了,就有效的解決了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在傳輸過程中可以保證接收方收到的資料是完整,有序,無差錯的。

但是,問題是三次握手是需要消耗時間的,這裡插播一個關于網絡延遲的概念。

網絡延遲又稱為 rtt(round trip time)。他是指一個請求從用戶端浏覽器發送一個請求資料包到伺服器,再從伺服器得到響應資料包的這段時間。rtt 是反映網絡性能的一個重要名額。

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

我們知道,tcp三次握手的過程用戶端和伺服器之間需要互動三次,那麼也就是說需要消耗1.5 rtt。

另外,如果使用的是安全的https協定,就還需要使用tls協定進行安全資料傳輸,這個過程又要消耗一個rtt(tls不同版本的握手機制不同,這裡按照最小的消耗來算)

那麼也就是說,一個純http/2的連接配接,需要消耗1.5個rtt,如果是一個https連接配接,就需要消耗3-4個rtt。

而具體消耗的時長根據伺服器和用戶端之間的距離則不盡相同,如果比較近的話,消耗在100ms以内,對于用來說可能沒什麼感覺,但是如果一個rtt的耗時達到300-400

ms,那麼,一次連接配接建立過程總耗時可能要達到一秒鐘左右,這時候,使用者就會明顯的感覺到網頁加載很慢。

基于上面我們提到的這些問題,很多人提出來說:既然tcp存在這些問題,并且我們也知道這些問題的存在,甚至解決方案也不難想到,為什麼不能對協定本身做一次更新,解決這些問題呢?