深刻了解HTTP/2的前世此生以及Web性能優化總結


HTTP/2的出現,無疑對Web性能的提高帶來了巨大的助力,改變了Web開發者優化網站的方式,但以前一直對它處於模糊的狀態,只知道一些零零碎碎的知識,週末終於靜下心來,從HTTP1開始,找到HTTP/2的存在及其存在必然性,整理了一些內容以下,但願能對有須要的同窗產生一點點幫助。css


分析以前,先來點直觀好玩的吧html

1、讓人興奮的HTTP/2

這個網站作了一個測試:分別利用HTTP/1和HTTP/2協議來下載一張大圖(該大圖由多張小圖組成),HTTP/2完勝 前端

點進去看看? [HTTP/2 is the future of the Web, and it is here!] webpack


有個成語叫「事出有因」,每一個事物都有其存在的意義(緣由),而HTTP/2的誕生天然來自於HTTP/1的一些痛點
git


2、爺爺HTTP/1的痛點以及解決辦法

HTTP(應用層)創建在TCP(傳輸層)之上,HTTP協議的一些瓶頸以及性能優化都是創建在TCP協議自己的特性之上。  github

因此談HTTP以前仍是得對TCP有一點點的瞭解(好比對三次握手、四次揮手、慢啓動、往返時延RTT、擁塞窗口cwnd……) web

起碼得知道三次握手和四次揮手是爲了防止了服務器端的一直等待而浪費資源;算法

知道慢啓動是爲了不擁塞;chrome

知道RTT和cwnd的概念是什麼 segmentfault

 傳送門:[TCP慢啓動、擁塞避免、快速重傳、快速恢復 - CSDN博客]


影響網絡請求的主要因素有兩個:帶寬和延遲 

帶寬跟網絡基礎建設相關暫不談,因此延遲成了web工程師們的頭號公敵。  

http1.0被抱怨最多的兩個問題

> 理解下面兩個問題有一個十分重要的前提:客戶端是依據域名來向服務器創建鏈接,通常PC端瀏覽器會針對單個域名的server同時創建6~8個鏈接,手機端的鏈接數則通常控制在4~6個。顯然鏈接數並非越多越好,資源開銷和總體延遲都會隨之增大。

一、鏈接沒法複用

鏈接沒法複用會致使每次請求都經歷三次握手和慢啓動。三次握手在高延遲的場景下影響較明顯,慢啓動則對文件類大請求影響較大。 

解決方案:

①HTTP持久鏈接:Connection:Keep-Alive [HTTP持久鏈接],痛點在於當前請求必須完全完成後,下一請求才能正確發送。 

②http long-polling:長輪詢 

③http streaming:創建起一個tcp鏈接後,服務器不會結束streaming請求,持續的經過這個通道返回最新的業務數據,數據通道也是單向的,除非客戶端自動斷開,不然一直保持鏈接

④websocket:也是基於tcp協議,提供雙向的數據通道,優點在於提供了message的概念,同時又提供了傳統的http所缺乏的長鏈接功能


二、head of line blocking 線頭阻塞

head of line blocking會致使帶寬沒法被充分利用,以及後續健康請求被阻塞,健康的請求會被不健康的請求影響,並且這種體驗的損耗受網絡環境影響,出現隨機且難以監控

解決方案: [HTTP管線化]


基於HTTP/1的其餘優化手段 

一、Spriting(圖片合併):但有時候只須要其中一張小圖,就會浪費流量 

二、Inlining(內容內嵌):好比把圖片轉化爲base64編碼後內嵌到總文件中,問題同上 

三、Concatenation(文件合併):粒度變大,一個小的js代碼改動會致使整個js文件被下載

四、Domain Sharding(域名分片):瀏覽器或者客戶端是根據domain(域名)來創建鏈接,多創建幾個sub domain(子域名),那麼同時能夠創建的http請求就會更多,鏈接數變多以後,受限制的請求就不須要等待前面的請求完成才能發出了;只有在請求數很是之多的場景下才有明顯的效果,移動端建議不要使用 [Why Domain Sharding is Bad News for Mobile Performance and Users]



3、爸爸SPDY的改進

HTTP/1存在很多問題,2012年google提出了SPDY的方案,直擊HTTP/1痛點


一、多路複用(multiplexing) 

多路複用經過多個請求stream共享一個tcp鏈接的方式,解決了http1.x holb(head of line blocking)的問題,下降了延遲同時提升了帶寬的利用率 

二、請求優先級(request prioritization) 

SPDY容許給每一個request設置優先級,這樣重要的請求就會優先獲得響應 

三、header壓縮 

