鍍金池/ 教程/ Linux/ HTTP 的現(xiàn)狀
后http2時代
升級HTTP
擴展
擴展閱讀
致謝
http2 的世界
curl中的http2
Chromium里的http2
背景
Firefox里的http2
HTTP 的現(xiàn)狀
http2 協(xié)議
http2 的基本概念
那些年,克服延遲之道

HTTP 的現(xiàn)狀

互聯(lián)網(wǎng)上幾乎所有內(nèi)容都采用HTTP 1.1作為通信協(xié)議。人們在該協(xié)議上投入了大量精力,基于它的基礎(chǔ)架構(gòu)也因此日臻完善。正因如此,在HTTP協(xié)議之上構(gòu)建新的方案會比從底層建立新的協(xié)議容易得多。

2.1. HTTP 1.1過于龐大

HTTP剛誕生的時候只被當(dāng)作是一個相對簡單直觀的協(xié)議,但時間證明這種初始設(shè)計并不如意。定義HTTP 1.0規(guī)范的RFC 1945共有60頁,發(fā)布于1996年。僅僅3年之后,定義HTTP 1.1規(guī)范的RFC 2616卻一下增長到了176頁。然而,當(dāng)我們在IETF在進行該規(guī)范更新工作時,它被拆分成了總頁數(shù)更多的六個文檔(這就是RFC 7230及其文件族的誕生)。不管怎么樣,HTTP 1.1包含了太多細(xì)節(jié)和可選的部分,這讓它變得過于龐大。

2.2. 過多的可選項

HTTP 1.1不僅包含了非常多的細(xì)枝末節(jié),還為將來的擴展預(yù)留的很多選項。這種事無巨細(xì)的風(fēng)格導(dǎo)致在現(xiàn)在的軟件生態(tài)中,幾乎沒有任何實現(xiàn)真正實現(xiàn)了協(xié)議中提及的所有細(xì)節(jié),甚至要弄清楚“所有細(xì)節(jié)”到底包括哪些細(xì)節(jié)都非常困難。正因為如此,很多最初不常用的功能在后來的實現(xiàn)中很少會被支持,而有些最初實現(xiàn)了的功能,卻又很少被使用。

隨著時間推移,這些當(dāng)初看似被邊緣化的功能逐漸被用上,客戶端和服務(wù)器的互用性(interoperability)問題就被暴露了出來。HTTP管線化(HTTP Pipelining)就是一個非常好的例子。

2.3. 未能被充分利用的TCP

HTTP 1.1很難榨干TCP協(xié)議所能提供的所有性能。HTTP客戶端和瀏覽器必須要另辟蹊徑的去找到新的解決方案來降低頁面載入時間。

與此同時,人們也嘗試去用新的協(xié)議來替代TCP,但結(jié)果證明這也非常困難。無奈之下,我們只能嘗試同時改進TCP協(xié)議本身和基于TCP的上層協(xié)議。

簡言之,我們也能通過更好的利用TCP來減少傳輸過程中的暫停,并充分挖掘利用那些本可以用于發(fā)送/接受更多數(shù)據(jù)的時間。下面幾段將會著重討論這些問題。

2.4. 傳輸大小和資源數(shù)量

如果仔細(xì)觀察打開那些最流行的網(wǎng)站首頁所需要下載的資源的話,會發(fā)現(xiàn)一個非常明顯的趨勢。 近年來加載網(wǎng)站首頁需要的下載的數(shù)據(jù)量在逐漸增加,并已經(jīng)超過了1.9MB。但在這里我們更需要關(guān)注的是:顯示每個頁面所需下載的平均資源數(shù)也超過了100個。

正如下圖所示,這種趨勢已經(jīng)持續(xù)了很長一段時間,并卻沒有減緩的跡象。該圖表中綠色直線展示了傳輸數(shù)據(jù)大小的增長,紅色直線展示了平均請求資源數(shù)量的增長。

http://wiki.jikexueyuan.com/project/http-2-explained/images/trend.png" alt="" />

2.5 惱人的延遲

HTTP 1.1對網(wǎng)絡(luò)延遲非常敏感。部分原因是HTTP Pipelining還有很多問題,所以對大部分用戶來說是默認(rèn)關(guān)閉的。

http://wiki.jikexueyuan.com/project/http-2-explained/images/rtt.png" alt="" />

雖然近幾年來網(wǎng)絡(luò)帶寬增長非???,但是與此相對的是,我們并沒有看到網(wǎng)絡(luò)延遲有對應(yīng)程度的降低。在高延遲的網(wǎng)絡(luò)上(比如移動設(shè)備),即使擁有高連接速率,也很難獲得優(yōu)質(zhì)快速的網(wǎng)絡(luò)體驗。

另外一個需要低延遲的場景是某些視頻服務(wù),如視頻會議、游戲和一些類似無法預(yù)生成待發(fā)送數(shù)據(jù)流的服務(wù)。

2.6 線頭阻塞(Head of line blocking)

HTTP Pipelining是這樣一種技術(shù):在等待上一個請求響應(yīng)的同時,發(fā)送下一個請求。(譯者注:作者這個解釋并不完全正確,HTTP Pipelining其實是把多個HTTP請求放到一個TCP連接中一一發(fā)送,而在發(fā)送過程中不需要等待服務(wù)器對前一個請求的響應(yīng);只不過,客戶端還是要按照發(fā)送請求的順序來接收響應(yīng)。)但就像在超市收銀臺或者銀行柜臺排隊時一樣,你并不知道前面的顧客是干脆利索的還是會跟收銀員/柜員磨蹭到世界末日(譯者注:不管怎么說,服務(wù)器(即收銀員/柜員)是要按照順序處理請求的,如果前一個請求非常耗時(顧客磨蹭),那么后續(xù)請求都會受到影響),這就是所謂的線頭阻塞(Head of line blocking)。

http://wiki.jikexueyuan.com/project/http-2-explained/images/holb.png" alt="" />

當(dāng)然,你可以在選擇隊伍時候就做好功課,去排一個你認(rèn)為最快的隊伍,或者甚至另起一個新的隊伍(譯者注:即新建一個TCP連接)。但不管怎么樣,你總歸得先選擇一個隊伍,而且一旦選定之后,就不能更換隊伍。

但是,另起新隊伍會導(dǎo)致資源耗費和性能損失(譯者注:新建 TCP 連接的開銷非常大)。這種另起新隊伍的方式只在新隊伍數(shù)量很少的情況下有作用,因此它并不具備可擴展性。(譯者注:這段話意思是說,靠大量新建連接是不能有效解決延遲問題的,即HTTP Pipelining并不能徹底解決Head of line blocking問題。)所以針對此問題并沒有完美的解決方案。

即使在2015年的今天,大部分桌面瀏覽器也默認(rèn)關(guān)閉了HTTP pipelining功能。

關(guān)于這個問題的更多細(xì)節(jié),可以參閱Firefox的 bugzilla #264354。