面試官問:你瞭解HTTP2.0嗎?

前言

做爲一隻前端開發🐶,HTTP是咱們知識地圖裏面必不可少的一部分,也是面試必問知識點。HTTP2號稱可讓咱們的應用更快、更簡單、更穩定,它完美解決了1.1版本的諸多問題,本文和你們一塊兒聊聊HTTP2的改進點。css

HTTP發展史

正式講HTTP2以前咱們先講一下HTTP的發展史。 html

  • HTTP/0.9 - 單行協議
    HTTP於1990年問世,那時候HTTP很是簡單:只支持GET方法;沒有首部;只能獲取純文本。
  • HTTP/1.0 - 搭建協議的框架
    1996年,HTTP正式被做爲標準公佈,版本爲HTTP/1.0。1.0版本增長了首部、狀態碼、權限、緩存、長鏈接(默認短鏈接)等規範,能夠說搭建了協議的基本框架。
  • HTTP/1.1 - 進一步完善
    1997年,1.1版本接踵而至。1.1版本的重大改進在於默認長鏈接;強制客戶端提供Host首部;管線化;Cache-Control、ETag等緩存的相關擴展。

目前存在的問題

如今咱們先不聊HTTP2, 看一下HTTP發展到1.1存在有哪些問題:前端

  1. 線頭阻塞:TCP鏈接上只能發送一個請求,前面的請求未完成前,後續的請求都在排隊等待。
  2. 多個TCP鏈接
    雖然HTTP/1.1管線化能夠支持請求併發,可是瀏覽器很難實現,chrome、firefox等都禁用了管線化。因此1.1版本請求併發依賴於多個TCP鏈接,創建TCP鏈接成本很高,還會存在慢啓動的問題。
  3. 頭部冗餘,採用文本格式
    HTTP/1.X版本是採用文本格式,首部未壓縮,並且每個請求都會帶上cookie、user-agent等徹底相同的首部。
  4. 客戶端須要主動請求

HTTP/2.0的時代來了

先來一個demo感覺一下吊炸天的HTTP/2.0,這個demo是加載379張圖片,來對比HTTP/1.1和HTTP/2.0的性能。 HTTP/1.1 與2.0 性能比較node

理論上HTTP/2.0會比HTTP/1.1有一倍多的性能提高,弱網環境下,性能提高會更加明顯。 下面兩張圖是我在設置網絡在fast 3G 和slow 3G的性能對比。web

是否是被HTTP/2.0的速度亮瞎了雙眼?2333,接下來咱們正式開始聊聊2.0。看看2.0 相比與1.1的一些重大改進。

二進制分幀層

HTTP2性能提高的核心就在於二進制分幀層。HTTP2是二進制協議,他採用二進制格式傳輸數據而不是1.x的文本格式。面試

看圖吧!很清晰的表達了HTTP/1.1的響應和2.0的區別。1.1響應是文本格式,而2.0把響應劃分紅了兩個幀,圖中的HEADERS(首部)和DATA(消息負載) 是幀的類型。 瞭解更多幀的類型也就是說一條HTTP響應,劃分紅了兩個幀來傳輸,而且採用二進制來編碼。

這裏咱們來提三個概念。chrome

  • 流(Stream):已創建的TCP鏈接上的雙向字節流,能夠承載一個或多個消息。
  • 消息(Message):一個完整的HTTP請求或響應,由一個或多個幀組成。特定消息的幀在同一個流上發送,這意味着一個HTTP請求或響應只能在一個流上發送。
  • 幀(Frame):通訊的基本單位。
    一個TCP鏈接上能夠有任意數量的流。

多路複用

上面提到HTTP/1.1的線頭阻塞和多個TCP鏈接的問題,HTTP2的多路複用完美解決。HTTP2讓全部的通訊都在一個TCP鏈接上完成,真正實現了請求的併發。咱們來看一下HTTP2具體是怎麼實現的:api

HTTP2創建一個TCP鏈接,一個鏈接上面能夠有任意多個流(stream),消息分割成一個或多個幀在流裏面傳輸。幀傳輸過去之後,再進行重組,造成一個完整的請求或響應。這使得全部的請求或響應都沒法阻塞。 咱們再來回看上面的那個demo:

打開控制檯能夠看到,HTTP/1.1的方式,後面的圖片的加載時間主要耗時在stalled,stalled的意思是從TCP鏈接創建完成,到真正能夠傳輸數據之間的時間差。這就是隊頭阻塞,前面的請求沒有處理,後面的請求都在排隊等待。

