原文地址:HTTP/2 Prioritization
原文做者:[Patrick Meenan]
譯文出自:FE-star/speed
譯者:smallbonelunginx
以正確的順序請求頁面資源對於快速的用戶體驗相當重要。想象一下,若是一個網頁上有一堆圖片,還有一個外部樣式表,一些自定義Web字體和一些在head
中的腳本。若是瀏覽器首先下載了全部圖片而且最後加載了樣式表,在全部內容都加載完畢前,頁面將徹底是空白頁。若是瀏覽器首先加載了全部阻塞資源,接着是Web字體和圖片,那麼它能夠更早地呈現頁面,並讓用戶開始看到內容,同時加載其他的圖片。我在Chrome瀏覽器性能工做上的大部分時間都花在了嘗試優化加載資源的順序以得到最佳用戶體驗上。git
使用HTTP/1.x
,瀏覽器能夠徹底控制資源加載順序。每一個鏈接一次只能支持一個資源請求,服務器會盡快返回請求的內容。瀏覽器能夠經過決定什麼時候請求資源以及打開多少個並行鏈接來安排請求。github
HTTP/2
讓這些事情變得更好也更復雜了。瀏覽器能夠一次請求多個資源,指定一些優先級信息來幫助肯定應該如何處理這些資源,而後等待服務器發回全部數據,而不是一次請求一個。若是瀏覽器和服務器都支持優先級,則應使用瀏覽器指定的規則並使用全部可用帶寬來傳遞資源,而不會有資源之間的相互競爭。web
每一個資源都獲取一個stream ID
來標識鏈接上的資源,而且有三個參數用於定義資源優先級:算法
root stream 0
。瀏覽器不必定同時知道全部資源,所以服務器可以在新請求到達時從新肯定請求的優先級也很關鍵。瀏覽器
那麼......咱們是怎麼作的呢?安全
這包括使用Chromium的優先級邏輯和網絡堆棧的全部內容。服務器
Chrome是惟一使用獨佔位的瀏覽器,它在每一個資源上使用它。它構建了一長串資源,將較低優先級的資源連接到仍在等待的最後一個相同或更高優先級的資源。若是沒有更高優先級的資源掛起,則啓動新鏈。權重以靜態映射的方式分配,Chrome的五個內部優先級分別對應相應的權重(即HIGHEST爲256)。網絡
假設給定幾個請求隊列,全部請求都設置了獨佔位,服務器將選擇權重最高的一個,完成傳遞後,就將其從列表中彈出並從新選擇。架構
假設Chrome正確構建了排序,這可能很是有效。獨佔下載資源是樣式表和腳本等阻塞資源的最佳選擇。當涉及到圖片和視頻時,你可能須要一些交錯執行的任務(特別是對於漸進式圖片)。不然,在轉到下一個請求前,你將要等待每一個圖片或視頻徹底下載下來。
Firefox實現了HTTP/2
的樹結構,並構建了一個虛擬的數據流樹,用來對不一樣請求類型進行分組。Firefox對分組進行了加權,以便爲更重要的組提供更多的帶寬,而且當全部節點都已完成時,空閒週期(idle cycles)可用於響應。
在根級別中,有一個「leader」組,,它的帶寬是「Other group」的兩倍。在「leader」組中,有一個叫「follower」的子組,它只有在「leader」組的直系後代完成下載後纔會開始下載。例如,在權重爲200的「leader」組下面,一旦全部CSS完成下載後,圖片和字體纔會開始下載。一個組內的全部子資源具備相同的權重並均勻分配帶寬(同時下載全部圖片或全部腳本)。
從總體結構上來看Firefox很是出色,能夠爲推測請求定義空閒週期,但對同時下載全部資源優先級的劃分並非很好。像樣式表和腳本等這樣的阻塞資源的優先下載要比按順序下載它們才能讓解析器處理文檔要好。
這包括iOS上的全部瀏覽器(包括Chrome)。
Safari採用了一種很是簡單的方法,看起來是SPDY優先級的遺留部分。五個內部webkit優先級靜態映射到權重,而且沒有定義依賴關係。全部請求基於每一個資源的優先級來劃分帶寬權重進行同時下載(例如,腳本得到圖片帶寬的三倍)。
這樣致使高併發性並非很好,並且落後於Firefox的實現,在Firefox中至少follower組的資源會等到leader組資源所有完成任務以後(儘管它可能不足以證實Firefox中樹的複雜性)。
簡而言之,Microsoft Edge(和Internet Explorer)根本不支持優先級。全部請求均勻分配帶寬(幾乎是最糟糕的狀況)。
如今大多數服務器都支持HTTP/2
了,一般也"支持"優先級的。支持加了引號,是由於即便一個服務器內部支持資源優先級,實際上讓它可以與瀏覽器工做也須要調整網絡堆棧並儘量減小輸出緩衝而不影響吞吐量。
緩衝多是一個問題,由於服務器能夠發送一堆低優先級的響應,這些響應在高優先級響應到來以前已經在緩衝區中排隊。發送高優先級響應時,沒法搶佔已緩衝的低優先級響應。緩衝能夠來自服務器自己,TLS層,TCP發送的緩衝,甚至來自網絡上的bufferbloat,跟蹤並消除全部多餘的緩衝可能會很複雜。我在今年早些時候的一篇博文中談到了一些緣由和解決方案,但這並非一個詳盡的清單。
爲了測試服務器優先級的有效性,我構建了一個測試頁面,你能夠在你的服務堆棧上部署該測試頁面以查看優先級是否正常工做。它專門針對Chrome的優先級邏輯,所以最好使用慢速鏈接上的Chrome進行測試。它先將3MB低優先級圖片排隊,而後在下載並執行高優先級腳本後,腳本會發送4個高優先級請求(一張圖片,一個頁面背景,一個自定義的webfont和一個阻塞腳本)。當優先級正常工做時,後置的高優先級請求的資源會跳太低優先級請求並快速獲得響應:
當優先級工做不正常時,部分或所有後置的高優先級請求的資源會被延遲,直到優先級較低的請求完成爲止:
後置請求的阻塞腳本的延遲超出了「DOM Content Loaded」的度量值,字體和2個圖片的延遲對視覺體驗產生了至關大的影響:
爲了跟蹤CDN和託管服務提供商支持HTTP/2
優先級的程度,Andy Davies建立了一個GitHub倉庫,用於跟蹤當前的支持情況,任何人均可以提交測試結果來羣策羣力。在撰寫本文時,狀況很是糟糕,只有兩個CDN確實正確地肯定了優先級,而且存在一些很是使人震驚的失敗(例如每一個雲提供商甚至Google的GFE)。但願經過提升對這種狀況的認知,咱們將可以爲優先級提供更普遍的支持。
對託管和服務器來講,好消息是你老是能夠在它們以前配置一個支持優先級的CDN來解決問題(儘管直接支持它會很好)。
在瀏覽器方面,除了敦促瀏覽器廠商以得到更好的支持以外,沒有太多能夠作的事情。其中的一些廠商可能會遇到架構問題,如他們的瀏覽器引擎在操做系統的網絡堆棧層之上,致使沒法傳遞優先級信息。多是個人偏見,但我認爲Chrome是最接近「正確」的作法,但仍有至關大的改進空間。
HTTP/3
也即將到來,但目前的優先級方案不會改變。這個改變是網絡堆棧的終結。在服務器端,這意味着操做系統的緩衝和擁塞控制再也不起做用,服務器軟件100%負責最小化緩衝(包括擁塞控制算法以最小化緩衝區)。
那麼就說到這裏,但願爲了HTTP/2
和一個安全,高性能的網絡,咱們能夠在2019年修復資源優先級。