1. 程式人生 > >HTTP/2 與 WEB 效能優化(一)

HTTP/2 與 WEB 效能優化(一)

提醒:本文最後更新於 1333 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

2013 年 11 月份開始,我的部落格開始支援了 SPDY 協議(詳見這裡),也就是 HTTP/2 的前身。今年二月份,Google 宣佈將在 16 年初放棄對 SPDY 的支援,隨後 Google 自家支援 SPDY 協議的服務都切到了 HTTP/2。今年 5 月 14 日,HTTP/2 以 RFC 7540 正式釋出。目前,瀏覽器方面,Chrome 40+ 和 Firefox 36+ 都正式支援了 HTTP/2;伺服器方面,著名的 Nginx 表示會在今年底正式支援 HTTP/2。

不得不說這幾年 WEB 技術一直在突飛猛進,爆炸式發展。昨天還覺得 HTTP/2 很遙遠,今天已經遍地都是了。對於新鮮事物,有些人不願意接受,覺得好端端為什麼又要折騰;有些人會盲目崇拜,認為它是能拯救一切的救世主。HTTP/2 究竟會給前端帶來什麼,什麼都不是?還是像某些人說的「讓前端那些優化小伎倆直接退休」?我打算通過寫一系列文章來嘗試回答這個問題,今天是第一篇。

提出問題

我們知道,一個頁面通常由一個 HTML 文件和多個資源組成。有一些很重要的資源,例如頭部的 CSS、關鍵的 JS,如果遲遲沒有載入完,會阻塞頁面渲染或導致使用者無法互動,體驗很差。如何讓重要的資源更快載入完是我本文要討論的問題。

HTTP/1

分析

我們先來考慮資源外鏈的情況。通常,外鏈資源都會部署在 CDN 上,這樣使用者就可以從離自己最近的節點上獲取資料。一般文字檔案都會採用 gzip 壓縮,實際傳輸大小是檔案大小的幾分之一。服務端託管靜態資源的效率通常非常高,服務端處理時間幾乎可以忽略。在忽略網路因素、傳輸大小以及服務端處理時間之後,使用者何時能載入完外鏈資源,很大程度上取決於請求何時能發出去,這主要受下面三個因素影響:

  • 瀏覽器阻塞(Stalled):瀏覽器會因為一些原因阻塞請求。例如在 rfc2616 中規定瀏覽器對於一個域名,同時只能有 2 個連線(HTTP/1.1 的修訂版中去掉了這個限制,詳見 rfc7230,因為後來瀏覽器實際上都放寬了限制),超過瀏覽器最大連線數限制,後續請求就會被阻塞。再例如現代瀏覽器在載入同一域名多個 HTTPS 資源時,會有意等第一個 TLS 連線建立完成再請求其他資源;
  • DNS 查詢(DNS Lookup):瀏覽器需要知道目標伺服器的 IP 才能建立連線。將域名解析為 IP 的這個系統就是 DNS。DNS 查詢結果通常會被快取一段時間,但第一次訪問或者快取失效時,還是可能耗費幾十到幾百毫秒;
  • 建立連線(Initial Connection):HTTP 是基於 TCP 協議的,瀏覽器最快也要在第三次握手時才能捎帶 HTTP 請求報文。這個過程通常也要耗費幾百毫秒;

當然我們一般都會給靜態資源設定一個很長時間的快取頭。只要使用者不清除瀏覽器快取也不重新整理,第二次訪問我們網頁時,靜態資源會直接從本地快取獲取,並不產生網路請求;如果使用者只是普通重新整理而不是強刷,瀏覽器會在請求頭帶上協商欄位 If-Modified-SinceIf-None-Match,服務端對沒有變化的資源會響應 304 狀態碼,告知瀏覽器從本地快取獲取資源。304 請求沒有正文,非常小。

也就是說資源外鏈的特點是,第一次慢,第二次快。

再來看看資源內聯的情況。把 CSS、JS 檔案內容直接內聯在 HTML 中的方案,毫無疑問會在使用者第一次訪問時有速度優勢。但通常我們很少快取 HTML 頁面,這種方案會導致內聯的資源沒辦法利用瀏覽器快取,後續每次訪問都是一種浪費。

解決

很早之前,就有網站開始針對第一次訪問的使用者將資源內聯,並在頁面載入完之後非同步載入這些資源的外鏈版本,同時記錄一個 Cookie 標記表示使用者來過。使用者再次訪問這個頁面時,服務端就可以輸出只有外鏈版本的頁面,減小體積。

這個方案除了有點浪費流量之外(一份資源,內聯外鏈載入了兩次),基本上能達到更快載入重要資源的效果。但是在流量更加寶貴的移動端,我們需要繼續改進這個方案。

