Cloudflare的HTTP/2优化策略
Cloudflare針對HTTP/2優先級的進一步優化,將網頁控制權盡可能地交給網站所有者,可根據具體需求與場景,定制化網頁加載優先級策略,提供更快速,更優質的用戶Web訪問與交互體驗。
文 / Patrick Meenan
譯 / John
原文?
https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/
HTTP/2意味著更快的網頁加載速度,而Cloudflare在很久之前也為所有客戶提供了HTTP/2訪問服務。但是其中HTTP/2的一項特性——加載優先級,并沒有達到預期的效果。事實上優先級特性本身并沒有什么問題, 真正地問題在于瀏覽器中優先級特性的實現方式。
現在,Cloudflare推出了對于HTTP/2優先級的優化升級,也就是讓我們的服務器有能力控制優先級策略從而真正提高網頁的加載速度。在此之前,瀏覽器已經能夠控制并決定加載網頁內容的方式與時長。而現在我們希望能通過對優先級模型進行升級,將網頁控制權盡可能地交給網站所有者。客戶可以在Cloudflare儀表板的“Speed”選項卡中啟用“增強HTTP/2優先級”——將升級的調度方案覆蓋至瀏覽器默認設置從而顯著提升網頁訪問體驗(根據多個場景下的測試,我們發現性能普遍提升達50%)。借助Cloudflare Workers,網站所有者可以根據需求進一步定制用戶的網頁瀏覽體驗。
背景
Web頁面一般由數十個甚至數百個單獨的資源組成,瀏覽器將這些資源加載并組裝成最終顯示的內容。這包括用戶與之交互的可見內容(HTML、CSS、圖像)以及網站本身的應用程序邏輯(JavaScript)、廣告、跟蹤網站使用情況的數據分析與營銷跟蹤信標等。根據何種優先級策略對這些資源的加載過程進行排序,直接決定用戶等待網頁加載所需要的時間以及查看網頁內容并與其進行交互的體驗。
瀏覽器本質上是一個HTML處理引擎,每當加載一個網頁時,瀏覽器會遍歷HTML文檔并遵循指示,按照從HTML開始到結束的順序構建頁面;與此同時,瀏覽器也會引用層疊樣式表(CSS)從而獲悉并設置頁面內容的樣式;一些情況下,為了明確設置要顯示的內容樣式,瀏覽器會延遲顯示網頁內容直到層疊樣式表被加載完成。文檔中引用的腳本可能有以下幾種不同的行為:如果腳本被標記為“異步”或“延遲”,則瀏覽器可以繼續處理文檔并在腳本可用時運行腳本代碼;如果腳本沒有被標記為“異步”或“延遲”,則瀏覽器必須停止處理文檔,直到腳本下載完成并被執行才會繼續處理文檔,這些沒有被標記的腳步被稱為“阻塞”腳本——顧名思義,“阻塞”腳本阻止瀏覽器繼續處理文檔直到其被加載和執行。
HTML文檔分為兩部分:<head>文檔的開頭部分包含顯示內容所需的瀏覽器樣式表、腳本和其他說明;<body>文檔位于頭部文件之后,包含瀏覽器窗口中顯示的實際頁面內容(腳本和樣式表也被包含在其中)。在瀏覽器訪問至文檔正文也就是<body>之前,網頁不會向用戶顯示任何內容,頁面將保持空白。因此,瀏覽器需要盡可能快地加載頭部文件。
在處理文檔的同時,通常瀏覽器也負責確定以什么樣的順序加載構建頁面所需的不同資源。在HTTP/1.x的情況下,瀏覽器單次從任一服務器端所請求的內容量被限制(通常是6個連接,每個連接一次只能請求一個資源),所以資源的加載順序是由瀏覽器通過請求的方式嚴格控制的。而對于HTTP/2,情況發生了很大的變化,瀏覽器可以一次請求所有的資源(至少了解有多少資源等待被加載),從而便于其向服務器提供有關資源傳輸的詳細說明。
最優資源排序
大多數瀏覽器在加載頁面的過程中存在最佳的加載資源優先級策略,其直接促成了良好的用戶體驗;同時最佳策略與非最佳策略所造成的網頁加載耗時可能存在高達50%的差異。
如上所述,在瀏覽器呈現全部網頁內容之前的頁面加載時期,會在CSS上被阻止并阻止HTML的<head>部分中的JavaScript;所以在這一期間最好使用全部連接帶寬以充分下載被阻塞的資源,并按照HTML定義的順序一次下載一個資源以便于瀏覽器在下載下一個阻塞資源時可同時解析并執行上一個項目,實現下載和執行的流水線化操作。
?
傳統的并行下載或依次下載所需要的下載時間相同,而如果按照順序下載并在第二個腳本下載時執行第一個腳本,那么這會明顯縮短網頁資源的加載時間。
一旦加載渲染項阻止內容,最佳加載狀態可能取決于特定網站甚至業務優先級情況(如用戶內容與廣告分析對提供商而言的權重)。其中尤為重要的一項的是字體,瀏覽器僅在將樣式表應用于即將顯示的網頁內容之后才會確認所加載字體。因而當瀏覽器確認所加載字體前,現存的即將被顯示在網頁上的文本就應當被準備完畢。獲取字體過程所發生的任何延遲最終都會導致屏幕上顯示空白文本或以錯誤字體顯示文本。
為確保網頁加載的正常,我們應當權衡以下內容:
應盡快加載頁面可見部分中的自定義字體與圖像——這直接關乎頁面加載時期的用戶視覺體驗。
非阻塞JavaScript相對于其他JavaScript資源應當以串行方式下載,同時每個JavaScript都以流水線形式加載。JavaScript可能包括面向用戶的應用程序邏輯、用戶行為分析與營銷跟蹤信標,一旦出現延遲即可導致業務跟蹤指標的下降。
借并行下載可實現更好的圖像加載效果。圖像文件的前幾個字節包含瀏覽器頁面布局所需要的圖像尺寸,并行的逐行圖像下載允許在瀏覽器僅接收原始數據的50%基礎之上優先完成視覺上的圖像加載。
權衡以上內容,我們可得出以下可達到良好運作狀態的策略:
按順序策略下載自定義字體,并使用可見圖像分割可用帶寬。
按并行策略下載圖像,切割“圖像”以便于按照所分配的帶寬逐行加載圖像。
當沒有更多等待被處理的字體或圖像時:
非阻塞腳本按順序下載,并使用不可見的圖像分割可用帶寬。
按并行策略下載不可見圖像,切割“圖像”以便于按照所分配的帶寬逐行加載圖像。
通過采取以上策略,我們希望瀏覽器能夠盡可能快地加載用戶可見的網頁內容,盡可能減少應用程序邏輯所造成的延遲,并以盡可能短的時間完成網頁布局與不可見圖像的加載。
實際案例
為了便于說明,我們將以電子商務網站的簡化產品類別頁面作為典型案例,其中頁面具有以下加載項:
?頁面本身的HTML文件,使用藍色框表示。
?1個外部樣式表(CSS文件),使用綠色框表示。
?4個外部腳本(JavaScript),使用橙色框表示。其中2個在頁面開頭處的腳本為阻塞腳本,使用較暗的橙色陰影框表示;除此之外還有2個異步腳本。
?1個自定義Web字體,使用紅色框表示。?
?13個圖像,使用紫色框表示。頁面徽標和4個產品圖像在視口中可見,使用較深的紫色框表示;8個產品圖像需要滾動頁面才能看到。
為簡單起見,我們假設以上所有資源的大小相同,每個資源在訪問端需要1秒時間連接與下載,加載所有資源總共需要20秒,這里我們主要研究采用不同的加載方式會對用戶瀏覽網頁的體驗帶來什么影響。
?
這就是我所描述的采用“最佳加載策略”加載資源時,瀏覽器所呈現出的效果:
啟用全部連接,加載HTML、CSS和阻止腳本的前4秒內,頁面為空白。
第4秒,頁面僅顯示了背景與結構卻未顯示文本與圖像。
第5秒,頁面文本被成功顯示。
5~10秒,圖像逐漸被加載;開始時圖像模糊,隨后圖像被快速銳化;第7秒時瀏覽器幾乎完成了全部圖像加載
第10秒,視覺窗口中的所有可視化內容都已加載完畢。
10~12秒,異步JavaScript被加載與執行,隨后包括數據分析、營銷信標在內的其他所有非關鍵邏輯被加載與執行。
12~20秒,其他的產品圖像開始被加載以便為用戶接下來可能的網頁滾動行為做好準備。
常見瀏覽器的優先級策略
常見的幾個瀏覽器引擎都采取了不同的優先級策略,耐人尋味的是其中沒有一個符合“最佳優先級加載策略”的要求。
1)Microsoft Edge和Internet Explorer
Microsoft Edge和Internet Explorer 不支持加載項的優先級排序,因而所有內容的加載方式都基于HTTP/2的默認設置,即并行加載所有內容并為所有內容均勻分配帶寬。預計在未來,采用Chromium引擎的新版Microsoft Edge會在此方面迎來極大改善。而在我們的示例頁面中,并行加載與均勻帶寬分配意味著瀏覽器的絕大部分加載過程都停留在頭部文件之上,而圖像等資源則會減慢阻塞腳本與樣式表的傳輸速度。
在大多數內容被成功顯示之前,用戶視覺會在長達19秒的時間內不得不停留在空白頁面,隨后經歷1秒的文本顯示延遲才能看到網頁所有元素。這就意味著用戶使用IE內核的瀏覽器觀看動畫時需要耐心等待頁面元素全部加載完成,這無疑是對用戶瀏覽網頁體驗的巨大影響。
2)Safari
Safari 同樣采取并行策略加載所有資源,但Safari會根據不同資源的重要程度為其劃分合適且足夠的帶寬(例如:渲染腳本和樣式表等阻塞資源比渲染圖像更為重要);而圖像雖采用并行加載的策略,但其也與阻塞渲染資源同時被加載。
雖然采用了與Edge類似的并行加載策略,但Safari通過為阻塞渲染資源分配更多帶寬,實現更快的網頁加載過程:
加載開始后的約8秒,樣式表和腳本已加載完畢,因而頁面開始被顯示;由于圖像采用并行加載策略,在此期間只有部分圖像被加載(相對于采用逐行加載策略的圖像而言更加模糊),但加載效果要遠勝于IE與Edge瀏覽器。
約第11秒,字體已加載完畢,文本正常顯示的同時有更多帶寬被投入圖像數據的加載當中,這讓圖像的清晰程度進一步提升,這樣的水平已經接近于采用“最佳加載策略”的第7秒加載效果。
接下來的9秒當中,隨著完成下載的數據進一步增多,圖像變得愈發清晰,直到第20秒完成全部加載活動。
3)Firefox
Firefox構建一個依賴關系樹,該樹將資源分組并安排這些組采取依次加載或組之間共享帶寬的形式進行加載。在給定組內,資源在共享帶寬的同時被下載;而那些圖像則被計劃在阻塞渲染資源之后,采用并行策略的方式進行加載,但阻塞渲染腳本和樣式表也會被并行加載,這樣便無法從流水化操作中獲得顯著的性能提升。
在我們的示例中,由于圖像加載過程被推遲到樣式表加載完成之后,因而最終的實際加載過程會略快于Safari。
第6秒,背景與產品圖像的模糊版本構成了網頁的大致內容。其整體觀感和Safari在第8秒時的加載效果與采用“最佳加載策略”瀏覽器的第4秒加載效果相似。?
第8秒,字體已加載完畢,文本正常顯示的同時圖片愈發清晰(其與Safari在第11秒時的加載效果與采用“最佳加載策略”瀏覽器的第7秒加載效果相似)。
剩余的12秒內,產品圖像逐漸變得更加清晰。
4)Chrome
Chrome以及所有基于Chromium內核的瀏覽器會將資源按照一定優先級順序排序至待加載列表中,這對于阻塞渲染資源來說非常有效;按順序加載策略為這些資源的加載過程所帶來的好處不言而喻,但其頁面中的圖像在開始下一張圖像之前需要加載至100%才可成功顯示。
在實際測試中,Chrome的加載效果幾乎與采用“最佳加載策略”的瀏覽器相同,唯一的區別是Chrome的圖像采用按順序加載的方式一次性加載完畢而非并行加載:
前5秒,Chrome體驗與采用“最佳加載策略”的瀏覽器相同——前4秒背景加載完畢,第5秒文本加載完畢。
5~10秒,可見圖像被依次下載直到第10秒時全部圖像加載完畢(與采用“最佳加載策略”的瀏覽器相比,Chrome在第7秒時,其圖像稍微模糊但在隨后的3秒內被快速銳化)。
10秒后,頁面的可視部分資源加載完畢(此成績與采用“最佳加載策略”的瀏覽器相同),接下來的10秒則會被用于運行異步腳本并加載隱藏圖像(此策略與采用“最佳加載策略”的瀏覽器相同)
視覺比較
上述瀏覽器的不同加載策略所體現出的視覺差異可能會十分明顯,即使這些瀏覽器廠商都花費了足夠多的時間與技術來優化頁面資源加載過程:
服務器端的優先級
客戶端(瀏覽器)請求HTTP/2優先級排序策略,隨后由服務器根據請求決定接下來做什么。很多服務器根本不支持使用優先級做任何事情,但是對于那些支持優先級的服務器,它們都尊重客戶端的請求。我們可以通過考慮客戶端的請求來決定在服務器端使用何種最佳優先級。
根據規范,HTTP/2優先級可以看作是一個依賴樹,此依賴樹需要完全掌握所有正在進行的請求以便能夠考慮到所有資源的加載狀況并優先決定關鍵資源的加載。由于不同的瀏覽器具有不同的加載策略,而不同層級的服務器各有差異,這種十分復雜的優先級策略很難在瀏覽器端被輕易實現。為了便于優先級的管理,我們開發了一種更簡單的優先級排序方案,該方案具有優化調度所需優先級的靈活性。
Cloudflare優先級排序方案由64個優先級“級別”組成,在每個優先級內,一組資源可確定如何在不同優先級之間共享連接:
在進入下一個較低優先級之前,瀏覽器會轉移所有較高優先級的資源。
在給定的優先級內,有3個不同的“并發”組:
0:并發“0”組中的所有資源按照請求的順序使用100%的帶寬依次發送。只有所有并發“0”組的資源被下載完成之后,瀏覽器才會考慮同一級別的其他組。
1:并發“1”組中的所有資源按請求順序依次發送。可用帶寬在并發“1”組和并發“n”組之間均勻分配。
n:并發“n”組中的資源是按照每個資源所分配的帶寬資源并行發送。
實際上,并發“0”組對于需按順序處理的關鍵內容(腳本,CSS等)而言非常有用;并發“1”組對于不太重要的內容而言非常有用,因為這些內容可以與其他資源共享帶寬,但資源本身仍可以從順序處理(異步腳本,非漸進式圖像等)中受益;并發“n”組對于依賴并行處理(漸進式圖像,視頻,音頻等)的資源而言非常有用。
Cloudflare默認優先級
啟用Cloudflare時,增強的優先級排序可實現上述資源的“最佳”調度。應用的特定優先級如下所示:
?
該優先化方案允許串行發送并呈現阻塞內容,隨后并行發送可見圖像。接下來通過某種程度的共享,覆蓋頁面內容的其余部分以平衡應用程序和內容加載。這里的“*If Detectable”警告是說,并非所有瀏覽器都區分不同類型的樣式表和腳本,但這不影響瀏覽器的加載速度。默認情況下Cloudflare會比其他瀏覽器,特別是Edge和Safari快50%。
?
人為可控的自定義優先級
盡管在默認情況下Cloudflare可實現更快加載速度,但真正有趣的是配置優先級的能力也向Cloudflare Workers公開,這樣站點就可以覆蓋資源的默認優先級,或者實現它們自己的完整優先級計劃。
如果工作人員為響應添加“cf-priority”標頭,則Cloudflare邊緣服務器將使用指定的優先級和并發響應。標頭的格式<priority>/<concurrency>就像response.headers.set('cf-priority', “30/0”);將給定響應的并發度為0的優先級設置為30。類似地,將“30/1”并發設置為1,將“30 / n”并發設置為n。
借助上述靈活性舉措,站點可以調整資源優先級以滿足其多樣化需求。例如,當瀏覽器識別出用戶正在閱讀某一網頁時,用戶的視覺重心位于當前網頁之上;而如果我們想要提升下一頁的觀感,那么我們可以嘗試提升某些關鍵異步腳本的優先級或增加關鍵圖像加載的優先級。
為了幫助通知任何優先級決策,Workers運行時還在傳遞給Worker的fetch事件偵聽器(request.cf. requestpriority)的請求對象中公開瀏覽器請求的優先級信息。傳入的請求優先級是以分號分隔的屬性列表,其類似于:
weight:HTTP/2優先級的瀏覽器請求權重。
exclusive:瀏覽器請求的HTTP/2獨占標志(基于Chromium的瀏覽器為1,其他為0)。
group:請求組的HTTP/2流ID(Firefox僅為非零)。
group-weight:請求組的HTTP/2權重(Firefox僅為非零)。
這僅僅是個開始
瀏覽器調整和控制響應優先級的能力可以讓許多未來相關項目從中受益。而我們則是在此基礎之上加入了獨創的高級優化——也就是讓整個優先級排序過程暴露給開發者以便于開發者基于網站其他研究人員的參考信息嘗試不同的優先級策略。通過Apps Marketplace,我們還在Workers平臺之上構建新的優化服務,并使其可供其他站點使用。
LiveVideoStack? 招募
LiveVideoStack正在招募編輯/記者/運營,與全球頂尖多媒及技術專家和LiveVideoStack年輕的伙伴一起,推動多媒體技術生態發展。了解崗位信息請在BOSS直聘上搜索“LiveVideoStack”,或通過微信“Tony_Bao_”與主編包研交流。
LiveVideoStackCon 2019北京正在招募講師,無論你是技術派還是學術派,亦或是行業專家,無論你的團隊有多小、有多新,都可以來申請成為LiveVideoStackCon的講師。點擊【閱讀原文】了解更多大會相關信息。
總結
以上是生活随笔為你收集整理的Cloudflare的HTTP/2优化策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Twitch未来五年的视频编码战略:从H
- 下一篇: LiveVideoStack线上分享第三