最近在做一個內部的服務對接,使用了Google的gRPC框架,gRPC是基於HTTP/2和protocol buffers實現的,所以額外去了解了一下HTTP/2,找到這這邊文章。這篇文章雖然是寫於2015年時間比較久遠,但是對於HTTP/2的介紹很全面,於是花了些時間翻譯了一下。
HTTP/2 誕生的意義
國際互聯網工程任務組(The Internet Engineering Task Force,簡稱 IETF)在2015年2月通過了HTTP/2標准,自從1999年HTTP/1.1被列為標准后,HTTP/2是對HTTP(Hypertext Transfer Protocol)第一個大版本的更新。HTTP/2可以與HTTP/1.1高度兼容,但是卻有更低的延遲。總而言之,HTTP/2就是為更快速的網站而生。
起源於SPDY
自從2009年底Google開發一個實驗性質的協議SPDY(pronounced speedy),SPDY是Google的一個標志並不是一個縮寫。HTTP/2期初是就以SPDY的實驗特性為基礎的。實際上,很多SPDY的核心開發者都參與了HTTP/2的研發工作。直到2015年2月,Google宣布SPDY將被廢棄,並主推HTTP/2,並在2016年完全替代。
HTTP/1.1
從1999年起,HTTP/1.1就已經開始為我們提供服務,HTTP/1.1的設計就是為眾多的電腦終端使用互聯網。不得不說,HTTP等一個革新實在是太久了。為了輔助理解HTTP/1的工作原理,我這里列舉了一些圖片。圖片中的需要展示的是一個客戶端(可能是個瀏覽器),如何與一個圖片右側服務器建立HTTP/1連接的。

② 瀏覽器客戶端發送一個http get請求去獲取一個網站的index.html頁面。
③ 表示服務端返回請求的資源
④-⑦ 在這個簡單的例子中,瀏覽器客戶端不斷地發送請求和獲取response,加載樣式和腳本文件來渲染和處理HTML文檔。
⑧ 最后HTTP/1連接關閉。
隊頭阻塞(Head-of-Line Blocking)
正如你所見的,瀏覽器客戶端浪費了大量的時間等待資源返回。主要是因為HTTP/1無法通過單一的連接來進行並發的請求,所以瀏覽器通常情況下采用打開多個連接的方式來加速獲取資源的進程。
奢侈的連接
然而使用打開多個連接來輔助加速的方式,從計算機網絡的角度來看,每打開一個連接都是非常奢侈的。由於建立連接的花銷非常大,目前的瀏覽器都會對HTTP/1.1的最大連接數進行限制,一般為6-8個。但是很多網站,會去請求80個乃至更多的資源,因此,這個限制也會導致很大的性能瓶頸。
HTTP管線化(HTTP pipelining)
HTTP/1.1嘗試通過HTTP管線化技術來解決這一性能瓶頸。不幸的是,一個體積很大的或慢response仍然會阻塞后面所有的請求。HTTP管線化技術並不是實施起來很困難,而是現階段不可能實現。由於服務端中間件和服務器都不能很好的支持HTTP管線化,所以也沒有任何一個瀏覽器去支持這一技術。
HTTP/2多路復用
多路復用允許多個request-response消息通過一個HTTP/2連接進行傳輸,同時為了展示HTTP/2有多高效,我准備了一個圖片和HTTP/1進行對比。還是相同的配方,我們來看看在HTTP/2的支持下頁面有多快開始進行渲染。
設想一下,如果對比的是一個更常見的一個場景80個請求需要請求的時候,通過HTTP/1.1每次建立6-8個連接去處理和HTTP/2通過一個連接就可以獲取所有的請求,結果一目了然。

