Http/2 對(duì)比 Http/1.1 的性能提升
- HTTP/1.1發(fā)明以來(lái)發(fā)生了哪些變化?
- HTTP/1.1 協(xié)議的性能缺陷
- HTTP/2 新特性
- HTTP/2 還存在的問(wèn)題
HTTP/1.1發(fā)明以來(lái)發(fā)生了哪些變化?
近年來(lái),仔細(xì)觀察那些最流行的網(wǎng)站首頁(yè)所需要下載的資源的話,會(huì)發(fā)現(xiàn)一個(gè)非常明顯的趨勢(shì):
- 消息變大 :從幾 KB 大小的消息,到幾 MB 大小的消息;
- 頁(yè)面資源變多 :從每個(gè)頁(yè)面不到 10 個(gè)的資源,到每頁(yè)超 100 多個(gè)資源;
- 內(nèi)容形式變多樣 :從單純到文本內(nèi)容,到圖片、視頻、音頻等內(nèi)容;
- 實(shí)時(shí)性要求變高 :對(duì)頁(yè)面的實(shí)時(shí)性要求的應(yīng)用越來(lái)越多;
自從 1997 年 HTTP/1.1 發(fā)布以來(lái),我們已經(jīng)使用 HTTP/1.x 相當(dāng)長(zhǎng)一段時(shí)間了,但近幾年內(nèi)容的爆炸式成長(zhǎng)使得 HTTP/1.1 越來(lái)越無(wú)法滿足現(xiàn)代網(wǎng)絡(luò)的需求了
HTTP/1.1 協(xié)議的性能缺陷
- 高延遲:頁(yè)面訪問(wèn)速度下降
- 無(wú)狀態(tài):頭部巨大切重復(fù)
- 隊(duì)頭阻塞問(wèn)題,同一連接只能在完成一個(gè) HTTP 事務(wù)(請(qǐng)求和響應(yīng))后,才能處理下一個(gè)事務(wù);
- 明文傳輸:不安全
- 不支持服務(wù)器推送消息,因此當(dāng)客戶端需要獲取通知時(shí),只能通過(guò)定時(shí)器不斷地拉取消息,這無(wú)疑浪費(fèi)大量了帶寬和服務(wù)器資源。
Http /2 的新特性
兼容 HTTP/1.1
HTTP/2 出來(lái)的目的是為了改善 HTTP 的性能。協(xié)議升級(jí)有一個(gè)很重要的地方,就是要兼容老版本的協(xié)議,否則新協(xié)議推廣起來(lái)就相當(dāng)困難,HTTP/2 是怎么做的呢?
HTTP/2 沒有在 URI 里引入新的協(xié)議名,仍然用「http://」表示明文協(xié)議,用「https://」表示加密協(xié)議,于是只需要瀏覽器和服務(wù)器在背后自動(dòng)升級(jí)協(xié)議,這樣可以讓用戶意識(shí)不到協(xié)議的升級(jí),很好的實(shí)現(xiàn)了協(xié)議的平滑升級(jí)。
還是基于 TCP 協(xié)議傳輸,應(yīng)用層方面為了保持功能上的兼容,與 HTTP/1.1 完全一致,比如請(qǐng)求方法、狀態(tài)碼、頭字段等規(guī)則保留不變。
二進(jìn)制傳輸
HTTP/2 不再像 HTTP/1.1 里的純文本形式的報(bào)文,而是全面采用了二進(jìn)制格式,頭信息和數(shù)據(jù)體都是二進(jìn)制,并且統(tǒng)稱為幀(frame):頭信息幀(Headers Frame)和數(shù)據(jù)幀(Data Frame)。
這樣對(duì)計(jì)算機(jī)非常友好,因?yàn)橛?jì)算機(jī)收到報(bào)文后,無(wú)需再將明文的報(bào)文轉(zhuǎn)成二進(jìn)制,而是直接解析二進(jìn)制報(bào)文,這增加了數(shù)據(jù)傳輸?shù)男省?/p>
Header 壓縮(HPACK)
HTTP 協(xié)議不帶有狀態(tài),每次請(qǐng)求都必須附上所有信息。所以,請(qǐng)求的很多字段都是重復(fù)的,比如Cookie和User Agent,一模一樣的內(nèi)容,每次請(qǐng)求都必須附帶,這會(huì)浪費(fèi)很多帶寬,也影響速度。
HTTP/2 對(duì)這一點(diǎn)做了優(yōu)化,引入了頭信息壓縮機(jī)制(header compression)。一方面,頭信息使用gzip或compress壓縮后再發(fā)送;另一方面,客戶端和服務(wù)器同時(shí)維護(hù)一張頭信息表,所有字段都會(huì)存入這個(gè)表,生成一個(gè)索引號(hào),以后就不發(fā)送同樣字段了,只發(fā)送索引號(hào),這樣就提高速度了。
HPACK 算法:在客戶端和服務(wù)器同時(shí)維護(hù)一張頭信息表,所有字段都會(huì)存入這個(gè)表,生成一個(gè)索引號(hào),以后就不發(fā)送同樣字段了,只發(fā)送索引號(hào),這樣就提高速度了。
多路復(fù)用
多路復(fù)用,就是在一個(gè) TCP 連接中可以存在多條流。換句話說(shuō),也就是可以發(fā)送多個(gè)請(qǐng)求,對(duì)端可以通過(guò)幀中的標(biāo)識(shí)知道屬于哪個(gè)請(qǐng)求。
這一特性使得 HTTP 傳輸性能得到極大提升,主要體現(xiàn)在以下三個(gè)方面:
復(fù)用 TCP 連接
HTTP/2 復(fù)用 TCP 連接,在一個(gè)連接里,客戶端和瀏覽器都可以同時(shí)發(fā)送多個(gè)請(qǐng)求或回應(yīng),而且不用按照順序一一對(duì)應(yīng),這樣就避免了"隊(duì)頭堵塞"
數(shù)據(jù)流
HTTP/2 并行交錯(cuò)地發(fā)送多個(gè)請(qǐng)求 / 響應(yīng),請(qǐng)求 / 響應(yīng)之間互不影響
HTTP/2 將每個(gè)請(qǐng)求或回應(yīng)的所有數(shù)據(jù)包,稱為一個(gè)數(shù)據(jù)流(stream)。每個(gè)數(shù)據(jù)流都有一個(gè)獨(dú)一無(wú)二的編號(hào)。數(shù)據(jù)包發(fā)送的時(shí)候,都必須標(biāo)記數(shù)據(jù)流ID,用來(lái)區(qū)分它屬于哪個(gè)數(shù)據(jù)流。另外還規(guī)定,客戶端發(fā)出的數(shù)據(jù)流,ID一律為奇數(shù),服務(wù)器發(fā)出的,ID為偶數(shù)。
數(shù)據(jù)流發(fā)送到一半的時(shí)候,客戶端和服務(wù)器都可以發(fā)送信號(hào)(RST_STREAM幀),取消這個(gè)數(shù)據(jù)流。1.1版取消數(shù)據(jù)流的唯一方法,就是關(guān)閉TCP連接。這就是說(shuō),HTTP/2 可以取消某一次請(qǐng)求,同時(shí)保證TCP連接還打開著,可以被其他請(qǐng)求使用。
優(yōu)先級(jí)
HTTP/2 還可以對(duì)每個(gè) Stream 設(shè)置不同優(yōu)先級(jí),幀頭中的「標(biāo)志位」可以設(shè)置優(yōu)先級(jí),比如客戶端訪問(wèn) HTML/CSS 和圖片資源時(shí),希望服務(wù)器先傳遞 HTML/CSS,再傳圖片,那么就可以通過(guò)設(shè)置 Stream 的優(yōu)先級(jí)來(lái)實(shí)現(xiàn),以此提高用戶體驗(yàn)。
服務(wù)端 Push
HTTP/1.1 不支持服務(wù)器主動(dòng)推送資源給客戶端,都是由客戶端向服務(wù)器發(fā)起請(qǐng)求后,才能獲取到服務(wù)器響應(yīng)的資源。
比如,客戶端通過(guò) HTTP/1.1 請(qǐng)求從服務(wù)器那獲取到了 HTML 文件,而 HTML 可能還需要依賴 CSS 來(lái)渲染頁(yè)面,這時(shí)客戶端還要再發(fā)起獲取 CSS 文件的請(qǐng)求,需要兩次消息往返,如下圖左邊部分:
如上圖右邊部分,在 HTTP/2 中,客戶端在訪問(wèn) HTML 時(shí),服務(wù)器可以直接主動(dòng)推送 CSS 文件,減少了消息傳遞的次數(shù)。
提高安全性
出于兼容的考慮,HTTP/2 延續(xù)了 HTTP/1 的“明文”特點(diǎn),可以像以前一樣使用明文傳輸數(shù)據(jù),不強(qiáng)制使用加密通信,但 HTTPS 已經(jīng)是大勢(shì)所趨,各大主流瀏覽器都支持加密的 HTTP/2,所以,真實(shí)應(yīng)用中的 HTTP/2 是還是加密的:
HTTP/2 遺留問(wèn)題
HTTP/2 還會(huì)隊(duì)頭阻塞
HTTP/2 通過(guò) Stream 的并發(fā)能力,解決了 HTTP/1 隊(duì)頭阻塞的問(wèn)題,看似很完美了,但是 HTTP/2 還是存在“隊(duì)頭阻塞”的問(wèn)題,只不過(guò)問(wèn)題不是在 HTTP 這一層面,而是在 TCP 這一層。
如果造成隊(duì)頭阻塞,問(wèn)題可能比http1.1還嚴(yán)重,因?yàn)橹挥幸粋€(gè)tcp連接,后續(xù)的傳輸都要等前面,http/1.1 多個(gè)tcp連接,阻塞一個(gè),其他的還可以正常跑。