考慮到移動端瀏覽器都支援 localStorage,可以將第一次內聯引入的資源快取起來後續使用。快取更新機制可以通過在 Cookie 中存放版本號來實現。這樣,服務端收到請求後,首先要檢查 Cookie 頭中的版本標記:

  • 如果標記不存在或者版本不匹配,就將資源內聯輸出,並提供當前版本標記。頁面執行時,會把內聯資源存入 localStorage,並將資源版本標記存入 Cookie;
  • 如果標記匹配,就輸出 JavaScript 片段,用來從 localStorage 讀取並使用資源;

由於 Cookie 內容需要儘可能的少,所以一般只存總的版本號。這會導致頁面任何一處資源變動,都會改變總版本號,進而忽略客戶端所有 localStorage 快取。要解決這個問題可以繼續改進我們的方案:Cookie 中只存放使用者唯一標識,使用者和資源對應關係存在服務端。服務端收到請求後根據使用者標識,計算出哪些資源需要更新,從而輸出更有針對性的 HTML 文件。

這套方案要投入實際使用,要處理一系列異常情況,例如 JS / Cookie / localStorage 被禁用;localStorage 被寫滿;localStorage 內容損壞或丟失等等。考慮成本和實際收益,推薦只在移動專案中使用這種方案。

HTTP/2

對於 HTTP/2 來說,要解決前面這個問題簡直就太容易了,開啟「Server Push」即可。HTTP/2 的多路複用特性,使得可以在一個連線上同時開啟多個流,雙向傳輸資料。Server Push,意味著服務端可以在傳送頁面 HTML 時主動推送其它資源,而不用等到瀏覽器解析到相應位置,發起請求再響應。另外,服務端主動推送的資源不是被內聯在頁面裡,它們有自己獨立的 URL,可以被瀏覽器快取,當然也可以給其他頁面使用。

服務端可以主動推送,客戶端也有權利選擇接收與否。如果服務端推送的資源已經被瀏覽器快取過,瀏覽器可以通過傳送 RST_STREAM 幀來拒收。

可以看到,HTTP/2 的 Server Push 能夠很好地解決「如何讓重要資源儘快載入」這個問題,一旦普及開來,可以取代前面介紹過的 HTTP/1 時代優化方案。

--EOF--

提醒:本文最後更新於 1333 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

相關推薦

HTTP/2 WEB 效能優化

提醒:本文最後更新於 1333 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 2013 年 11 月份開始,我的部落格開始支援了 SPDY 協議(詳見這裡),也就是 HTTP/2 的前身。今年二月份,Google 宣佈將在 16 年初放棄對 SPDY 的支援,隨後 Google 自家支援

HTTP/2 WEB 效能優化

提醒:本文最後更新於 1327 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 在「HTTP/2 與 WEB 效能優化(一)」這篇部落格中,我主要寫了 HTTP/2 中的 Server Push 給 WEB 效能優化帶來的便利,今天繼續來聊一聊 HTTP/2 其他方面的改變。 我們知道,HT

HTTP/2 WEB 效能優化

提醒:本文最後更新於 1320 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 在連續寫了兩篇關於「HTTP/2 與 WEB 效能優化」的文章後,今天來寫這個系列的最後一篇。在正式開始之前,我們先來簡單回顧下之前兩篇文章: 「HTTP/2 與 WEB 效能優化(一)」的結論是:HTTP/2

WEB效能優化:Resin下的 GZIP壓縮

最近在做前端的效能優化,發現一個頁面引入的js、css等外部資源過多的話,瀏覽器第一次請求的時候會下載很大的資源,那麼在使用者網路不好的情況下,頁面的載入速度會受很大的影響,因此要對WEB前端做各種優化。 在此第一步做的就是所有資源的壓縮,在開發環境編寫好的js和css檔案

Web前端效能優化

1. 靜態資源的壓縮與合併 我們在開發的時候會習慣縮排和寫註釋,方便我們在日常的維護,但將程式碼上傳至服務端後,我們完全可以把那些空格、製表符、換行符進行壓縮,以此減少請求資源的大小;同樣的,我們在服務端所引用的第三方庫進行合併,能減少 HTTP 的請求數量 將

前端效能優化-- 檔案的壓縮合併

首先我們需要搞清楚,我們為什麼需要進行檔案的壓縮與合併?壓縮與合併的原因主要有兩點 減少HTTP請求數 減小HTTP的請求大小 這裡的主要優化方式有3點: HTML/CSS/JS檔案的壓縮 CSS/JS檔案的合併 開啟GZIP壓縮 如何進行HTML壓縮 使用線上網站壓縮

Storm 使用經驗效能優化

提交任務:storm jar storm-starter-topologies-1.0.1.jar org.apache.storm.starter.WordCountTopology word-count查詢任務:storm list Kill任務:storm kill

