HTTP2 基礎知識點總結

最近讀完《HTTP2 基礎教程》,至關因而對 HTTP2 有了個大體的瞭解,本文已加入個人博客,感謝你們支持!css

HTTP 發展史

互聯網剛開始的時候,人們瀏覽網頁只是爲了閱讀文字,隨着時代的不斷髮展,人們對於網站的需求愈來愈高,一個網站不只僅要展現文字,還要展現圖片,視頻,3D 特效等。html

一、Web 頁面引用的內容每一年都在增加,圖片,JS,CSS 愈來愈大,也愈來愈多。git

二、Web 所依賴的資源也變得愈來愈複雜。github

三、大多數 Web 頁面會關聯數十個域名的資源,每個資源都須要經歷一次 DNS,TCP,TLS 等。算法

HTTP1.1 階段

人們對網站的需求愈來愈多,可是 HTTP 協議卻發展很慢,HTTP1.1 已經存在 20 年了,卻仍是當前社會中使用最普遍的協議。如下幾個缺點也愈來愈被你們所關注:瀏覽器

一、隊頭阻塞,在請求響應中若是出現任何問題,剩下的工做都會被阻塞在那次請求應答以後。緩存

二、低效的 TCP 利用安全

擁塞窗口:在接收方確認數據包以前,發送方能夠發出的 TCP 包的數量。(例如:若是擁塞窗口爲 1,那麼發送方發出 1 個數據包以後,只有接收方確認了那個包,才能發送下一個)。服務器

TCP 中有個概念叫慢啓動,目的是爲了讓新鏈接搞清楚當前的網絡情況,避免給已經擁堵的網絡繼續添亂。(它容許客戶端在收到每一個確認回覆後額外發送 1 個未確認包,這意味着新鏈接在收到 1 個確認回覆後,能夠發送 2 個數據包,在收到 2 個確認回覆後,能夠發 4 個,以此類推,直到達到上限值)cookie

三、臃腫的消息首部

雖然 HTTP1 提供了壓縮請求內容的機制,可是消息首部卻沒法壓縮,若是算上 cookie,可能每次都會多發送幾千個字節。

四、受限制的優先級設置

HTTP1 沒有優先級一說,要麼發起請求,要麼不發起。

Web 性能調優

爲了解決 HTTP1 的各類問題,你們也總結一下優化方案,咱們來依次介紹一下吧。

網站運行流程(簡化版)

  1. 輸入 URL 並敲回車。
  2. 根據域名解析 IP 地址。
  3. 創建 TCP 鏈接管道。
  4. 若是是 HTTPS,進行 TLS 握手。
  5. 服務器端收到請求。
  6. 輸出主體 HTML 。
  7. 客戶端根據 HTML 內的其餘資源進行請求。

若是想在 HTTP 協議層面作優化,能夠考慮下幾點:

  • DNS 查詢時間
  • TCP 三次握手時間
  • TLS 安全協議時間(祕鑰協商,對稱加密,非對稱加密)

DNS 查詢優化

  • 限制不一樣域名數量
  • 使用 dns-prefetch,在解析主體 HTML 的同時,就會解析制定域名。
<link rel="dns-prefetch" href="//www.xxx.com" />
  • 找一家好的外部供應商

優化 TCP 鏈接

  • 使用 preconnect 指令,讓鏈接在使用以前就已經創建好。
<link rel="preconnect" href="//www.xxx.com" />
  • 儘早終止響應(藉助 CDN,讓傳輸更近)。

避免重定向

  • 利用 CDN 雲端重定向。
  • 統一域名使用 Web 服務器上的 rewrite 規則,避免重定向。

緩存策略

咱們經常使用緩存來避免沒必要要的請求,但要使用緩存必須遵照着兩個概念:多用戶之間可共享可以接受必定程度的舊數據

  • 純靜態不變的內容,能夠永久緩存。
  • CSS/JS 等個性化資源,緩存時間是會話(交付)平均時間的兩倍。
強緩存

使用 Expires 首部,將資源失效的日期告訴客戶端,在失效如期以前,客戶端都會直接使用緩存中的資源而不會發起請求

