本文整理在,個人github 上。歡迎Star。css
在HTTP創建之初,主要是爲了傳輸超文本標記語言(HTML)文檔。隨着時代的發展,也進行了若干次演進。下圖是各個版本發佈的時間軸。
html
目前爲止,使用最爲普遍的是http1.1,http1.0應該比較少了,最新的是http2。
這篇博文也主要,圍繞着1.0、1.一、2.0三個版本進行介紹。前端
http1.0不會複用tcp連接,每次請求都會打開、斷開一條連接。
若是您看過我前陣子整理的關於TCP的博文,您就會知道,TCP是有延遲響應機制的,每次請求並不會立刻返回。這算是http1.0性能很差的一個緣由吧。git
http/1.1當前普及程度最高的http版本。
到了http/1.1版本,tcp連接能夠持久保持了(也就說,一段時間內,一個tcp連接會等到同一個域名下的全部資源加載完後再斷開。)github
在保持tcp連接的基礎上,引入了http管道的機制,差點實現了多路複用。算法
經過一條tcp連接請求資源,只有在上一個請求完成後,才能發出下一個請求。也就是上圖描述的情形。瀏覽器
客戶端不會等待響應,直接併發N個請求。可是,http/1.x有嚴格的串行返回響應機制。通俗的講就是:請求時,不用等上一個完成;但響應時,必須嚴格按照順序返回。
經過開發者工具,你就能夠觀察到這一點。緩存
基於以上描述,使用「 HTTP 管道」技術時,萬一第一個響應時間很長,那麼後面的響應處理完了也沒法發送,只能被緩存起來,佔用服務器內存,這就是傳說中的「隊首阻塞(head of line blocking)」。
這也是http/1.x下,多數網絡體驗很差的緣由。性能優化
在介紹http/2.0以前,咱們來先看一份Akamai公司提供的一個官方演示。服務器
這裏用了361(19*19)張圖片,分別使用http/1.1,http/2.0兩種版本的協議進行對比。能夠直觀的感覺到,http/2.0比http/1.0快出5倍左右的速度。
考慮到您可能須要分別用開發者工具仔細查看下兩個版本,我已經幫你找好了兩個版本對應的連接。(不客氣)
那http/2.0究竟引入了哪些機制、特性才達到目前的加速效果呢?簡答的說能夠歸納成。
引入了二進制分幀層,就再也不是文本傳輸了,而是數據幀(二進制)。
注意:HTTP本來的語義,方法、動詞、首部都不受影響。僅僅是傳輸期間的數據格式變化了。
http/2規定了10種不一樣的幀。
如上圖,分針層會把 開始行,首部行分割到HEADERS幀,正文實體分割到DATA幀。
TCP 鏈接在客戶端和服務器間創建了一條運輸的通道,能夠雙向通行,當一端要向另外一端發送消息時,會先把這個消息拆分紅幾部分(幀),而後經過發起一個流對這些幀進行發送,最後在另外一端將同一個流的幀從新組合。
這裏涉及瞭如下概念。
流:已創建的鏈接上的雙向字節流
消息:與邏輯消息對應的完整的一系列數據幀
幀:HTTP/2 通訊的最小單位,每一個幀包含幀首部
其中幀對數據進行順序標識,這樣瀏覽器收到數據以後,就能夠按照序列對數據進行合併,而不會出現合併後數據錯亂的狀況。一樣是由於有了序列,服務器就能夠並行的傳輸數據,這就是流所作的事情。
HTTP/2對同一域名下全部請求都是基於流,也就是說同一域名無論訪問多少文件,也只創建一路鏈接。一樣Apache的最大鏈接數爲300,由於有了這個新特性,最大的併發就能夠提高到300,比原來提高了6倍!
在服務器和客戶端各維護一個「首部表」,表中用索引表明首部名,或者首部鍵 - 值對,上一次發送兩端都會記住已發送過哪些首部,下一次發送只須要傳輸差別的數據,相同的數據直接用索引表示便可。
首部壓縮,能夠解決http頭臃腫的問題。
服務器能夠對一個客戶端請求發送多個響應。也就是說,除了對最初請求的響應外,服務器還能夠額外向客戶端推送資源。
這裏就涉及到了另外一個幀類型:PUSH_PROMISE幀。
舉個栗子,當客戶端請求index.html時,服務器會同時推送style.css,index.js對應的PUSH_PROMISE幀。客戶端能夠直接緩存起來。
我的以爲前端的性能優化,應該主要從兩個方面。加載速度和流暢運行。
原引,在網上看到的一段話:
網頁不只應該被快速加載,同時還應該流暢運行,好比快速響應的交互,如絲般順滑的動畫等。
固然,今天的主題是討論網路協議,那咱們只談加載速度。
基於http1.x的相關特性,可愛的前端們提出了不少頗具成效的優化方案。(精靈圖,多域名加載等等)其中,比較著名的雅虎軍規,不少人應道都知道,這裏有一張整理好的圖。
在http/2的基礎上,不少http/1.x要優化的問題,都不存在了。問題都不存在了,問題的優化方案也就不存在了。
這裏插一句,我始終堅信的一個觀點是:沒有任何優化手段是不須要付出代價的。是藥三分毒,無非是取捨罷了。
在http/1.x時代,http並無最大程度上利用好tcp連接。雖然http/1.1裏有了http管道,但其也帶來了隊首阻塞等問題,同時也要受隊列大小的限制。因此咱們要經過合併文件的方式減小http連接數量。
不錯,減小http請求數量的確能起到優化的做用,但與此同時,也有不少弊端:
以上,就是」合併css方案"、「合併js方案」、「精靈圖方案」的優點與弊端。
在http/1.x基礎上,分域名有兩個好處。
在http/2上,對於這些問題
若是頁面須要多種數據,咱們會盡可能將數據彙總到一個接口,以減小http請求數量。
這種作法,幾乎違背了各類程序設計規範,好比「單一職責原則」等等,接口很難複用,維護成本高。
這種方案在http/2下,明顯弊端>優點了。
插一句《RFC7540》是官方對http2.0規格的描述,比較權威。