這裏例子咱們能很直觀的看到就是多路複用起到的優化做用。由於HTTP2 實現了請求併發,後面的請求不用再等待,加載時長固然少了不少。截一張HTTP2的圖片加載耗時詳情來看看(要看比較靠後的請求): 瀏覽器

咦??什麼狀況?咱們發現後面的不少請求依舊有在排隊哎,只是排隊的時間相對1.1少了不少。一個TCP鏈接能夠有任意數量的流,也就是同時能夠併發任意數量的請求啊,爲啥還會排隊呢?緣由就是請求太多時,瀏覽器或服務器會受不了,這超出了它的處理能力。流控制幫咱們解決了這個問題,流控制會管理數據的傳輸,容許接收者中止或減小發送的數據量,省得接收方不堪重負。因此請求太多時,仍是會存在排隊等待的問題,由於不論是客戶端或服務器端,能同時處理請求或響應都是有限的。

頭部壓縮

頭部壓縮也是HTTP2的一大亮點。在1.X版本中,首部用文本格式傳輸,一般會給每一個傳輸增長500-800字節的開銷。如今打開一個網頁上百個請求已經是常態,而每一個請求帶的一些首部字段都是相同的,例如cookie、user-agent等。HTTP2爲此採用HPACK壓縮格式來壓縮首部。頭部壓縮須要在瀏覽器和服務器端之間:緩存

  • 維護一份相同的靜態字典,包含常見的頭部名稱,以及常見的頭部名稱和值的組合
  • 維護一份相同的動態字典,能夠動態的添加內容
  • 經過靜態Huffman編碼對傳輸的首部字段進行編碼

HTTP2的靜態字典是長這個樣子的(只截取了部分,完整表格在這裏):

因此咱們在傳輸首部字段的時候,例如要傳輸method:GET,那咱們只須要傳輸靜態字典裏面method:GET對應的索引值就能夠了,一個字節搞定。像user-agent、cookie這種靜態字典裏面只有首部名稱而沒有值的首部,第一次傳輸須要user-agent在靜態字典中的索引以及他的值,值會採用靜態Huffman編碼來減少體積。

第一次傳輸過user-agent 以後呢,瀏覽器和服務器端就會把它添加到本身的動態字典中。後續傳輸就能夠傳輸索引了,一個字節搞定。

咱們用WireShark來抓包驗證一下:
HTTP2目前都是HTTPS的請求,WireShark對HTTPS網站抓包解密請參考這裏

  • 首次傳輸user-agent和第二次傳輸user-agent

因爲第一次傳輸的時候,字典裏面並無user-agent的值,這時候user-agent是63字節,第二次傳輸時,他已經在動態字典裏面了,只傳索引,一個字節搞定。

  • HPACK的首部壓縮力度

Header解碼後的長度有471個字節,而HEADERS流只有246個字節。這只是第一個請求,後續的請求壓縮力度會更大,由於前面請求用到的首部(靜態字典中沒有的)會添加到動態字典中,使得後續請求只須要傳輸字典裏面的索引。

服務器端推送

服務器端推送使得服務器能夠預測客戶端須要的資源,主動推送到客戶端。
例如:客戶端請求index.html,服務器端可以額外推送script.js和style.css。 實現原理就是客戶端發出頁面請求時,服務器端可以分析這個頁面所依賴的其餘資源,主動推送到客戶端的緩存,當客戶端收到原始網頁的請求時,它須要的資源已經位於緩存。

針對每個但願發送的資源,服務器會發送一個PUSH_PROMISE幀,客戶端能夠經過發送RST_STREAM幀來拒絕推送(當資源已經位於緩存)。這一步的操做先於父響應(index.html),客戶端了解到服務器端打算推送哪些資源,就不會再爲這些資源建立重複請求。當客戶端收到index.html的響應時,script.js和style.css已經位於緩存。

想要搭一個HTTP2服務器的話推薦node,很簡單。連接

參考文章

結語

簡單講了HTTP2相比1.1版本的重要改進點,感覺了一下h2的強大。還有一些流優先化等特性文中未涉及,感興趣的能夠在參考文章中看看。若有錯誤,懇請指正!

@Author:小夭yao愛吃糖糖糖

相關文章
相關標籤/搜索