使用 Cache-Control 首部,進行更多的定製化緩存:

  • max-age 表示資源會緩存的具體時間
  • no-cache 不使用本地緩存。須要使用緩存協商。
  • no-store 直接禁止遊覽器緩存數據,每次用戶請求該資源,都會向服務器發送一個請求,每次都會下載完整的資源。
  • public 能夠被全部的用戶緩存,包括終端用戶和 CDN 等中間代理服務器。
  • private 只能被終端用戶的瀏覽器緩存,不容許 CDN 等中繼緩存服務器對其緩存。
協商緩存

在請求中包含 HTTP 首部 Last Modified,僅當最新內容在首部中制定的日誌以後被更新過,服務器才返回完整內容,不然返回 304.

在請求實體中包含實體校驗碼 ETag,它惟一標識所請求的資源,服務器會比較當前 ETag 與請求首部中收到 ETag,若是一致,就返回 304.

壓縮和代碼簡化

刪除 html 文檔中的註釋,換行,空格等,減小資源大小。

避免阻塞 CSS/JS

因爲 JS 在處理時,會阻止其餘任何資源的下載和渲染,可能會帶來沒必要要的延遲。

  • CSS 影響頁面可視化效果,建議先請求。
  • JS 則須要正確用好 defer, async。

圖片優化

一張圖片中每每並非只有圖片內容,每每還包含有一些圖片元信息:地理位置信息,時間戳,尺寸,像素等。而這些信息對於頁面並無聲明用,還會增長圖片的大小,建議刪除掉圖片元信息,只保留真正有用的部分。

另外,頁面中的圖片,儘可能不要使用 CSS 去拉伸或者縮放,須要多大的圖片,就返回多大的圖,避免資源浪費。

迴歸正題 HTTP2 核心概念

上面介紹了 HTTP 的歷史以及現階段使用最普遍的 HTTP1 ,接下來咱們來介紹一下 HTTP2 ,看一看 HTTP2 是怎麼解決 HTTP1 所遺留的問題?

首先,要搭建 HTTP2 服務,必須配套使用 HTTPS 安全策略,才能獲得瀏覽器的支持。HTTP2 其實並無要求必須使用 HTTPS,只是人們正好認識到 HTTPS 的重要性,而 HTTP2 正好出來,就不謀而合的結合在一塊兒了

HTTP2 分層

  • 分幀層,即 HTTP2 多路複用能力的核心部分。
  • 數據或 HTTP 層,其中包含傳統上被認爲是 HTTP 及其相關數據的部分。

分幀會來來以下好處:

一、二進制協議:HTTP2 的分幀層是基於幀的二進制協議,方便機器解析。

二、首部壓縮:僅僅使用二進制協議還不夠,HTTP2 的首部還會被深度壓縮。

三、多路複用:當你在使用 HTTP2 傳輸連接的時候,沒必要等待上一個請求結束後才進行下一個請求,請求和響應能夠交織在一塊兒。

HTTP2 是基於幀的協議,爲了將重要的信息都封裝起來,讓協議的解析方能夠輕鬆的閱讀、解析並還原信息。相比之下,HTTP1 並非基於幀的,而是以文原本分隔,服務器只能根據文本換行符來拆分請求數據。

使用 HTTP1 可能會產生如下問題:

  • 換行符對於每一個平臺可能有兼容性問題,例若有些平臺採用<crlf>,有些平臺採用<lf>
  • 一次只能處理一個請求或響應,完成以前不能中止解析。
  • 沒法預判解析須要多少內存,若是一行的信息量太大,超出了內存,會返回 400 錯誤

幀有着嚴格的結構格式,有了幀,處理協議的程序就能預先知道會受到什麼,從而採起對應的解析方法。能夠把幀理解爲一個對象:

var frame = {
    length:'幀負載的長度',
    Type:'類型',
    Flags:'幀的標識',
    R:'保留位',
    Stream Identifer :'每一個流惟一ID',
    Frame Payload:'真實的幀內容'
}

這樣以來,實現和維護都會簡單不少,不用等到一個請求完成之後才進行下一次請求,請求和響應能夠交錯甚至可多路複用。

流是 HTTP2 連接上獨立的,雙向的幀序列交換。能夠將流看做在鏈接上的一些列幀,他們構成了單獨的 HTTP 請求和響應。