資料庫設計效能優化

** 良好的資料庫設計能夠 **: 節省資料的儲存空間。 能夠保證資料的完整性。 方便進行資料庫應用系統的開發。 糟糕的資料庫設計: 資料冗餘、儲存空間浪費。 記憶體空間浪費。 資料更新和插入異常麻煩。 資料庫的生命週期: 1、需求分析

淺談前端效能優化

前端效能優化中,減少HTTP請求可以提高頁面的響應速度。 瀏覽器在第一次訪問頁面時向伺服器請求資源,並快取起來,下次再訪問時會判斷在快取中是否已有該資源且有沒有更新過,如果已有該資源且未更新過,則直接從瀏覽器快取中讀取。原理:通過HTTP 請求頭中的 If-Modified-Since(If-No-Matc

oracle程式設計300例-效能優化

1、在SELECT語句中避免使用“*” 2、儘可能減小記錄行數 3、使用rowid高效刪除重複記錄 例項: delete from stu s where s.rowid>(select min(t.rowid) from stu t where t.stu=t.stu / 4、使用t

MySQL之查詢效能優化

為什麼查詢速度會慢 通常來說,查詢的生命週期大致可以按照順序來看:從客戶端,到伺服器,然後在伺服器上進行解析,生成執行計劃,執行,並返回結果給客戶端。其中“執行”可以認為是整個生命週期中最重要的階段,這其中包括了大量為了檢索資料到儲存引擎的呼叫以及呼叫後的資料處理,包括排序、分組等。 在完成這些任務的時候

JVM效能優化JVM技術入門

作者 Eva Andreasson  譯者:趙峰 校對:方騰飛  原文連結 Java應用程式是執行在JVM上的,但是你對JVM技術瞭解嗎?這篇文章(這個系列的第一部分)講述了經典Java虛擬機器是怎麼樣工作的,例如:Java一次編寫的利弊,跨平臺引擎,垃圾回收基礎知識,經典的GC演算法和編譯優

百萬級資料庫效能優化——建立索引

對查詢進行優化,要儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 為了能夠使用索引,我們應該避免使用以下查詢方式: 2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表

UI效能優化Overdraw排查和調優

文章目錄 概述與案例 排查技巧一:檢視是否過度繪製 排查技巧二:通過Hierachy View或者Layout Inspecot檢視佈局層級 Overdraw優化策略-扁平化 一、至尊超薄

資料庫效能優化 索引

當前主流關係型資料庫RDBMS都是將平衡樹(B樹、B+樹)作為預設索引的資料結構。主鍵與索引A. 表不加主鍵,會以無序的形式一行一行的存放在磁碟上。B. 表增加主鍵後,轉變為樹狀結構,整個表變成一個聚集索引。索引的優缺點優點:索引可提升表的查詢速度;為用來排序或分組的欄位新增

Android效能優化App啟動原理分析及啟動時間優化

一、啟動原理解析 Android是基於Linux核心的,當手機啟動,載入完Linux核心後,會由Linux系統的init祖先程序fork出Zygote程序,所有的Android應用程式程序以及系統服務程序都是這個Zygote的子程序(由它fork出來的)。其中最重要的一個就

效能優化Hibernate 利用快取一級、二級、查詢提高系統性能

      在hibernate中我們最常用的有三類快取,分別為一級快取、二級快取和查詢快取,下面我們對這三個快取在專案中的使用以及優缺點分析一下。       快取它的作用在於提高效能系統性能,介於應用系統與資料庫之間而存在於記憶體或磁碟上的資料。       我們程式設

Android效能優化記憶體洩露優化靜態變數、單例模式、屬性動畫

記憶體洩露優化分為兩個方面,一方面是在開發過程中避免寫出有記憶體洩露的程式碼,另一方面是通過一些分析工具比如 MAT來找出潛在的記憶體洩露繼而解決。 一、靜態變數導致記憶體洩露。一般情況下靜態變數引用

超詳細:資料庫效能優化

出處: 1.資料庫訪問優化法則 要正確的優化SQL,我們需要快速定位能性的瓶頸點,也就是說快速找到我們SQL主要的開銷在哪裡?而大多數情況效能最慢的裝置會是瓶頸點,如下載時網路速度可能會是瓶頸點,本地複製檔案時硬碟可能會是瓶頸點,為什麼這些一般的工

高效能網站建設指南-前端效能優化

​ 年前,讀完了《高效能網站建設指南》,但是一直沒有整理。年後回來和同事一起出了份前端面試題,涉及到了關於效能優化的問題,在此特梳理一下。 ​ 大量的公司在開發功能業務時,只關注功能點的實現,對於效能方面要求很低甚至不作為考慮範圍。在遇到一些效能瓶