最近讀完《HTTP2 基礎教程》,至關因而對 HTTP2 有了個大體的瞭解,本文已加入個人博客,感謝你們支持!css
互聯網剛開始的時候,人們瀏覽網頁只是爲了閱讀文字,隨着時代的不斷髮展,人們對於網站的需求愈來愈高,一個網站不只僅要展現文字,還要展現圖片,視頻,3D 特效等。html
一、Web 頁面引用的內容每一年都在增加,圖片,JS,CSS 愈來愈大,也愈來愈多。git
二、Web 所依賴的資源也變得愈來愈複雜。github
三、大多數 Web 頁面會關聯數十個域名的資源,每個資源都須要經歷一次 DNS,TCP,TLS 等。算法
人們對網站的需求愈來愈多,可是 HTTP 協議卻發展很慢,HTTP1.1 已經存在 20 年了,卻仍是當前社會中使用最普遍的協議。如下幾個缺點也愈來愈被你們所關注:瀏覽器
一、隊頭阻塞,在請求響應中若是出現任何問題,剩下的工做都會被阻塞在那次請求應答以後。緩存
二、低效的 TCP 利用安全
擁塞窗口:在接收方確認數據包以前,發送方能夠發出的 TCP 包的數量。(例如:若是擁塞窗口爲 1,那麼發送方發出 1 個數據包以後,只有接收方確認了那個包,才能發送下一個)。服務器
TCP 中有個概念叫慢啓動,目的是爲了讓新鏈接搞清楚當前的網絡情況,避免給已經擁堵的網絡繼續添亂。(它容許客戶端在收到每一個確認回覆後額外發送 1 個未確認包,這意味着新鏈接在收到 1 個確認回覆後,能夠發送 2 個數據包,在收到 2 個確認回覆後,能夠發 4 個,以此類推,直到達到上限值)cookie
三、臃腫的消息首部
雖然 HTTP1 提供了壓縮請求內容
的機制,可是消息首部卻沒法壓縮,若是算上 cookie,可能每次都會多發送幾千個字節。
四、受限制的優先級設置
HTTP1 沒有優先級一說,要麼發起請求,要麼不發起。
爲了解決 HTTP1 的各類問題,你們也總結一下優化方案,咱們來依次介紹一下吧。
若是想在 HTTP 協議層面作優化,能夠考慮下幾點:
<link rel="dns-prefetch" href="//www.xxx.com" />
<link rel="preconnect" href="//www.xxx.com" />
咱們經常使用緩存來避免沒必要要的請求,但要使用緩存必須遵照着兩個概念:多用戶之間可共享
,可以接受必定程度的舊數據
。
使用 Expires 首部,將資源失效的日期
告訴客戶端,在失效如期以前,客戶端都會直接使用緩存中的資源而不會發起請求
。
使用 Cache-Control 首部,進行更多的定製化緩存:
在請求中包含 HTTP 首部 Last Modified,僅當最新內容在首部中制定的日誌以後被更新過,服務器才返回完整內容,不然返回 304.
在請求實體中包含實體校驗碼 ETag,它惟一標識所請求的資源,服務器會比較當前 ETag 與請求首部中收到 ETag,若是一致,就返回 304.
刪除 html 文檔中的註釋,換行,空格等,減小資源大小。
因爲 JS 在處理時,會阻止其餘任何資源的下載和渲染,可能會帶來沒必要要的延遲。
一張圖片中每每並非只有圖片內容,每每還包含有一些圖片元信息:地理位置信息,時間戳,尺寸,像素等。而這些信息對於頁面並無聲明用,還會增長圖片的大小,建議刪除掉圖片元信息
,只保留真正有用的部分。
另外,頁面中的圖片,儘可能不要使用 CSS 去拉伸或者縮放,須要多大的圖片,就返回多大的圖,避免資源浪費。
上面介紹了 HTTP 的歷史以及現階段使用最普遍的 HTTP1 ,接下來咱們來介紹一下 HTTP2 ,看一看 HTTP2 是怎麼解決 HTTP1 所遺留的問題?
首先,要搭建 HTTP2 服務,必須配套使用 HTTPS 安全策略,才能獲得瀏覽器的支持。HTTP2 其實並無要求必須使用 HTTPS,只是人們正好認識到 HTTPS 的重要性,而 HTTP2 正好出來,就不謀而合的結合在一塊兒了
。
分幀會來來以下好處:
一、二進制協議:HTTP2 的分幀層是基於幀的二進制協議,方便機器解析。
二、首部壓縮:僅僅使用二進制協議還不夠,HTTP2 的首部還會被深度壓縮。
三、多路複用:當你在使用 HTTP2 傳輸連接的時候,沒必要等待上一個請求結束後才進行下一個請求,請求和響應能夠交織在一塊兒。
HTTP2 是基於幀的協議,爲了將重要的信息都封裝起來,讓協議的解析方能夠輕鬆的閱讀、解析並還原信息。相比之下,HTTP1 並非基於幀的,而是以文原本分隔,服務器只能根據文本換行符來拆分請求數據。
使用 HTTP1 可能會產生如下問題:
<crlf>
,有些平臺採用<lf>
幀有着嚴格的結構格式,有了幀,處理協議的程序就能預先知道會受到什麼,從而採起對應的解析方法。能夠把幀理解爲一個對象:
var frame = { length:'幀負載的長度', Type:'類型', Flags:'幀的標識', R:'保留位', Stream Identifer :'每一個流惟一ID', Frame Payload:'真實的幀內容' }
這樣以來,實現和維護都會簡單不少,不用等到一個請求完成之後才進行下一次請求,請求和響應能夠交錯甚至可多路複用。
流是 HTTP2 連接上獨立的,雙向的幀序列交換。能夠將流看做在鏈接上的一些列幀,他們構成了單獨的 HTTP 請求和響應。
一、消息:泛指 HTTP 中一個請求或一個響應。
二、流量控制:當一段接收並消費被髮送的數據時,它將發出一個 WINDOW_UPDATE 幀,用來表示其更新後的處理字節的能力。
確保一個流不會影響到其餘的流。
三、優先級
首先請求網頁上最重要的元素,以最優的順序獲取資源,由此來優化頁面性能。
提高單個資源性能的最佳方式,就是在它被用到以前就放到了瀏覽器的緩存裏,服務器端能夠主動將資源發給客戶端,這多是由於它知道客戶端不久後將會用到該資源。
若是服務器決定推送一個對象,會經過 PUSH_PROMISE 幀去傳遞將會被推送的資源。
以前說到,HTTP1 中沒有對首部進行壓縮,這會在每次請求中發送大量的冗餘首部,而 HTTP2 則解決了這個問題。HTTP2 沒有使用 gzip 壓縮,而是使用 HPACK,由於 GZIP 壓縮有泄漏加密信息的風險,簡稱 CRIME。
CRIME 原理:攻擊者在請求中添加數據,觀察壓縮加密後的數據量,若是變小了,就證實注入的數據和請求中的其餘內容有重複,進而搞清楚全部的加密數據內容。
HTTP2 的 HPACK 原理:
當客戶端請求時,會根據發送的首部信息,創建一張表:
索引 | 首部名稱 | 值 |
---|---|---|
62 | header1 | foo |
63 | header2 | bar |
64 | header3 | baz |
服務器端再接收到數據的時候也會建立一張與之對應的表。客戶端在發送下一個請求的時候,若是首部是相同的,就不用發送 Header 頭,只用發送索引號就好了,服務器端會索引去還原對應的首部信息。
以前說了這麼多 HTTP2 的好處,你是否已經以爲升級 HTTP2 已經火燒眉毛了呢?可是 HTTP2 頁不是完美的,這一小節咱們來介紹一下 HTTP2 的一些坑。
一、關於丟包。以前說到,HTTP2 採用多路複用,可讓多個請求在同一個 TCP 鏈接中進行傳輸,可是因爲 HTTP2 是單連接架構,若是惟一的鏈接發生了丟包,全部的工做都會受到影響,這實際上是 HTTP2 中比較大的坑。
HTTP1 在請求時創建了多個鏈接(和瀏覽器相關,通常爲 6 個),相對於 TCP 的初始擁塞窗口更大。當有一個鏈接發生丟包時,不會影響到其餘請求。對比之下: HTTP2 比 HTTP1 更容易丟包。
二、關於服務器端推送。以前說到,服務器端推送能夠主動給客戶端推送資源,用來減小客戶端發起請求數量。但是這也可能帶來一個問題:若是推送的資源在客戶端已經緩存過,那就是畫蛇添足了,因此在作服務器端渲染時,必定要和客戶端的緩存策略結合起來。
HTTP2 部署以後,以前針對於 HTTP1 的優化方案有可能就不適用了,咱們來看一下都有哪些。
在 HTTP1 中,會將一些靜態資源存在多個 cdn 服務器(由於瀏覽器對同一個域名下的資源請求併發數有限制,通常是 6 個)。可是使用 HTTP2 以後就沒必要要了,由於 HTTP2 採用多路複用,再多的資源也都可以進行併發請求。
在 HTTP1 中,咱們可會對一些小圖片直接打包成 base64 格式,用來減小請求。但內聯沒法利用緩存優點,應具體狀況具體分析。
因爲多路複用的緣由,多個小圖片能夠並行請求,雪碧圖也不是頗有必要了。
在 HTTP1 中,因爲沒法壓縮首部,會啓動一個無 cookie 的服務器專門用來存放某些靜態資源,用來減小沒必要要的 cookie 傳輸。在 HTTP2 中,首部信息會被 HPACK 算法優化,大大減小了首部字節,並且不用心增一個無 cookie 的服務器,因此建議取消掉禁用 cookie 域名的方式。
高數瀏覽器,之喲啊有可能就繼續下載可緩存資源,並把這些資源緩存起來,這個仍是有必要。
<link rel="prefetch" href="xxx.css">
一、HTTP 是使用 TCP 做爲傳輸層的協議,因爲 TCP 是可靠的,擁塞控制的協議,在進行一次鏈接時,會發生三次握手,斷開鏈接時會有 4 次揮手,因此有人提出能夠用 UDP 這種簡單,快速的協議去代替。
二、TLS(傳輸層安全協議,用來實現 HTTPS)也在不斷地進行改進。在 TLS1.3 版本中 新鏈接只須要一次往返(目前最少是三次),若是是恢復鏈接,則不須要往返延時。