一、消息:泛指 HTTP 中一個請求或一個響應。

二、流量控制:當一段接收並消費被髮送的數據時,它將發出一個 WINDOW_UPDATE 幀,用來表示其更新後的處理字節的能力。

確保一個流不會影響到其餘的流。

三、優先級

首先請求網頁上最重要的元素,以最優的順序獲取資源,由此來優化頁面性能。

  • 經過 HEADERS 幀能夠指明某些對象和其餘對象的依賴關係。
  • 經過 PRIORITY 幀,能夠告訴服務器如何肯定具備共同依賴關係的對象的優先級。

服務器推送

提高單個資源性能的最佳方式,就是在它被用到以前就放到了瀏覽器的緩存裏,服務器端能夠主動將資源發給客戶端,這多是由於它知道客戶端不久後將會用到該資源。

若是服務器決定推送一個對象,會經過 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 的一些坑。

一、關於丟包。以前說到,HTTP2 採用多路複用,可讓多個請求在同一個 TCP 鏈接中進行傳輸,可是因爲 HTTP2 是單連接架構,若是惟一的鏈接發生了丟包,全部的工做都會受到影響,這實際上是 HTTP2 中比較大的坑。

HTTP1 在請求時創建了多個鏈接(和瀏覽器相關,通常爲 6 個),相對於 TCP 的初始擁塞窗口更大。當有一個鏈接發生丟包時,不會影響到其餘請求。對比之下: HTTP2 比 HTTP1 更容易丟包。

二、關於服務器端推送。以前說到,服務器端推送能夠主動給客戶端推送資源,用來減小客戶端發起請求數量。但是這也可能帶來一個問題:若是推送的資源在客戶端已經緩存過,那就是畫蛇添足了,因此在作服務器端渲染時,必定要和客戶端的緩存策略結合起來。

HTTP2 反模式

HTTP2 部署以後,以前針對於 HTTP1 的優化方案有可能就不適用了,咱們來看一下都有哪些。

  • 域名拆分

在 HTTP1 中,會將一些靜態資源存在多個 cdn 服務器(由於瀏覽器對同一個域名下的資源請求併發數有限制,通常是 6 個)。可是使用 HTTP2 以後就沒必要要了,由於 HTTP2 採用多路複用,再多的資源也都可以進行併發請求。

  • 資源內聯

在 HTTP1 中,咱們可會對一些小圖片直接打包成 base64 格式,用來減小請求。但內聯沒法利用緩存優點,應具體狀況具體分析。

  • 資源合併(雪碧圖等)

因爲多路複用的緣由,多個小圖片能夠並行請求,雪碧圖也不是頗有必要了。

  • 禁用帶 cookie 的域名

在 HTTP1 中,因爲沒法壓縮首部,會啓動一個無 cookie 的服務器專門用來存放某些靜態資源,用來減小沒必要要的 cookie 傳輸。在 HTTP2 中,首部信息會被 HPACK 算法優化,大大減小了首部字節,並且不用心增一個無 cookie 的服務器,因此建議取消掉禁用 cookie 域名的方式。

  • 資源預取

高數瀏覽器,之喲啊有可能就繼續下載可緩存資源,並把這些資源緩存起來,這個仍是有必要。

<link rel="prefetch" href="xxx.css">

展望將來

一、HTTP 是使用 TCP 做爲傳輸層的協議,因爲 TCP 是可靠的,擁塞控制的協議,在進行一次鏈接時,會發生三次握手,斷開鏈接時會有 4 次揮手,因此有人提出能夠用 UDP 這種簡單,快速的協議去代替。

  • Google 開發的 QUIC 是極快的 UDP 網絡鏈接,提供了 HTTP2 等效的,多路複用,流量控制,TSL 等效的安全機制,以及 TCP 等效的鏈接語義、可靠性、擁塞機制。

二、TLS(傳輸層安全協議,用來實現 HTTPS)也在不斷地進行改進。在 TLS1.3 版本中 新鏈接只須要一次往返(目前最少是三次),若是是恢復鏈接,則不須要往返延時。

相關文章
相關標籤/搜索