HTTP 2 的新特性你 get 了嗎?
導語
HTTP/2 的主要設計思想應該都是源自 Google的 SPDY 協議,是互聯網工程任務組 ( IETF ) 對谷歌提出的 SPDY 協議進行標準化才有了現在的 HTTP/2 。下面我們直奔主題分析 HTTP/2 的新特性,並且與 HTTP/1.x作對比。
一、多路復用的單一長連接
1.單一長連接
在HTTP/2中,客戶端向某個域名的伺服器請求頁面的過程中,只會創建一條TCP連接,即使這頁面可能包含上百個資源。而之前的HTTP/1.x一般會創建6-8條TCP連接來請求這100多個資源。單一的連接應該是HTTP2的主要優勢,單一的連接能減少TCP握手帶來的時延(如果是建立在SSL/TLS上面,HTTP2能減少很多不必要的SSL握手,大家都知道SSL握手很慢吧)。
另外我們知道,TCP協議有個滑動窗口,有慢啟動這回事,就是說每次建立新連接後,數據先是慢慢地傳,然後滑動窗口慢慢變大,才能較高速度地傳,這下倒好,這條連接的滑動窗口剛剛變大,http1.x就創個新連接傳數據(這就好比人家HTTP2一直在高速上一直開著,你HTTP1.x是一輛公交車走走停停)。由於這種原因,讓原本就具有突發性和短時性的 HTTP 連接變的十分低效。
所以咯,HTTP2中用一條單一的長連接,避免了創建多個TCP連接帶來的網路開銷,提高了吞吐量。
2.多路復用
明明是一條連接,怎麼又是多路復用呢?後台開發的童鞋應該對多路復用很熟悉,例如用select,poll,epoll來管理一堆的fd,在這裡,HTTP2雖然只有一條TCP連接,但是在邏輯上分成了很多stream。這個特性又很關鍵吶。先看下面這個網上借用的圖 。
圖片來源:HTTP/2.0 相比1.0有哪些重大改進?
以前的http1.x怎麼乾的?在一條TCP連接上,多個請求只能串列執行!你說咱們現在的網路帶寬這麼大,這不浪費嗎?http2就不一樣了,不管多少請求,只要有,就往連接裡面扔好了,這能明顯降低一個頁面載入的時間。
HTTP2多路復用怎麼做到的?又來打個比方,你看高速公路,雖然路只有一條,但是收費的那個門是不是有很多個?
HTTP2把要傳輸的信息分割成一個個二進位幀,首部信息會被封裝到HEADER Frame,相應的request body就放到DATA Frame,一個幀你可以看成路上的一輛車,只要給這些車編號,讓1號車都走1號門出,2號車都走2號門出,就把不同的http請求或者響應區分開來了。但是,這裡要求同一個請求或者響應的幀必須是有有序的,要保證FIFO的,但是不同的請求或者響應幀可以互相穿插。這就是HTTP2的多路復用,是不是充分利用了網路帶寬,是不是提高了並發度?
更進一步,http2還能對這些流(車道)指定優先順序,優先順序能動態的被改變,例如把CSS和JavaScript文件設置得比圖片的優先順序要高,這樣代碼文件能更快的下載下來並得到執行。
現在回過頭來看下,請求一個包含幾十個或者幾百個資源的頁面,HTTP1.x和HTTP2在過程上面的區別,如下圖所示:
我想英文不捉雞的同學應該都能看懂,這裡http1.x建了6到8個tcp連接後,一個個請求串列地用這八個連接執行,而http2能一次把所有請求都發出去,還是壓縮過的,高下立判。
二、頭部壓縮和二進位格式
http1.x一直都是plain text,對此我只能想到一個優點,便於閱讀和debug。但是,現在很多都走https,SSL也把plain text變成了二進位,那這個優點也沒了。
於是HTTP2搞了個HPACK壓縮來壓縮頭部,減少報文大小(調試這樣的協議將需要curl這樣的工具,要進一步地分析網路數據流需要類似Wireshark的http2解析器)。HPACK把報文中常見的欄位名和值變成一個索引值index,也就是維護了一張靜態索引表,例如把 method: GET對應成索引表中index為2的一個值,但是頭部還有一些不確定的東西,比如user-agent對應的瀏覽器名字啊。
所以它也維護了一個動態的索引表,靜態表索引值為2-61,這時候數據傳輸過程中發現一個user-agent Mozilla/5.0,那就把這個追加到動態索引表值為62的地方,這次開始就用62代替這個user-agent Mozilla/5.0,所以這個動態索引表是在數據傳輸過程中逐步建立的,靜態索引表寫死的。
此外,對於資源路徑這種完全不確定的東西,HPACK就採用Huffman編碼來壓縮,這樣三管齊下,頭部內容能大幅減少。可以看看下面的HPACK示意圖:
頭部為什麼需要壓縮?
因為一些重複東西在每個http請求裡面都有,例如method: GET。當一個客戶端從同一伺服器請求一些資源(例如頁面的圖片)的時候,這些請求看起來幾乎是一致的。而這些大量一致的東西正好值得被壓縮。
另外,HTTP 1.1請求的大小變得越來越大,有時甚至會大於TCP窗口的初始大小,這會嚴重拖累發送請求的速度。因為它們需要等待帶著ACK的響應回來以後,才能繼續被發送。尤其是當http請求內容超過TCP報文最大報文大小時,會被分成幾個TCP報文,這時候如果壓縮,能減少了tcp報文個數,就能減少幾個RTT時間了。
反過來,頭部壓縮也帶來了CPU消耗,而且如果剛好頭部能被裝到一個TCP報文裡面,壓縮也沒什麼卵用。而且大部分響應報文的body一般比header大很多,這時候好像壓縮頭部也是多此一舉。
三、服務端推送Server Push
這個功能通常被稱作「緩存推送」。主要的思想是:當一個客戶端請求資源X,而伺服器知道它很可能也需要資源Z的情況下,伺服器可以在客戶端發送請求前,主動將資源Z推送給客戶端。
這個功能幫助客戶端將Z放進緩存以備將來之需。伺服器推送需要客戶端顯式的允許伺服器提供該功能。但即使如此,客戶端依然能自主選擇是否需要中斷該推送的流。如果不需要的話,客戶端可以通過發送一個RST_STREAM幀來中止。
以上就是HTTP最主要的幾個新特性啦(當然還有很多新特性,這裡不詳談啦)。最後安利一下HTTP2 + SSL吧,貌似目前瀏覽器只有在伺服器支持http2並且使用了SSL的時候才會使用http2協議。總結一下為什麼HTTP2能去掉SSL在HTTP1.x上的開銷?
1.單一的長連接,減少了SSL握手的開銷
2.頭部被壓縮,減少了數據傳輸量
3.多路復用能大幅提高傳輸效率,不用等待上一個請求的響應
4.不用像http1.x那樣把多個文件或者資源弄成一個文件或者資源(http1.x常見的優化手段),這時候,緩存就能更容易命中啊(http1.x裡面你揉成一團的東西怎麼命中緩存?)
哇。。寫文章真的累。但是有時間我還會再寫個nginx如何部署http2,以及做些實驗測試http2的性能。
相關推薦:
【乾貨合輯】你有什麼獨家資料庫優化技巧?
HTTPS轉發配置入門指南
HTTP/2探索第一篇——概念推薦閱讀:
※如何運用雲模型改進模糊控制?以及雲模型在國內的發展現狀?
※一切計算都是調度問題
※群雄逐鹿 誰會成為雲計算行業第一股?
※2018年或成為雲計算轉折之年:IaaS整合 PaaS崛起 SaaS蓄勢
※王東臨:創新從未停止 IT基礎架構革命蘊含新機會