SPDY對header的壓縮率能夠達到80%以上 

四、server推送(server push) 

開啓server push以後,server經過X-Associated-Content header(X-開頭的header都屬於非標準的,自定義header)告知客戶端會有新的內容推送過來。在用戶第一次打開網站首頁的時候,server將資源主動推送過來能夠極大的提高用戶體驗。 

五、server暗示(server hint) 

和server push不一樣的是,server hint並不會主動推送內容,只是告訴有新的內容產生,內容的下載仍是須要客戶端主動發起請求。server hint經過X-Subresources header來通知



4、新生代HTTP/2及其特色

HTTP/1.x是一個文本協議,這注定它是很是冗餘的協議,HTTP/2改變了這一點,在HTTP/1.x的語義上,將文本數據封裝在幀裏,並採用二進制編碼

http2.0的格式定義更接近tcp層的方式,雖然看上去協議的格式和http1.x徹底不一樣了,實際上http2.0並無改變http1.x的語義,只是把原來http1.x的header和body部分用frame從新封裝了一層而已。調試的時候瀏覽器甚至會把http2.0的frame自動還原成http1.x的格式


理解HTTP/2以前,要先理解兩個概念 幀(frame)和流(stream)[HTTP/2中多路複用:幀(frame)和流(stream)]


HTTP/2和SPDY不一樣的地方在於,它是業界標準,而SPDY是chrome自家的孩子,馬虎不得,一言一行都得考慮明星效應


因此它有幾個設計前提 

  • 客戶端向server發送request這種基本模型不會變。 
  • 老的scheme不會變,使用http://和https://的服務和應用不會要作任何更改,不會有http2://。 
  • 使用http1.x的客戶端和服務器能夠無縫的經過代理方式轉接到http2.0上。 
  • 不識別http2.0的代理服務器能夠將請求降級到http1.x。


基於以上原則,HTTP/2繼承了SPDY的部分特性,並基於本身的明星定位作了一些擴展,下面介紹HTTP/2的基本概念及其如何優化Web性能的一些實踐。


一、二進制幀:HTTP/2的「基本單位」

把HTTP/1.x每一個請求都看成一個「流」,那麼請求化成多個流,請求響應數據切成多個幀,不一樣流中的幀交錯地發送給對方,這就是HTTP/2中的多路複用


二、多路複用(鏈接共享)

一、消除了多種經過捆綁相關資產以削減鏈接數量的長期解決思路的存在必要性

好比(上面的優化手段): 

  • JS和CSS文件級聯:將多個小型文件彙總成一個大型文件,從而下降整體請求數量 
  • 雪碧圖 * Domain Sharding(域名分片):增長總體TCP鏈接數量 
  • 內容內嵌  

二、請求優先級和請求依賴 

一個request對應一個stream並分配一個id,這樣一個鏈接上能夠有多個stream,每一個stream的frame能夠隨機的混雜在一塊兒,接收方能夠根據stream id將frame再歸屬到各自不一樣的request裏面 

因此,HTTP/2裏的每一個stream均可以設置優先級(Priority)和依賴(Dependency),真正解決了關鍵請求被阻塞的問題

三、header壓縮 

SPDY/2使用的是gzip壓縮算法 

HTTP/2採用的是一種叫HPACK的壓縮算法

四、Server Push服務器推送

好比說客戶端請求一個 html, html 裏面含有 css 和圖片,按照正常來說,解析 html 以後要分別發出 CSS 的請求和圖片的請求,可是若是服務端得知頁面支持 server push,客戶端便只須要發出 http 請求,而服務器直接將 css 和圖片一塊兒發出去,以至請求多個響應未發先至。這就是 server push 的做用,和 inlining 有點相似,可是相比 inlining 有兩個好處,inlining 會影響緩存,會增大 html 的體積,包括後臺模板的維護,這也便增長開發和維護成本,對於客戶而言僅僅是多個請求。

五、重置鏈接

對於HTTP/1來講,是經過設置tcp segment裏的reset flag來通知對端關閉鏈接的。這種方式會直接斷開鏈接,下次再發請求就必須從新創建鏈接。 

HTTP/2引入RST_STREAM類型的frame,能夠在不斷開鏈接的前提下取消某個request的stream,表現更好。


5、HTTP/2下的Web優化觀念

一、核心理念

在HTTP/1下,你們的關注點都在減小向服務器發起的HTTP請求數,將盡量多的資源塞進一個鏈接中,並尋找其餘辦法來避免瀏覽器出現線頭阻塞。 

在HTTP/2下,Web開發者應該專一於網站的緩存調優,而不是擔憂如何減小HTTP請求數。通用的法則是,傳輸輕量、細粒度的資源,以便獨立緩存和並行傳輸。 


