HTTP2简介和基于HTTP2的Web优化
時值公司全面切換到HTTPS和HTTP/2,討論HTTP/2有了更現(xiàn)實的意義。以前也斷斷續(xù)續(xù)看了些文章,做了些了解,這里算作一個學(xué)習(xí)和總結(jié)吧。
本文定位入門級別,分作兩大塊:
- HTTP/2是什么
- 基于HTTP/2前端可以做什么優(yōu)化
本文參考了一些博文和資料,后面已列出,感謝他們的分享。
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是現(xiàn)行HTTP協(xié)議(HTTP/1.x)的替代,但它不是重寫,HTTP方法/狀態(tài)碼/語義都與HTTP/1.x一樣。HTTP/2基于SPDY3,專注于性能,最大的一個目標(biāo)是在用戶和網(wǎng)站間只用一個連接(connection)。
HTTP/2由兩個規(guī)范(Specification)組成:
- Hypertext Transfer Protocol version 2 - RFC7540
- HPACK - Header Compression for HTTP/2 - RFC7541
為什么需要HTTP/2
我們知道,影響一個HTTP網(wǎng)絡(luò)請求的因素主要有兩個:帶寬和延遲。在今天的網(wǎng)絡(luò)情況下,帶寬一般不再是瓶頸,所以我們主要討論下延遲。延遲一般有下面幾個因素:
- 瀏覽器阻塞(Head-Of-Line Blocking):瀏覽器會因為一些原因阻塞請求。
- DNS查詢。
- 建立連接(Initial connection):HTTP基于 TCP 協(xié)議,TCP的3次握手和慢啟動極大增加延遲。
說完背景,我們討論下HTTP/1.x中到底存在哪些問題?
HTTP/1.x的缺陷
- 連接無法復(fù)用:連接無法復(fù)用會導(dǎo)致每次請求都經(jīng)歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對文件類大請求影響較大。
- HTTP/1.0傳輸數(shù)據(jù)時,每次都需要重新建立連接,增加延遲。
- 1.1雖然加入keep-alive可以復(fù)用一部分連接,但域名分片等情況下仍然需要建立多個connection,耗費資源,給服務(wù)器帶來性能壓力。
- Head-Of-Line Blocking:導(dǎo)致帶寬無法被充分利用,以及后續(xù)健康請求被阻塞。HOLB是指一系列包(package)因為第一個包被阻塞;HTTP/1.x中,由于服務(wù)器必須按接受請求的順序發(fā)送響應(yīng)的規(guī)則限制,那么假設(shè)瀏覽器在一個(tcp)連接上發(fā)送了兩個請求,那么服務(wù)器必須等第一個請求響應(yīng)完畢才能發(fā)送第二個響應(yīng)——HOLB。
- 雖然現(xiàn)代瀏覽器允許每個origin建立6個connection,但大量網(wǎng)頁動輒幾十個資源,HOLB依然是主要問題。
- 協(xié)議開銷大:HTTP/1.x中header內(nèi)容過大(每次請求header基本不怎么變化),增加了傳輸?shù)某杀尽?/li>
- 安全因素:HTTP/1.x中傳輸?shù)膬?nèi)容都是明文,客戶端和服務(wù)端雙方無法驗證身份。
HTTP/2的新特性
因為HTTP/1.x的問題,人們提出了各種解決方案。比如希望復(fù)用連接的長鏈接/http long-polling/websocket等等,解決HOLB的Domain Sharding(域名分片)/inline資源/css sprite等等。
不過以上優(yōu)化都繞開了協(xié)議,直到谷歌推出SPDY,才算是正式改造HTTP協(xié)議本身。降低延遲,壓縮header等等,SPDY的實踐證明了這些優(yōu)化的效果,也最終帶來HTTP/2的誕生。
1. 新的二進(jìn)制格式(Binary Format)
http1.x誕生的時候是明文協(xié)議,其格式由三部分組成:start line(request line或者status line),header,body。要識別這3部分就要做協(xié)議解析,http1.x的解析是基于文本。基于文本協(xié)議的格式解析存在天然缺陷,文本的表現(xiàn)形式有多樣性,要做到健壯性考慮的場景必然很多,二進(jìn)制則不同,只認(rèn)0和1的組合。基于這種考慮http2.0的協(xié)議解析決定采用二進(jìn)制格式,實現(xiàn)方便且健壯。
http2的格式定義十分高效且精簡。length定義了整個frame的大小,type定義frame的類型(一共10種),flags用bit位定義一些重要的參數(shù),stream id用作流控制,payload就是request的正文。
2. Header壓縮
http1.x的header由于cookie和user agent很容易膨脹,而且每次都要重復(fù)發(fā)送。
http2.0使用encoder來減少需要傳輸?shù)膆eader大小,通訊雙方各自cache一份header fields表,既避免了重復(fù)header的傳輸,又減小了需要傳輸?shù)拇笮 8咝У膲嚎s算法可以很大的壓縮header,減少發(fā)送包的數(shù)量從而降低延遲。
3. 流(stream)和多路復(fù)用(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上返回。
多路復(fù)用(MultiPlexing),即連接共享。之所以可以復(fù)用,是因為每個stream高度獨立,堵塞的stream不會影響其它stream的處理。一個連接上可以有多個stream,每個stream的frame可以隨機的混雜在一起,接收方可以根據(jù)stream id將frame再歸屬到各自不同的request里面。
3.1 流量控制(Flow Control)
類似TCP協(xié)議通過sliding window的算法來做流量控制,http2.0使用 WINDOW_UPDATE frame 來做流量控制。每個stream都有流量控制,這保證了數(shù)據(jù)接收方可以只讓自己需要的數(shù)據(jù)被傳輸。
3.2 流優(yōu)先級(Stream Priority)
每個流可以設(shè)置優(yōu)先級。優(yōu)先級的目標(biāo)是允許終端高速對端(當(dāng)對端處理并發(fā)流時)怎么分配資源。
更重要的是,當(dāng)傳輸能力有限時,優(yōu)先級可以用來挑選哪些流(高優(yōu)先級)優(yōu)先傳輸——這是優(yōu)化瀏覽器渲染的關(guān)鍵,即服務(wù)端負(fù)責(zé)設(shè)置優(yōu)先級,使重要的資源優(yōu)先加載,加速頁面渲染。
4. Server Push
Server Push即服務(wù)端能通過push的方式將客戶端需要的內(nèi)容預(yù)先推送過去,也叫“cache push”。
基于HTTP/2的Web優(yōu)化
從HTTP/1.x到HTTP/2的通用優(yōu)化規(guī)則
盡管HTTP/2相比HTTP/1.x有很大的不同,但有幾條優(yōu)化規(guī)則是仍然適用的:
- 減少DNS查詢。DNS查詢需要時間,沒有resolved的域名會阻塞請求。
- 減少TCP連接。HTTP/2只使用一個TCP連接。
- 使用CDN。使用CDN分發(fā)資源可以減少延遲。
- 減少HTTP跳轉(zhuǎn)。特別是非同一域名的跳轉(zhuǎn),需要DNS,TCP,HTTP三種開銷。
- 消除不必要的請求數(shù)據(jù)。HTTP/2壓縮了Header。
- 壓縮傳輸?shù)臄?shù)據(jù)。gzip壓縮很高效。
- 客戶端緩存資源。緩存是必要的。
- 消除不必要的資源。激進(jìn)的提前獲取資源對客戶端和服務(wù)端都開銷巨大。
因HTTP/2而不一樣的優(yōu)化規(guī)則
然后下面要介紹一些HTTP/1.x里推薦而HTTP/2禁止的優(yōu)化。
- Domain Sharding(域名分片):HTTP/1.x中瀏覽器一般每個域名最多同時使用6個連接。每個連接都會經(jīng)歷3次握手,會消耗服務(wù)器資源,甚至?xí)嗷ザ氯H欢?.x中我們?nèi)匀皇褂肈omain Sharding(域名分片)來突破連接數(shù)的限制(提高并行加載能力)。但是,多少域名合適,每個連接的資源消耗,帶寬競爭,DNS查詢時間等等都是問題。在HTTP/2里,多路復(fù)用完美解決問題。所以請不要在HTTP/2里使用域名分片。
- Concatenation(文件合并):1.x中我們經(jīng)常合并文件來減少請求。但是,
- 大文件會延遲(delay)客戶端的處理執(zhí)行(必須等到整個文件下載完)。
- 緩存失效的開銷昂貴:很少量的數(shù)據(jù)更新會使整個大文件失效,然后需要重新下載整個大文件。
- 破壞了顆粒化的資源的緩存,更新和重新生效。
- 此外,文件合并也需要額外的構(gòu)建處理(build step),增加項目復(fù)雜度。
所以在HTTP/2里,請避免合并文件。使用小的顆粒化的資源,優(yōu)化緩存政策。
- Inline resource(內(nèi)聯(lián)資源):內(nèi)聯(lián)資源也是1.x中常用的優(yōu)化手段,可以減少請求。但是,內(nèi)聯(lián)資源無法獨立緩存,也破壞了HTTP/2的多路復(fù)用和優(yōu)先級策略(使用了父資源的優(yōu)先級,也沒法被客戶端拒絕)。HTTP/2中不要再使用內(nèi)聯(lián)資源,直接利用Server push:
- 顆粒化的資源可以被獨立緩存。
- 顆粒化的資源可以被正確地mux'ed(利用多路復(fù)用傳輸)和設(shè)置優(yōu)先級。
- 允許客戶端更靈活地控制資源的下載和使用。
HTTP/2需要特別考慮的優(yōu)化規(guī)則
With HTTP/2 the browser is relying on the server to deliver data in an optimal way --- this is critical
HTTP/1.1時,瀏覽器會通過維持一個優(yōu)先級隊列來給資源設(shè)置優(yōu)先級,然后猜測可用TCP連接的最佳利用方式——這延遲了請求發(fā)出。
HTTP/2中,瀏覽器根據(jù)type/context來給資源設(shè)置優(yōu)先級,并且在發(fā)現(xiàn)資源后立即發(fā)出請求。優(yōu)先級以權(quán)重+依賴(weights+dependencies)的形式傳達(dá)給服務(wù)端。這時候,服務(wù)端必須給重要資源設(shè)置更高優(yōu)先級,更早地傳給瀏覽器,使瀏覽器能獲取必要資源,盡早渲染。
參考
- HTTP2主頁
- HTTP,HTTP2.0,SPDY,HTTPS你應(yīng)該知道的一些事 --- 樸實易懂!
- 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
總結(jié)
以上是生活随笔為你收集整理的HTTP2简介和基于HTTP2的Web优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中套接字,如何在java中获得一
- 下一篇: 元气女孩是什么意思