HTTP2简介和基于HTTP2的Web优化
時值公司全面切換到HTTPS和HTTP/2,討論HTTP/2有了更現實的意義。以前也斷斷續續看了些文章,做了些了解,這里算作一個學習和總結吧。
本文定位入門級別,分作兩大塊:
- HTTP/2是什么
- 基于HTTP/2前端可以做什么優化
本文參考了一些博文和資料,后面已列出,感謝他們的分享。
HTTP/2簡介
HTTP/2 is a replacement for how HTTP is expressed “on the wire.” It is not a ground-up rewrite of the protocol; HTTP methods, status codes and semantics are the same, and it should be possible to use the same APIs as HTTP/1.x (possibly with some small additions) to represent the protocol.
HTTP/2是現行HTTP協議(HTTP/1.x)的替代,但它不是重寫,HTTP方法/狀態碼/語義都與HTTP/1.x一樣。HTTP/2基于SPDY3,專注于性能,最大的一個目標是在用戶和網站間只用一個連接(connection)。
HTTP/2由兩個規范(Specification)組成:
- Hypertext Transfer Protocol version 2 - RFC7540
- HPACK - Header Compression for HTTP/2 - RFC7541
為什么需要HTTP/2
我們知道,影響一個HTTP網絡請求的因素主要有兩個:帶寬和延遲。在今天的網絡情況下,帶寬一般不再是瓶頸,所以我們主要討論下延遲。延遲一般有下面幾個因素:
- 瀏覽器阻塞(Head-Of-Line Blocking):瀏覽器會因為一些原因阻塞請求。
- DNS查詢。
- 建立連接(Initial connection):HTTP基于 TCP 協議,TCP的3次握手和慢啟動極大增加延遲。
說完背景,我們討論下HTTP/1.x中到底存在哪些問題?
HTTP/1.x的缺陷
- 連接無法復用:連接無法復用會導致每次請求都經歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對文件類大請求影響較大。
- HTTP/1.0傳輸數據時,每次都需要重新建立連接,增加延遲。
- 1.1雖然加入keep-alive可以復用一部分連接,但域名分片等情況下仍然需要建立多個connection,耗費資源,給服務器帶來性能壓力。
- Head-Of-Line Blocking:導致帶寬無法被充分利用,以及后續健康請求被阻塞。HOLB是指一系列包(package)因為第一個包被阻塞;HTTP/1.x中,由于服務器必須按接受請求的順序發送響應的規則限制,那么假設瀏覽器在一個(tcp)連接上發送了兩個請求,那么服務器必須等第一個請求響應完畢才能發送第二個響應——HOLB。
- 雖然現代瀏覽器允許每個origin建立6個connection,但大量網頁動輒幾十個資源,HOLB依然是主要問題。
- 協議開銷大:HTTP/1.x中header內容過大(每次請求header基本不怎么變化),增加了傳輸的成本。
- 安全因素:HTTP/1.x中傳輸的內容都是明文,客戶端和服務端雙方無法驗證身份。
HTTP/2的新特性
因為HTTP/1.x的問題,人們提出了各種解決方案。比如希望復用連接的長鏈接/http long-polling/websocket等等,解決HOLB的Domain Sharding(域名分片)/inline資源/css sprite等等。
不過以上優化都繞開了協議,直到谷歌推出SPDY,才算是正式改造HTTP協議本身。降低延遲,壓縮header等等,SPDY的實踐證明了這些優化的效果,也最終帶來HTTP/2的誕生。
1. 新的二進制格式(Binary Format)
http1.x誕生的時候是明文協議,其格式由三部分組成:start line(request line或者status line),header,body。要識別這3部分就要做協議解析,http1.x的解析是基于文本?;谖谋緟f議的格式解析存在天然缺陷,文本的表現形式有多樣性,要做到健壯性考慮的場景必然很多,二進制則不同,只認0和1的組合。基于這種考慮http2.0的協議解析決定采用二進制格式,實現方便且健壯。
http2的格式定義十分高效且精簡。length定義了整個frame的大小,type定義frame的類型(一共10種),flags用bit位定義一些重要的參數,stream id用作流控制,payload就是request的正文。
2. Header壓縮
http1.x的header由于cookie和user agent很容易膨脹,而且每次都要重復發送。
http2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,既避免了重復header的傳輸,又減小了需要傳輸的大小。高效的壓縮算法可以很大的壓縮header,減少發送包的數量從而降低延遲。
3. 流(stream)和多路復用(MultiPlexing)
什么是stream?
Multiplexing of requests is achieved by having each HTTP request/response exchange associated with its own stream. Streams are largely independent of each other, so a blocked or stalled request or response does not prevent progress on other streams.
A "stream" is an independent, bidirectional sequence of frames exchanged between the client and server within an HTTP/2 connection.
A client sends an HTTP request on a new stream, using a previously unused stream identifier. A server sends an HTTP response on the same stream as the request.
Multiplexing of requests is achieved by having each HTTP request/response exchange associated with its own stream.
翻譯下,stream就是在HTTP/2連接上的雙向幀序列。每個http request都會新建自己的stream,response在同一個stream上返回。
多路復用(MultiPlexing),即連接共享。之所以可以復用,是因為每個stream高度獨立,堵塞的stream不會影響其它stream的處理。一個連接上可以有多個stream,每個stream的frame可以隨機的混雜在一起,接收方可以根據stream id將frame再歸屬到各自不同的request里面。
3.1 流量控制(Flow Control)
類似TCP協議通過sliding window的算法來做流量控制,http2.0使用 WINDOW_UPDATE frame 來做流量控制。每個stream都有流量控制,這保證了數據接收方可以只讓自己需要的數據被傳輸。
3.2 流優先級(Stream Priority)
每個流可以設置優先級。優先級的目標是允許終端高速對端(當對端處理并發流時)怎么分配資源。
更重要的是,當傳輸能力有限時,優先級可以用來挑選哪些流(高優先級)優先傳輸——這是優化瀏覽器渲染的關鍵,即服務端負責設置優先級,使重要的資源優先加載,加速頁面渲染。
4. Server Push
Server Push即服務端能通過push的方式將客戶端需要的內容預先推送過去,也叫“cache push”。
基于HTTP/2的Web優化
從HTTP/1.x到HTTP/2的通用優化規則
盡管HTTP/2相比HTTP/1.x有很大的不同,但有幾條優化規則是仍然適用的:
- 減少DNS查詢。DNS查詢需要時間,沒有resolved的域名會阻塞請求。
- 減少TCP連接。HTTP/2只使用一個TCP連接。
- 使用CDN。使用CDN分發資源可以減少延遲。
- 減少HTTP跳轉。特別是非同一域名的跳轉,需要DNS,TCP,HTTP三種開銷。
- 消除不必要的請求數據。HTTP/2壓縮了Header。
- 壓縮傳輸的數據。gzip壓縮很高效。
- 客戶端緩存資源。緩存是必要的。
- 消除不必要的資源。激進的提前獲取資源對客戶端和服務端都開銷巨大。
因HTTP/2而不一樣的優化規則
然后下面要介紹一些HTTP/1.x里推薦而HTTP/2禁止的優化。
- Domain Sharding(域名分片):HTTP/1.x中瀏覽器一般每個域名最多同時使用6個連接。每個連接都會經歷3次握手,會消耗服務器資源,甚至會相互堵塞。然而1.x中我們仍然使用Domain Sharding(域名分片)來突破連接數的限制(提高并行加載能力)。但是,多少域名合適,每個連接的資源消耗,帶寬競爭,DNS查詢時間等等都是問題。在HTTP/2里,多路復用完美解決問題。所以請不要在HTTP/2里使用域名分片。
- Concatenation(文件合并):1.x中我們經常合并文件來減少請求。但是,
- 大文件會延遲(delay)客戶端的處理執行(必須等到整個文件下載完)。
- 緩存失效的開銷昂貴:很少量的數據更新會使整個大文件失效,然后需要重新下載整個大文件。
- 破壞了顆粒化的資源的緩存,更新和重新生效。
- 此外,文件合并也需要額外的構建處理(build step),增加項目復雜度。
所以在HTTP/2里,請避免合并文件。使用小的顆粒化的資源,優化緩存政策。
- Inline resource(內聯資源):內聯資源也是1.x中常用的優化手段,可以減少請求。但是,內聯資源無法獨立緩存,也破壞了HTTP/2的多路復用和優先級策略(使用了父資源的優先級,也沒法被客戶端拒絕)。HTTP/2中不要再使用內聯資源,直接利用Server push:
- 顆?;馁Y源可以被獨立緩存。
- 顆粒化的資源可以被正確地mux'ed(利用多路復用傳輸)和設置優先級。
- 允許客戶端更靈活地控制資源的下載和使用。
HTTP/2需要特別考慮的優化規則
With HTTP/2 the browser is relying on the server to deliver data in an optimal way --- this is critical
HTTP/1.1時,瀏覽器會通過維持一個優先級隊列來給資源設置優先級,然后猜測可用TCP連接的最佳利用方式——這延遲了請求發出。
HTTP/2中,瀏覽器根據type/context來給資源設置優先級,并且在發現資源后立即發出請求。優先級以權重+依賴(weights+dependencies)的形式傳達給服務端。這時候,服務端必須給重要資源設置更高優先級,更早地傳給瀏覽器,使瀏覽器能獲取必要資源,盡早渲染。
參考
- HTTP2主頁
- HTTP,HTTP2.0,SPDY,HTTPS你應該知道的一些事 --- 樸實易懂!
- Optimizing Application Delivery
- HTTP2 is here, let's optimize! --- 超棒的PPT!
- HTTP 2.0的那些事
截圖來自 HTTP2 is here, let's optimize!
原文來自:https://github.com/creeperyang/blog/issues/23
總結
以上是生活随笔為你收集整理的HTTP2简介和基于HTTP2的Web优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中套接字,如何在java中获得一
- 下一篇: 元气女孩是什么意思