高性能浏览器-HTTP 2.0
生活随笔
收集整理的這篇文章主要介紹了
高性能浏览器-HTTP 2.0
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
HTTP 2.0 將會使應用程序更快、更簡單、并且更健壯。HTTP 2.0的首要目標通過請求-響應多路復用,報頭壓縮,優先級控制、服務器推送來減少延時。為了達到這個目的,HTTP 2.0需要支持大量的路I量控制、錯誤異常處理以及協議升級機制。
HTTP 2.0 沒有改變http1.x中methods,?status?codes,?URIs, header?fields這些元數據的語義。但是改變這些數據的傳輸方式。
HTTP 2.0 發展歷史以及與SPDY關系
spdy 是google 在2009年中開發的實驗性的協議,旨在通過解決HTTP 1.1中一些性能限制以降低網頁的加載時間,它的大概要達到的目標有:
提出該協議后沒多久,很快谷歌就公布是SPDY實驗結果以及源碼; 2012年,包括chrome,firefox opera等其他站點都以及支持了SPDY;同年,HTTP?Working?Group已經準備將SPDY吸收到HTTP 2.0的官方標準中,之后HTTP-WG提出多次草案: ??March?2012:?Call?for?proposals?for?HTTP?2.0 ??September?2012:?First?draft?of?HTTP?2.0 ??July?2013:?First?implementation?draft?of?HTTP?2.0 ??April?2014:?Working?Group?last?call?for?HTTP?2.0 ??November?2014:?Submit?HTTP?2.0?to?IESG?as?a?Proposed?Standard
設計和技術標準:
二進制幀: HTTP2 性能提升的核心是全新的二進制幀分層,客戶端和服務端必須使用新的二進制編碼方式同對端通信,下圖描述了http消息在客戶端和服務端間如何分裝和傳輸: 二進制幀層只設計在socket收發層和HTTP層之間, 對http原來的語義,比如verbs,method和報頭沒有影響,但是在傳輸過程的編碼方式不同,比如http1.x中使用的換行符,在http2通信中則被拆成更小的二進制消息和幀;
流,消息和幀 流: 一個tcp連接內的雙向字節流;
消息: 一個對應著邏輯消息的完整的 一系列幀;
幀: HTTP 2.0 最小的傳輸單位,每個幀都包含一個幀頭,標識了每個幀屬于哪個流;
HTTP2.0的通信是在一個tcp連接中進行的,每個連接可以包含人一個流。相應的,每個流通過消息通信,每個消息由幀組成,流之間可以相互交錯并且通過幀頭中的流標識進行重組。
HTTP 2.0 主要特征 總結:
簡單的說,HTTP 2.0將http協議拆分成了多個獨立的幀,每個幀對應著一個邏輯的流。一個tcp連接中每個流可以并行的進行傳輸。
請求響應多路復用 HTTP/1.x 中,客戶端可以通過使用多tcp連接讓請求并行,但是請求是按順序發送,同一個時間只能有一個響應返回。這種方式更不利的地方是,在http層產生了線頭阻塞(只要某個響應卡住,其他相應也會卡住),另外也無法充分利用tcp的最大性能(每個連接都要通過慢啟動方式來增大窗口來提高吞吐)
HTTP2.0 引入幀的概念消除了這個限制,通過將http消息拆成獨立的、可交錯的、可重組的幀,讓所有的請求和響應都可以多路復用。
如上圖,客戶端發送一個DATA?frame?(stream?5)給服務端,服務端為流1和流3發送一系列交錯的幀給客戶端。如此,就有三對 請求-響應 在并行的傳輸了。
將http消息拆分成了多個獨立、可交錯、可重組的幀,是http 2.0最大改進; 這些特性帶來如下好處:
請求優先級
HTTP消息可以拆分成多個獨立幀,幀發送的順序將會影響應用程序的性能。為了控制幀順序,每個流都可以賦予一個31位的優先級。 ??0表示著最高優先級 ??2^31?-?1 表示最低優先級
客戶端和服務端可以應用不同的策略去用于控制流、消息和幀,服務器可以根據CPU、內存、帶寬來標識優先級;如果響應數據已經到達,應該提升優先級發送給客戶端。
單TCP連接 有了幀的特新,服務端和客戶端只要保持一個長連接,就可以完成請求-響應多路復用,帶來的好處是,減少socket的數量,減少內存使用,更大的tcp吞吐,減少網絡擁塞,減少慢啟動帶來的影響。大多數的http消息都是簡短的,突發的,只用一個連接能更充分使用tcp性能(但只使用一個連接的HTTP 2.0 ,不能縮短網絡延時(受限光速),但能提高網絡吞吐率以及減少不必要的消耗);
HTTP 2.0 使用單連接,也有一些潛在的缺點:
雖然性能過于依賴TCP和網絡,但是實際實驗過程中,使用單連接性能仍然比多連接好許多。HTTP 2.0解決了許多性能瓶頸,但是TCP將會是最后一個瓶頸。關于tcp優化的解決方案有TCP?Fast?Open,?Proportional?Rate?Reduction,?increased?initial?congestion?window等等。
流量控制 單連接會引起多路復用產生對共享tcp資源的競爭,雖然優先級策略解決了資源的發送順序,但不能很好解決多流之間的流控問題。因此,HTTP 2.0 引入了一個簡單的機制來解決 多流間的流控問題。
當HTTP 2.0連接建立是,兩端會交換setting幀,其中包含了窗口大小。當然任意一端也可以為某條流或者整個鏈接禁止流控功能。Tcp的窗口控制不能基于每個流來控制,這也是HTTP 2.0 需要流控的原因。 HTTP 2.0協議沒有指定具體算法、值或者window?update何時發送,實現中可以根據使用情況和性能來設置。
服務端推送
HTTP 2.0 有個強大功能,可以對一個請求發送除了對應的響應外,還會發送多個其他相關文件響應。多余的響應是和請求是相關的。服務端可以把請求的其他關的資源推送的客戶端,而不用等待客戶端一一請求。
服務端推送帶來了一下幾個好處:
PUSH_PROMISE 所有推送流都是通過PUSH_PROMISE幀啟動,PUSH_PROMISE幀只是包含了推送資源的http報頭。 客戶端收到了推送幀,客戶端可以選擇拒絕該流(比如該資源已經被客戶端緩存)。 服務端必須遵循請求-響應的規則,只有收到請求后才可以發送推送幀,而不能任意發送推送幀。推送內容必須在它本身請求之前被發送。
報頭壓縮 HTTP傳輸攜帶著一些列報頭,這些報頭描述了需要傳輸的資源以及資源的屬性,在HTTP/1.x中這些語義都是用明文來表示并且這些報頭讓每個請求會增加500-800個字節大小,如果攜帶了cookies將會增加上千字節的數據。為了減少這些報頭,并且提升性能,HTTP/2.0壓縮了這些報頭:
如此,收發兩端就可以知道已經發送了那些報頭以及對應的value,這樣新報頭就可以根據就得報頭信息,發送不一樣的鍵值對信息即可,如下圖:
這個例子中,第二個請求只要發送發生改變的path報頭,如此減少了重復報頭發送量。一般情況下鍵值對在整個連接過程幾乎不發生改變(如user-agent, accept header)。相同報頭只要發送一次,如果報頭都未發生變化,請求將繼承之前請求的報頭信息。
HTTP 2.0 升級和發現 切換到HTTP 2.0不可能在一夜之前發生,有數百萬計的服務器,數億計的客戶端需要更新瀏覽器或者網絡庫。 http 2.0支持兼容模式的切換方式,客戶端需要在連接啟動階段判斷服務端是否支持HTTP 2.0; 需要考慮一下三種場景:
ALPN 用于發現HTTPS連接是否支持HTTP 2.0的TLS擴展頭,可以在HTTPs連接握手階段判斷是否支持HTTP2.0,以減少延時。 明文方式啟動的http將會費事些,HTTP/1.x 和HTTP 2.0都運行在80端口,沒有其他信息可以用于判斷是否支持HTTP2.0 客戶端將會用一種 Upgrade 升級機制來協商出一種合適的協議: GET?/page?HTTP/1.1 Host:?server.example.com Connection:?Upgrade,?HTTP2-Settings Upgrade:?HTTP/2.0 ? ?(1) HTTP2-Settings:?(SETTINGS?payload)?(2)
HTTP/1.1?200?OK ???(3) Content-length:?243 Content-type:?text/html (...?HTTP?1.1?response?...)
(or) HTTP/1.1?101?Switching?Protocols ??(4) Connection:?Upgrade Upgrade:?HTTP/2.0 (...?HTTP?2.0?response?...)
http 1.1請求攜帶 HTTP2.0升級報頭 HTTP2.0 SETTING攜帶 Base64編碼的URL 服務器拒絕升級,返回http 1.1響應 服務器接受HTTP 2.0升級,切換到新框架
二進制幀簡介
帶長度表示的二進制幀是HTTP 2.0的核心改進點。與 HTTP/1.x使用換行分隔符相比,二進制幀提供了更加簡潔的方式,代碼上也更加簡單和高效。一旦HTTP 2.0連接建立后,客戶端和服務端通過幀來通信。每個幀都帶有一個8字節的頭部,包含了幀的長度和幀類型,一個標志位和一個31位的流id。
有以下幾種幀類型: DATA? ? ? ?:數據幀用于傳輸HTTP body消息 HEADERS ?:?報頭幀由鍵值對(name-value)組成,用來打開一個流 PRIORITY?? : ?優先級幀明確了發送者建議的流的優先 RST_STREAM?:終止幀用于終止一條流 SETTINGS?:設置幀設置兩端通訊的參數 PUSH_PROMISE:推送承諾幀用來告知接收端準備稍后推送數據? PING?:ping幀 用于衡量兩端rtt GOAWAY?: 超時幀用于通知接收端不要在當前連接上創建新流。但之前的流仍可以繼續處理 WINDOW_UPDATE:窗口更新幀用來實現流量控制,包含對單個流或整個連接的控制,但只能影響DATA幀的傳輸 CONTINUATION:?延續幀用來延續一個報頭塊片段。
啟動一條新流 應用程序在發送數據前,必須創建一條流,指明優先級或者發送報頭等。HTTP 2.0中,客戶端和服務端都可以啟動新流:
為了避免流id沖突,客戶端啟動新流只取奇數id,服務端啟動新流只取偶數id;流的元數據和應用程序數據是分開發送的,客戶端和服務端可以使用不同的優先級,比如流控可以使用更高的優先級,流控只用于數據幀
數據發送 流一旦創建并且報頭已經發送, http數據就可以發送了,數據可以拆成多個數據幀發送,最后一個數據幀打上END_STREAM標記。
嚴格來說,數據幀長度可以達到2^16-1(65535)),但是為了避免線頭阻塞, HTTP 2.0協議規定最大長度是2^14 -1 (16383),超過最大值就要拆成多個數據幀。
HTTP 2.0 發展歷史以及與SPDY關系
spdy 是google 在2009年中開發的實驗性的協議,旨在通過解決HTTP 1.1中一些性能限制以降低網頁的加載時間,它的大概要達到的目標有:
- 降低50%的頁面加載時間
- 不要站點維護人員進行內容改變
- 簡化部署復雜度,避免網絡拓撲變化
- 與開源組織合作
- 搜集實驗數據驗證該協議
提出該協議后沒多久,很快谷歌就公布是SPDY實驗結果以及源碼; 2012年,包括chrome,firefox opera等其他站點都以及支持了SPDY;同年,HTTP?Working?Group已經準備將SPDY吸收到HTTP 2.0的官方標準中,之后HTTP-WG提出多次草案: ??March?2012:?Call?for?proposals?for?HTTP?2.0 ??September?2012:?First?draft?of?HTTP?2.0 ??July?2013:?First?implementation?draft?of?HTTP?2.0 ??April?2014:?Working?Group?last?call?for?HTTP?2.0 ??November?2014:?Submit?HTTP?2.0?to?IESG?as?a?Proposed?Standard
設計和技術標準:
二進制幀: HTTP2 性能提升的核心是全新的二進制幀分層,客戶端和服務端必須使用新的二進制編碼方式同對端通信,下圖描述了http消息在客戶端和服務端間如何分裝和傳輸: 二進制幀層只設計在socket收發層和HTTP層之間, 對http原來的語義,比如verbs,method和報頭沒有影響,但是在傳輸過程的編碼方式不同,比如http1.x中使用的換行符,在http2通信中則被拆成更小的二進制消息和幀;
流,消息和幀 流: 一個tcp連接內的雙向字節流;
消息: 一個對應著邏輯消息的完整的 一系列幀;
幀: HTTP 2.0 最小的傳輸單位,每個幀都包含一個幀頭,標識了每個幀屬于哪個流;
HTTP2.0的通信是在一個tcp連接中進行的,每個連接可以包含人一個流。相應的,每個流通過消息通信,每個消息由幀組成,流之間可以相互交錯并且通過幀頭中的流標識進行重組。
HTTP 2.0 主要特征 總結:
- 所有通信只在一個TCP連接中進程
- 流在連接中是一個虛擬的通道,每個流攜帶者雙向的信息。每個流程有著唯一的id?(1,?2,?…,?N).
- 消息是一個邏輯的http消息,比如請求或者響應,它們由一個或者多個幀組成。
- 幀是最小的通信單位,攜帶者指定的數據,比如http報頭或者負載等。
簡單的說,HTTP 2.0將http協議拆分成了多個獨立的幀,每個幀對應著一個邏輯的流。一個tcp連接中每個流可以并行的進行傳輸。
請求響應多路復用 HTTP/1.x 中,客戶端可以通過使用多tcp連接讓請求并行,但是請求是按順序發送,同一個時間只能有一個響應返回。這種方式更不利的地方是,在http層產生了線頭阻塞(只要某個響應卡住,其他相應也會卡住),另外也無法充分利用tcp的最大性能(每個連接都要通過慢啟動方式來增大窗口來提高吞吐)
HTTP2.0 引入幀的概念消除了這個限制,通過將http消息拆成獨立的、可交錯的、可重組的幀,讓所有的請求和響應都可以多路復用。
如上圖,客戶端發送一個DATA?frame?(stream?5)給服務端,服務端為流1和流3發送一系列交錯的幀給客戶端。如此,就有三對 請求-響應 在并行的傳輸了。
將http消息拆分成了多個獨立、可交錯、可重組的幀,是http 2.0最大改進; 這些特性帶來如下好處:
- ?讓請求和響應多路復用,而不用擔心線頭阻塞問題
- 只要用一個tcp連接就可以進行多個請求-響應通信,降低系統負載;
- 降低頁面加載時間,減少不必要的延時
請求優先級
HTTP消息可以拆分成多個獨立幀,幀發送的順序將會影響應用程序的性能。為了控制幀順序,每個流都可以賦予一個31位的優先級。 ??0表示著最高優先級 ??2^31?-?1 表示最低優先級
客戶端和服務端可以應用不同的策略去用于控制流、消息和幀,服務器可以根據CPU、內存、帶寬來標識優先級;如果響應數據已經到達,應該提升優先級發送給客戶端。
單TCP連接 有了幀的特新,服務端和客戶端只要保持一個長連接,就可以完成請求-響應多路復用,帶來的好處是,減少socket的數量,減少內存使用,更大的tcp吞吐,減少網絡擁塞,減少慢啟動帶來的影響。大多數的http消息都是簡短的,突發的,只用一個連接能更充分使用tcp性能(但只使用一個連接的HTTP 2.0 ,不能縮短網絡延時(受限光速),但能提高網絡吞吐率以及減少不必要的消耗);
HTTP 2.0 使用單連接,也有一些潛在的缺點:
- 單連接解決了HTTP層的線頭阻塞,但沒有解決tcp層的線頭阻塞(反而比多連接影響更大);
- 如果沒有啟用window scaling特性(窗口最大只有64k了),帶寬延遲積將會限制連接吞吐率;
- 當發生丟包,擁塞窗口減小,連接的吞吐率會大大降低;
雖然性能過于依賴TCP和網絡,但是實際實驗過程中,使用單連接性能仍然比多連接好許多。HTTP 2.0解決了許多性能瓶頸,但是TCP將會是最后一個瓶頸。關于tcp優化的解決方案有TCP?Fast?Open,?Proportional?Rate?Reduction,?increased?initial?congestion?window等等。
流量控制 單連接會引起多路復用產生對共享tcp資源的競爭,雖然優先級策略解決了資源的發送順序,但不能很好解決多流之間的流控問題。因此,HTTP 2.0 引入了一個簡單的機制來解決 多流間的流控問題。
- 流控是hop by hop,不是end to end
- 流控是基于window?update幀,接收端通告對端在這條流或者整個鏈接中它將接收多少字節
- 流控通過WINDOW_UPDATE幀更新,其中指定了流id和窗口增大值
- 流控具有方向的,接收端可以為每個流選擇設置任意大小窗口大小
- 流控可以被接收端禁止,可以是一條流也可以是整個連接。
當HTTP 2.0連接建立是,兩端會交換setting幀,其中包含了窗口大小。當然任意一端也可以為某條流或者整個鏈接禁止流控功能。Tcp的窗口控制不能基于每個流來控制,這也是HTTP 2.0 需要流控的原因。 HTTP 2.0協議沒有指定具體算法、值或者window?update何時發送,實現中可以根據使用情況和性能來設置。
服務端推送
HTTP 2.0 有個強大功能,可以對一個請求發送除了對應的響應外,還會發送多個其他相關文件響應。多余的響應是和請求是相關的。服務端可以把請求的其他關的資源推送的客戶端,而不用等待客戶端一一請求。
服務端推送帶來了一下幾個好處:
- 推送資源可以被客戶端緩存
- 推送資源可以被客戶端拒絕
- 推送資源可以被多個頁面復用
- 推送資源可以被服務端優先處理
PUSH_PROMISE 所有推送流都是通過PUSH_PROMISE幀啟動,PUSH_PROMISE幀只是包含了推送資源的http報頭。 客戶端收到了推送幀,客戶端可以選擇拒絕該流(比如該資源已經被客戶端緩存)。 服務端必須遵循請求-響應的規則,只有收到請求后才可以發送推送幀,而不能任意發送推送幀。推送內容必須在它本身請求之前被發送。
報頭壓縮 HTTP傳輸攜帶著一些列報頭,這些報頭描述了需要傳輸的資源以及資源的屬性,在HTTP/1.x中這些語義都是用明文來表示并且這些報頭讓每個請求會增加500-800個字節大小,如果攜帶了cookies將會增加上千字節的數據。為了減少這些報頭,并且提升性能,HTTP/2.0壓縮了這些報頭:
- 不用為每個請求和響應傳輸相同的數據,HTTP 2.0使用了 "header table",同時在服務端和客戶端引用和存儲這些key-value 對。
- Header table 在整個連接過程有效,客戶端和服務端也可以進行增量更新。
- 一個新的key-value 可以添加到表的末端,也替換掉表中的舊值。
如此,收發兩端就可以知道已經發送了那些報頭以及對應的value,這樣新報頭就可以根據就得報頭信息,發送不一樣的鍵值對信息即可,如下圖:
這個例子中,第二個請求只要發送發生改變的path報頭,如此減少了重復報頭發送量。一般情況下鍵值對在整個連接過程幾乎不發生改變(如user-agent, accept header)。相同報頭只要發送一次,如果報頭都未發生變化,請求將繼承之前請求的報頭信息。
HTTP 2.0 升級和發現 切換到HTTP 2.0不可能在一夜之前發生,有數百萬計的服務器,數億計的客戶端需要更新瀏覽器或者網絡庫。 http 2.0支持兼容模式的切換方式,客戶端需要在連接啟動階段判斷服務端是否支持HTTP 2.0; 需要考慮一下三種場景:
- TLS?和ALPN方式啟動https連接
- ?序言方式啟動http連接
- 沒有序言方式啟動連接
ALPN 用于發現HTTPS連接是否支持HTTP 2.0的TLS擴展頭,可以在HTTPs連接握手階段判斷是否支持HTTP2.0,以減少延時。 明文方式啟動的http將會費事些,HTTP/1.x 和HTTP 2.0都運行在80端口,沒有其他信息可以用于判斷是否支持HTTP2.0 客戶端將會用一種 Upgrade 升級機制來協商出一種合適的協議: GET?/page?HTTP/1.1 Host:?server.example.com Connection:?Upgrade,?HTTP2-Settings Upgrade:?HTTP/2.0 ? ?(1) HTTP2-Settings:?(SETTINGS?payload)?(2)
HTTP/1.1?200?OK ???(3) Content-length:?243 Content-type:?text/html (...?HTTP?1.1?response?...)
(or) HTTP/1.1?101?Switching?Protocols ??(4) Connection:?Upgrade Upgrade:?HTTP/2.0 (...?HTTP?2.0?response?...)
二進制幀簡介
帶長度表示的二進制幀是HTTP 2.0的核心改進點。與 HTTP/1.x使用換行分隔符相比,二進制幀提供了更加簡潔的方式,代碼上也更加簡單和高效。一旦HTTP 2.0連接建立后,客戶端和服務端通過幀來通信。每個幀都帶有一個8字節的頭部,包含了幀的長度和幀類型,一個標志位和一個31位的流id。
- 16位長度位,一個幀最大可以攜帶2^16 -1 ?長度數據,不包括8字節幀頭
- 8位類型
- 8位標志位
- 一個保留位(一直為0)
- 31位流唯一標識
有以下幾種幀類型: DATA? ? ? ?:數據幀用于傳輸HTTP body消息 HEADERS ?:?報頭幀由鍵值對(name-value)組成,用來打開一個流 PRIORITY?? : ?優先級幀明確了發送者建議的流的優先 RST_STREAM?:終止幀用于終止一條流 SETTINGS?:設置幀設置兩端通訊的參數 PUSH_PROMISE:推送承諾幀用來告知接收端準備稍后推送數據? PING?:ping幀 用于衡量兩端rtt GOAWAY?: 超時幀用于通知接收端不要在當前連接上創建新流。但之前的流仍可以繼續處理 WINDOW_UPDATE:窗口更新幀用來實現流量控制,包含對單個流或整個連接的控制,但只能影響DATA幀的傳輸 CONTINUATION:?延續幀用來延續一個報頭塊片段。
啟動一條新流 應用程序在發送數據前,必須創建一條流,指明優先級或者發送報頭等。HTTP 2.0中,客戶端和服務端都可以啟動新流:
- 客戶端通過發送報頭幀啟動一個請求,報頭幀包含一個流ID,一個可選的31位優先級和一系列http報頭鍵值對。
- 服務端通過發送一個承諾推送幀來啟動一個推送流,幾乎和報頭幀一樣,但多包含了一個承諾流的id,取代爆頭戰中的優先級值
為了避免流id沖突,客戶端啟動新流只取奇數id,服務端啟動新流只取偶數id;流的元數據和應用程序數據是分開發送的,客戶端和服務端可以使用不同的優先級,比如流控可以使用更高的優先級,流控只用于數據幀
數據發送 流一旦創建并且報頭已經發送, http數據就可以發送了,數據可以拆成多個數據幀發送,最后一個數據幀打上END_STREAM標記。
嚴格來說,數據幀長度可以達到2^16-1(65535)),但是為了避免線頭阻塞, HTTP 2.0協議規定最大長度是2^14 -1 (16383),超過最大值就要拆成多個數據幀。
總結
以上是生活随笔為你收集整理的高性能浏览器-HTTP 2.0的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MTBF需要测试多久,MTBF失效率是多
- 下一篇: 关于HTML几种简单布局方式