HTTP/2 Server Push 詳解(上)
作者:Jeremy Wagner
譯者:Johnny
原文:www.alloyteam.com/2017/04/guide-http2-server-push-part1/
網路優化一直是譯者長期研究的方向,HTTP/2 的理論學習也已做了不少,隨著這項標準的推進,越來越多特性被大家開始使用。作為 HTTP/2 最激動人心的特性,Server Push 在性能提升的效果被寄予了很高期望,卻因其對傳統 B/S 架構的開發模式影響較大未能廣泛實踐。如何更好地使用這項能力,讓我們跟著作者深入探索~
======= 譯文分割線 =======
在過去的一年時間,HTTP/2 的出現為關注性能的開發者帶來了顯著的變化。HTTP/2 已經不再是我們期待中的特性,而是伴著 Server Push(服務端推送)能力已然到來。
除了解決常見的 HTTP/1 性能問題(比如,首部阻塞和未壓縮的報頭),HTTP/2 還提供了 Server Push 能力!服務端推送允許我們向用戶發送一些還沒有被訪問的資源。這是一種獲得 HTTP/1 優化實踐(例如內聯)所帶來性能提升的優雅方式,同時也避免了原先實踐的一些缺點。
本文中,你將了解什麼是 Server Push,它的工作原理與解決了哪些問題。同時你也將學習如何使用它,判斷它是否正常運作,以及它對性能的影響。讓我們開始吧!
Server Push 為何物
訪問網站始終遵循著請求——響應模式。用戶將請求發送到遠程伺服器,在一些延遲後,伺服器會響應被請求的內容。
對網路伺服器的初始請求通常是一個 HTML 文檔。在這種情況下,伺服器會用所請求的 HTML 資源進行響應。接著瀏覽器開始對 HTML 進行解析,過程中識別其他資源的引用,例如樣式表、腳本和圖片。緊接著,瀏覽器對這些資源分別發起獨立的請求,等待伺服器返回。
典型的伺服器通信
這一機制的問題在於,它迫使用戶等待這樣一個過程:直到一個 HTML 文檔下載完畢後,瀏覽器才能發現和獲取頁面的關鍵資源。從而延緩了頁面渲染,拉長了頁面載入時間。
有了 Server Push,就有了解決上述問題的方案。Server Push 能讓伺服器在用戶沒有明確詢問下,搶先地「推送」一些網站資源給客戶端。只要正確地使用,我們可以根據用戶正在訪問的頁面,給用戶發送一些即將被使用的資源。
比如說你有一個網站,所有的頁面都會在一個名為 styles.css 的外部樣式表中,定義各種樣式。當用戶向務器請求 index.html 時,我們可以向用戶推送 styles.css,同時我們發送 index.html。
使用HTTP/2 Server Push的Web伺服器通信
相比等待伺服器發送 index.html,然後等待瀏覽器請求並接收 styles.css,用戶只需等待伺服器的響應,就可在初次請求同時使用 index.html 和 styles.css。
可以想像,這可以降低一個頁面的渲染時間。它還解決了一些其他問題,特別是在前端開發工作流方面。
Server Push 解決了什麼問題?
Server Push 解決了減少關鍵內容網路迴路的耗時問題,但這並不是唯一作用。Server Push 更像是 HTTP/1 特定優化反模式的替代方案,例如將 CSS 和 JavaScript 內聯在 HTML,以及使用 data URI 方案將二進位數據嵌入到 CSS 和 HTML 中。
這些技術在 HTTP/1 優化工作流中非常受用,是因為這樣減少了我們所說的頁面「感知渲染時間」,也就是說在頁面整體載入時間可能不會減少的同時,對用戶而言網頁的載入速度卻顯得更快。這確實是說得通的,如果你將 CSS 內嵌到 HTML 的標籤中,瀏覽器就可以無需等待外部資源的獲取,而立即應用 HTML 中的樣式。這種概念同樣適用於內聯腳本,以及使用 data URL 方式內聯二進位數據。
內聯內容的伺服器通信
看起來是個不錯的方案,對吧?在 HTTP/1 的時代確實如此,因為也沒有別的選擇。這麼做實際上也留下了惡果,即內聯的內容不能有效地被緩存。當樣式、腳本資源以外鏈及模塊形式引用,會更高效地進行緩存。當用戶訪問後續頁面需要這些資源時,可以直接從緩存中獲取,從而省去了額外的資源請求。
優化緩存行為
而當我們對內容進行內聯時,它們是沒有獨立的緩存上下文的,而存在於所內聯文檔的上下文中。舉個在 HTML 中內聯 CSS 的例子,如果 HTML 的緩存策略,是每次訪問都向伺服器拉取最新的內容,那麼內聯的CSS總是無法緩存其內容。即使把 HTML 進行緩存,但在後續訪問的頁面內,內聯相同的 CSS 內容也是需要重複下載的。這還是比較寬鬆的緩存策略,實際情況中 HTML 僅有較短的緩存周期。內聯是我們在 HTTP/1 優化方案中所做的權衡,它確實在用戶第一次訪問時非常有效,而往往第一印象是非常重要的。
這就是 Server Push 能解決的問題。當推送資源時,我們能獲得與內聯相同的性能提升,同時保持資源的外鏈形式,從而有獨立的緩存策略。這裡有個需要注意的問題,我們稍後再深入探討。
我已經談了很多為什麼你該考慮使用 Server Push 的原因,也澄明了它能為用戶和開發者所解決的問題。接下來讓我告訴你如何去使用它。
如何使用 Server Push
使用Server Push,通常會以下面的方式使用 Link 這個HTTP首部。
注意我說的是通常,上面看到的實際是預載入資源示意(resource hint)的實踐。這是個區別於Server Push的獨立優化方案,但大多數(並非全部)HTTP/2的實現都將 preload 放進來 Link 首部。如果伺服器或客戶端選擇不接受推送的資源,客戶端仍可以根據指示提早獲取資源。
首部中 as=style 部分是必選的,它能告知瀏覽器推送資源的類型。在這個例子中,我們使用 style 來指明推送的資源是一個樣式表,你還可以設置其他的內容類型。值得注意的是如果省略了 as 的值,會導致瀏覽器對推送資源下載兩次,所以千萬別忘了它。
現在知道推送資源的方法了,但具體要怎樣設置 Link 首部呢?我們有兩種方式:
Web伺服器配置(例如,Apache httpd.conf 或.htaccess);
後端語言功能(例如PHP的 header 方法)。
使用伺服器配置設置 Link 首部
下面是一個 Apache 配置(通過httpd.conf或.htaccess)的例子,作用是在請求 HTML 時推送樣式資源。
這裡我們使用了 FilesMatch 指令來匹配後綴為「.html」的文件請求。當一個請求匹配這個條件時,我們就往響應頭裡加入 Link 首部,並告知伺服器推送位置在 /css/styles.css的資源。
邊註:Apache 的 HTTP/2 模塊也可以使用 H2PushResource 指令啟用資源推送。該指令的文檔指出,這種方法能夠早於 Link 首部方法啟用推送。根據Apache安裝時的不同設置,你也可能無法使用此功能。本文後面會給出 Link 首部方法的性能測試結果。
截至目前,Nginx 並不支持 HTTP/2 Server Push,目前的 changelog 中沒有任何支持情況的記錄。而隨著 Nginx HTTP/2 實現的逐漸成熟,這種情況可能會發生變化。
使用後端代碼設置 Link 首部
另一個設置 Link 首部的方法是使用伺服器端語言。這在你無法修改或覆蓋伺服器配置時十分有效。下面是 PHP header 方法設置 Link 首部的例子:
如果你的應用程序部署在一個共享的託管環境中,並且修改伺服器的配置不太現實,那麼這個方法可能是最適合你的。你可以使用任何服務端語言設置這個首部。在真實使用前記得確保測試無誤,以避免潛在的運行時錯誤。
多資源推送
目前看到的都是演示推送一個資源的例子,如果想一次推送更多資源呢?這麼做也是很有道理的,對吧?畢竟頁面不止是樣式表組成的。下面來看推送多資源的例子:
當你想推送多個資源,只要用逗號把每個指令隔開就行了。因為資源示意是通過 Link 首部加入的,這種語法讓我們可以把不同資源的推送指令合在一起。這還有個包括 preconnect 的混合推送指令示例:
多個 Link 首部也是同樣合法的。下面是 Apache 給 HTML 配置多個 Link 首部的例子:
這種語法相比一長串逗號分隔的字元串更為方便,且達到的作用是相同的。唯一的缺點就是沒那麼緊湊,而且會多一點位元組量的網路傳輸,但提供的便利是值得的。
現在知道了如何推送資源,在本文下半部分,我們繼續看推送是否生效,且表現性能如何。
在微信公眾號內回複數字「1」
小編拉你進粉絲微信群
不是在文章評論里回復
※分布式系統常見的事務處理機制
※你是「空巢程序員」嗎?
※做程序員,不做碼農,有哪些好辦法?
※程序員常用的技術網站
※每個程序猿應該閱讀的10本經典書籍
TAG:程序員之家 |
※如何在 Firefox 中啟用 DNS-over-HTTPS(DoH)
※Mozilla在Firefox中測試DNS over HTTPS
※Mozilla 測試 DNS over HTTPs
※HTTP / 3用UDP替換TCP以提高網路速度和可靠性-thenewstack
※Apache HTTP Server v2.4.33穩定版發布
※雪上加霜,Firefox要求AppCache使用HTTPS
※Nginx Configuration 免費HTTPS加密證書
※HTTP 的content-type
※修復.NET的HttpClient
※Firefox 62將使用DNS over HTTPS技術終結DNS查找明碼風險
※Servlet HTTP 狀態碼
※為什麼Fastly喜歡QUIC和HTTP/3
※使用HTTPS Everywhere插件,默認HTTPS加密訪問網站
※Apache HTTPD 2.4.38 Stable 發布
※Nginx+Koa 開啟http/2 server push
※Servlet 客戶端 HTTP 請求
※EFF為HTTPS Everywhere推持續性規則集更新!
※request,ProxyHandle與HttpCookiProcessor函數用法
※濫用HTTPS站點隱藏的/.well-known/目錄傳播惡意軟體
※高性能的 PHP 封裝的 HTTP Restful 多線程並發請求庫-MultiHttp