當前位置:
首頁 > 知識 > HTTP/2 Server Push 詳解(上)

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 詳解(上)



使用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/2 Server Push 詳解(上)


內聯內容的伺服器通信


看起來是個不錯的方案,對吧?在 HTTP/1 的時代確實如此,因為也沒有別的選擇。這麼做實際上也留下了惡果,即內聯的內容不能有效地被緩存。當樣式、腳本資源以外鏈及模塊形式引用,會更高效地進行緩存。當用戶訪問後續頁面需要這些資源時,可以直接從緩存中獲取,從而省去了額外的資源請求。

HTTP/2 Server Push 詳解(上)



優化緩存行為


而當我們對內容進行內聯時,它們是沒有獨立的緩存上下文的,而存在於所內聯文檔的上下文中。舉個在 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