HTTP/2 Server Push 詳解(下)

發表於2017-04-23

接上篇 HTTP/2 Server Push 詳解(上)

譯者注:上文介紹了 HTTP/2 Server Push 的基本概念和用法,下面繼續深入實際使用的效能和考量。

如何分辨 Server Push 是否生效

目前,我們已經通過 Link 首部來告訴伺服器推送一些資源。剩下的問題是,我們怎麼知道是否生效了呢?

這還要看不同瀏覽器的情況。最新版本Chrome將在開發者工具的網路發起欄中展示推送的資源。

Chrome顯示伺服器推送的資源(大圖

更進一步,如果把滑鼠懸停在網路請求瀑布圖中的資源上,將獲得關於該推送資源的詳細耗時資訊:

Chrome顯示推送資源的詳細耗時資訊(大圖

Firefox對推送資源則標識地沒那麼明顯。如果一個資源是被推送的,則瀏覽器開發者工具的網路資訊裡,會將其狀態顯示為一個灰色圓點。

Firefox對推送資源的展示(大圖

如果你在尋找一個確保能分辨資源是否為推送的方法,可以使用 nghttp 命令列客戶端來檢查是否來自 HTTP/2 伺服器,像這樣:

這個命令會顯示出會話中所有資源的彙總結果。推送的資源將在輸出中顯示一個星號(*),像這樣:

這裡,我在自己的站點上使用了 nghttp,有五個推送的資源(至少在寫這篇文章時)。推送的資源在 requestStart 欄左側以星號標記了出來。

現在我們知道了如何識別推送的資源,接下里具體看看對真實站點的效能有什麼實際影響。

測量 Server Push 效能

測量任何效能提升的效果都需要很好的測試工具。Sitespeed.io 是一個可從 npm 獲取的優秀工具,它可以自動地測試頁面,收集有價值的效能資料。有了得力的工具,我們來快速過一下測試方法吧。

測試方法

我想通過一個有意義的方法,來測量 Server Push 對網站效能的影響。為了讓結果是有意義的,我需要建立6種獨立的場景來交叉對比。這些場景以兩個方面進行分隔:使用 HTTP/2 或 HTTP/1。在 HTTP/2 伺服器上,我們想測量 Server Push 在多個指標的效果。在 HTTP/1 伺服器上,我們想看看內聯資源的方法,在相同指標中對效能有什麼影響,因為內聯應該能達到和 Server Push 差不多的效果。具體場景如下:

  • 未使用 Server Push 的HTTP/2

網站使用了 HTTP/2 協議,但沒有資源是被推送的。

  • 僅推送 CSS 的 HTTP/2

使用了 Server Push,但僅用在了 CSS 資源。該網站的 CSS 體積比較小,經過 Brotli 壓縮後僅有2KB多一點。

  • 推送所有資源

網站的所有資源都是推送的。包括了上面的 CSS,以及6個JS(合計 1.4KB)、5個SVG圖片(合計5.9KB)。這些資源同樣經過了壓縮處理。

  • 未內聯資源的HTTP/1

網站只執行在 HTTP/1 上,沒有內聯任何資源,來減少請求數和加快渲染速度。

  • 只內聯 CSS

只有網站的 CSS 被內聯了。

  • 內聯所有資源

頁面上的所有資源都進行了內聯。CSS 和指令碼是普通內聯,而 SVG 圖片是經過 Base64 編碼方式直接放入 HTML 標籤中。值得一提的是 Base64 編碼後體積比原先大了1.37倍

在每個場景中,都使用下面的命令開始測試:

如果想知道這個命令的輸入、輸出,可以參看文件。簡而言之,這個命令測試了我的網站 https://jeremywagner.me 的主頁,使用了下面的條件:

  • 頁面中的連結無法抓取。只測試指定的頁面。
  • 頁面測試25次
  • 使用了“有線寬頻”級的網路配置。迴路時間(譯者注:RTT)為28ms,下行頻寬是5000kbps,上行頻寬為1000kbps。
  • 測試使用 Google Chrome

每項測試中收集和展示3項指標:

  • 首屏渲染時間

頁面在瀏覽器首次展現的時間點。當我們努力讓一個頁面“感覺上”載入很快,那麼這個指標是我們要儘量降低的。

  • DOMContentLoaded 時間

這個是 HTML 完成載入與解析的時間。同步的 JavaScript 程式碼會阻塞解析,並導致這個時間增加。在// <![CDATA[
標籤上使用 async 屬性可以避免對解析的阻塞。

  • 頁面載入時間

這個是整個頁面完成所有資源載入的耗時。

測試的所有因素都確定後,讓我們看看結果!

測試結果

經過對上述6種場景的測試,我們將結果以圖表形式做了展示。先看看各個場景的首屏渲染時間情況:

首屏渲染時間

首屏渲染時間(大圖

讓我們先講講圖表是如何設計的。圖中藍色部分代表了首屏渲染的平均時間,橙色部分是90%的情況,灰色部分代表了首屏渲染的最長耗時。

接下來我們討論結果。最慢的情形是未使用任何優化的 HTTP/2 和 HTTP/1。可以看到,對 CSS 使用 Server Push 使頁面渲染平均速度提升了8%,而內聯 CSS 也比簡單的 HTTP/1 提升了5%速度。

當我們儘可能地推送了所有資源,圖片卻顯示出了一些異樣,首屏渲染時間有所輕微增加。在 HTTP/1 中我們儘可能內聯所有資源,效能表現和推送所有資源差不多,僅僅少了一點時間。

結論很明確:使用 Server Push,我們能獲得比 HTTP/1 中使用內聯更優的效能。但隨著推送或內聯的資源增多,提升的效果逐漸減少。

使用 Server Push 或內聯雖好,但對於首次訪問的使用者並沒有太大價值(譯者注:實際上對於首次訪問使用者有很大的效能提升,猜測作者這裡寫錯了)。另外,這些測試實驗是執行在較少資源的站點上,所以未必能反映出你的網站的使用情況。

我們再看看各項測試對 DOMContentLoaded 時間的影響:

DOMContentLoaded 時間(大圖

資料趨勢跟剛才看到的圖表沒太大差別,除了一個需要注意的區別:在 HTTP/1 中儘可能地內聯資源,相對 DOMContentLoaded 時間非常低。可能的原因是內聯減少了需要下載的資源數,從而保證解析器(parser)可以不被打斷地工作。

最後再看看頁面載入時間的情況:

頁面載入時間(大圖

各項測量資料依然保持了先前的趨勢。僅推送 CSS 時載入時間最短。推送所有資源會偶爾導致服務遲緩,但畢竟還是比什麼都不做表現更優。與內聯相比,Server Push 的各項情況都是優於內聯的。

在做最後總結前,還要講講使用 Server Push 時可能遇到的“坑”。

使用 Server Push 的一些建議

Server Push 並不是效能優化的萬金油,它也有一些需要注意的地方。

推送過多資源

前面的一項測試中,我推送了很多資源,但它們加起來也只佔傳輸資料的一小部分。一次推送很多大資源的話,會造成頁面渲染及可互動時間的延遲,因為瀏覽器不但要載入 HTML 文件,還要同時下載推送的資源。最好的做法是有選擇性地推送,樣式表檔案是個不錯的開始(目前它們並不是很大),接著再評估還有什麼其他資源適合推送。

推送頁面以外的資源

如果你有訪客統計分析,那麼這種做法也未必不好。一個好的例子是,在多頁註冊賬戶表單場景,可以推送下一頁的註冊步驟資源。但要澄清的是,如果你不確定使用者是否會訪問後續的頁面,千萬不要嘗試推送它的資源。有些使用者的流量是十分珍貴的,這麼做可能會導致其不必的損失。

正確地配置 HTTP/2 服務

有些伺服器會給出很多 Server Push 的配置選項。Apache 的 mod_http2 模組有一些關於如何推送資源的配置選項。H2PushPriority 設定就比較有意思,雖然在我的伺服器上使用了預設設定。有一些實驗性的配置可以獲得額外的效能提升。每一種 Web伺服器都有其整套不同的實驗性配置,所以檢視你的伺服器手冊,看看有哪些配置可以用起來吧!

推送資源可能不被快取

Server Push 也有一些有損效能的的情況,對於訪問網站的回頭客們,一些資源可能會被非必要地進行推送。有些伺服器會盡可能地減輕這種影響。Apache 的 mod_http2 模組使用了 H2PushDiarySize 設定對這一點進行了一些優化。H2O 伺服器有一種 Server Push 快取感知特性,使用了 Cookie 機制來記錄推送行為。

如果你不是使用 H2O伺服器,也可以使用服務端程式碼實現同樣的效果,即只推送 Cookie 記錄外的資源。如果有興趣瞭解具體做法,可以檢視我在 CSS Tricks 上的文章。值得一提的是,瀏覽器可以向伺服器傳送一個 RST_STREAM 幀來通知不需推送的資源。隨著時間推移,這個問題的解決將會愈加優雅。

最後來總結一下以上學到的內容。

最後的思考

如果你已經將自己的網站遷移到 HTTP/2,你沒有什麼理由使用伺服器推送。如果你的網站因有過多的資源而顯得複雜,可以從體積較小的資源開始嘗試。一個好的經驗法則是,考慮推送那些你曾經用到內聯的資源。推送 CSS 是個不錯的開始。如果感覺更有冒險精神之後,就考慮推送其他資源。要牢記在改動後測試對效能的影響。下了一定功夫後,你一定能從中有所受益。

如果你沒有用像 H2O 這樣使用快取感知推送機制的伺服器,可以考慮用 cookie 追蹤你的使用者,只在沒有相關 cookie 的情況下給他們推送資源。這樣可以為未知使用者提升著效能的同時,最小化向已知使用者的資源推送量。這不僅利於效能優化,也向使用者展示了資料用量的尊重。

剩下的就需要你自己在伺服器上折騰 Server Push 了,看看有哪些特性可以對你或使用者有用吧。如果你想了解更多關於 Server Push,看看這些資源吧:

相關文章