這種轉變的出現是由於HTTP/2的多路複用和頭部壓縮特性。 多路複用使得不一樣的請求共用一個TCP鏈接,容許多個資源並行下載,避免創建多個鏈接帶來沒必要要的額外開銷。它消除了HTTP/1.1中的線頭阻塞問題。 

頭部壓縮進一步減小了多個HTTP請求的開銷,由於每一個請求開銷都小於未壓縮的等價HTTP/1.1請求。  

HTTP/2還有兩個改變會影響到你的Web優化:流優先級和服務端推送。前者容許瀏覽器指定接受資源的順序,後者容許服務端主動發送額外的資源。


二、將會被歷史拋棄的HTTP/1優化手段

如此一來,上面HTTP/1的幾種優化手段就應該被歷史拋棄了:合併文件(webpack怎麼辦?思考題)、內聯資源、雪碧圖、細分域名


三、依然能複用的優化手段

①DNS預解析:減小DNS查詢時間

DNS查詢須要一個RTT時間,在瀏覽器級別,系統級別都會有層DNS緩存,以前解析過的能夠直接從本機緩存獲取,以減小延遲。 Web標準提供了一種DNS預解析技術,由於服務器是知道頁面即將會發生哪些請求的,那咱們能夠在頁面頂部,插入 

<link rel="dns-prefetch" href="//host/">複製代碼

讓瀏覽器先解析一下這個域名。那麼,後續掃到同域的請求,就能夠直接從DNS緩存獲取了。 

此外,Web標準也提供prefetch,prerender的預加載技術。prefectch會在瀏覽器空閒的時候,向所提供的連接發起請求,而prerender不只會請求,還會幫你在後臺渲染頁面。若是在一個頁面中,你知道用戶有很大機率去點某個連接,能夠嘗試把這個連接加到prefetch或prerender,那麼用戶就會秒開這個頁面了。 

②使用CDN 

將Web資源經過CDN放在地理上更靠近來訪者的服務器節點上

③利用瀏覽器緩存 

進一步利用內容分發網絡,將資源存儲在用戶的本地瀏覽器緩存中,除了產生一個304 Not Modified響應以外,這避免了任何形式的數據在網絡上傳輸 

④最小化HTTP請求大小和響應大小 

⑤避免沒必要要的重定向 

重定向意味着要從新發起請求 

這裏要說的一種重定向是,訪問HTTP站點,跳轉到HTTPS,並非指資源緩存的重定向獲取 避免這種跳轉,咱們能夠用HSTS策略告訴瀏覽器,之後訪問我這個站點,必須用HTTPS協議來訪問,讓瀏覽器幫忙作轉換,而不是請求到了服務器後,才知道要轉換

在響應頭部加上 Strict-Transport-Security: max-age=31536000便可


6、HTTP/2目前存在的問題以及使用限制

一、HTTP2.0最大的亮點在於多路複用,而多路複用的好處只有在http請求量大的場景下才明顯,因此目前來講,可能更適用於瀏覽器瀏覽大型站點的時候。 

二、HTTP2.0對於ssl的依賴比較強 雖然HTTP2.0也能夠不走ssl,有些場景確實可能不適合https,好比對代理服務器的cache依賴,對於內容安全性不敏感的get請求能夠經過代理服務器緩存來優化體驗 

三、移動端iOS9+自動支持HTTP/2,Android理論上來講須要5.0以上才支持(這個理論上非絕對,這裏不說了) 


7、後記

感謝您耐心看到這裏,但願有所收穫! 

若是不是很忙的話,麻煩點個star⭐【Github博客傳送門】,舉手之勞,倒是對做者莫大的鼓勵。  

我在學習過程當中喜歡作記錄,分享的是本身在前端之路上的一些積累和思考,但願能跟你們一塊兒交流與進步,更多文章請看【amandakelake的Github博客】


參考

HTTP/2.0 相比1.0有哪些重大改進? - 知乎 

從TCP、HTTP/1的問題上分析了爲什麼會誕生HTTP/2 排名第二的那篇文章更加詳細  

[Web 開發者的 HTTP/2 性能優化指南] 

與HTTP/1作了對比,容易理解和記憶 

[Web 的現狀:網頁性能提高指南 - 前端郭高工 - SegmentFault 思否] 

在HTTP/1的基礎上,講的比較詳細有條理 

【網絡協議】Web協議將來優化指南

對TCP、HTTP一、HTTPS、SPDY、HTTP2等幾種協議作了對比區分

相關文章
相關標籤/搜索