其他的HTTP/2性能優化點
除了多路復用之外,HTTP/2使用的是二進制傳輸而不是像HTTP/1使用文本。相較於文本協議,二進制解析起來更加的高效,具有更高的壓縮率,且更不容易出錯。
HTTP/2對請求的頭部信息進行了壓縮,這些都是HTTP/1所欠缺的。
服務端推(Server Push)
服務端推是HTTP/2的一個機制,服務端可以主動發送數據而不需要客戶端的請求。舉個例子,如果一個請求獲取你的網站首頁,服務端將會吧首頁連帶着logo和樣式文件等一並返回,因為服務端知道這些文件客戶端將會需要。這種機制的本質相當於,將這些資源與DOM文檔進行內部關聯,除此之外,推送的資源將會在客戶端進行緩存。
服務端推技術的一個缺點是:當客戶端已經緩存了資源就會造成資源浪費,這也是為什么我推薦使用服務端暗示(Server Hints)。
服務端暗示(Server Hints)
服務端暗示技術將會在客戶端請求之前對將會需求的資源進行識別。但是服務器並不會發送完整的資源內容,僅僅是發送URL。客戶端之后如果需要請求這些資源會先去校驗緩存,然后去請求這些資源。服務端暗示技術並不是HTTP/2的新特性,但是就像前面所描述的那樣,這個技術非常值得一提的是,不會有服務端推技術可能會造成資源冗余的缺點。
服務端暗示是使用HTTP Link頭來實現,並且與已經存在的鏈接預取語義上重復。舉個例子,一個HTTP Link頭看起來是這樣的:
Link: <https://example.com/images/large-background.jpg>; rel=prefetch
如果HTML文檔在head標簽中包含鏈接預取屬性的link,那么則不需要服務端進行實現。例子如下
<link rel="prefetch" href="https://example.com/images/large-background.jpg">
要了解更多關於rel="prefetch", 可以查看Mozilla
鏈接預取FAQ。
更新一步了解服務端暗示技術
preload rel屬性通過聲明一個資源和它的fetch屬性來實現。這個規范通過使用額外的處理策略來拓展功能,從而當下一次導航的時候可以更高效的獲取資源。舉個例子:
<!-- fetch and preprocess for next navigation --> <link rel="preload" href="//example.com/next-page.html" as="html" loadpolicy="next"> <!-- fetch and do not preprocess for next navigation --> <link rel="preload" href="//example.com/next-component.html" as="html" loadpolicy="next inert">
"next inert"加載策略在一些瀏覽器實現上等同於rel=prefetch,"next"加載策略在一些瀏覽器實現語義上等同於rel=prerender。
該規范的實現拓展了先前的預取和預渲染功能
了解更多,可以查看Ilya Grigorik編輯,W3C發布的
Resource Hints
HTTP/2安全批評
盡管HTTP/2的主要目的是使網站的速度更快,但是它也因為沒有強制使用加密連接受到了大量的批評。因而領先的瀏覽器廠商因此很久沒有去支持沒有加密的HTTP/2。所以HTTP/2需要使用加密連接的方式來落地這一技術。可以來看我的另一篇文章
HTTPS Everywhere,除非你不認為HTTPS是未來的網站的一個很好的發展方向。
瀏覽器支持情況
HTTP/2正在或即將被所有主流的瀏覽器支持
Chrome 40支持了HTTP/2第14草案,但是默認情況下沒有啟用。HTTP/2第17草案(最終草案)被Chrome Canary 43(預發布開發版)所使用。目前僅僅基於TLS(加密)的HTTP/2才被支持。
想要在Chrome瀏覽器啟用啟用HTTP/2,可以訪問鏈接:
chrome://flags/#enable-spdy4
火狐瀏覽器已經支持了HTTP/2並且從36版本開始默認是開啟的。34版本中火狐瀏覽器開始實驗性質地支持HTTP/2。目前僅僅實施了基於TLS的HTTP/2。
IE11僅僅在 Windows 10 beta版本支持HTTP/2,默認情況下是啟用的,目前也是僅僅支持基於TLS的HTTP/2。
Spartan瀏覽器被期待支持基於TLS的HTTP/2,微軟為Windows 10打造的新瀏覽器。
Safari在Mac OS X Yosemite (10.10)和iOS 8默認支持SPDY。預計在2015年底去全面支持HTTP/2。
Opera默認也是支持SPDY。一旦HTTP/2草案在Chrome瀏覽器中默認支持的時候,Opera也會全面支持。
服務端支持情況
支持HTTP/2
IIS (Internet Information Services) 在Windows 10 beta版本中支持HTTP/2。
OpenLiteSpeed在1.3.8和1.4.5中支持HTTP/2草案17.
支持SPDY, 但是不支持HTTP/2
Apache通過mod_spdy模塊支持老版本的SPDY,但是目前這個模塊已經停止開發了。
LiteSpeed Web Server目前支持SPDY/3.1。
Nginx通過模塊提供實驗性質的而支持SPDY (草案 3.1),並且計划在2015年底開始支持HTTP/2。
沒有打算支持HTTP/2的服務器
lighttpd 在1.x的版本中沒有支持SPDY或者HTTP/2的計划。
其他支持HTTP/2的服務器
其他支持HTTP/2的比較有名的服務器可以在
GitHub HTTP/2 wiki找到。
結語
正如我們的探索,HTTP/2對於Web是一個跨世紀的更新。因此在接下來的幾年里將會被更加廣泛的使用,網站和其他的Web服務想比以前將會變得更快更穩定。特別感謝這些具有前瞻性的瀏覽器開發者,HTTP/2也會提高用戶的隱私和安全性。然而還有很長的一段路要走,我認為HTTP/2是這個互聯網發展邁出的一大步。
如果你對於HTTP/2有任何的問題和想法,我將在我的Twitter進行回復
@BenjaminPatch。
致謝
特別感謝
Ilya Grigorik,一位Google優秀的Web性能工程師,感謝他對於這邊文章提供的支持。Ilya也是《High-Performance Browser Networking》的作者,對於Web開發這來說是很好的學習網絡和瀏覽器性能的資源。