面試真經(jīng) HTTP HTTPS HTTP1.1 HTTP2 HTTP3
金山銀四, 是一個騷動的季節(jié)。
昨天在某大廠面試中,就被問到"你用過HTTPS沒?" 這種直白的問題,回答的并不流暢,結(jié)合最近我在寫gRPC, 索性梳理一下 HTTP HTTPS HTTP1.1 HTTP2 HTTP3
HTTP
客戶端(如Web瀏覽器)從服務(wù)器(如Web服務(wù)器)請求資源時用到的協(xié)議。
HTTPS
一種加密HTTP的方式。一般使用SSL/TLS將HTTP消息包裝為加密格式。
現(xiàn)代Web越來越趨向于使用HTTPS, 除非您有充足的理由拒絕HTTPS,否則現(xiàn)在創(chuàng)建的任何網(wǎng)站上都推薦使用HTTPS (傳送門)
當通過未加密的HTTP為網(wǎng)站提供服務(wù)時,越來越多的Web瀏覽器會發(fā)出警告。
HTTP/1.1
這是HTTP協(xié)議目前的流行格式。它是基于文本的協(xié)議,
HTTP/1.1消息可以是未加密的(網(wǎng)站地址以http://開頭),也可以使用HTTPS加密(網(wǎng)站地址以https://開頭)??蛻舳耸褂肬RL的開頭來決定要使用的協(xié)議,如果未提供,通常默認為http://
HTTP2
2015年發(fā)布的HTTP新版本,通過從基于文本的協(xié)議轉(zhuǎn)移到二進制協(xié)議,解決了1.1版本的性能問題。
對于客戶端和服務(wù)器,這更容易解析,減少了錯誤的發(fā)生,并且還允許多路復用。
HTTP/2沒有強制要求使用TLS,可以通過未加密(http://)和加密(https://)通道使用,但是Web瀏覽器僅通過HTTPS支持它(在此情況下,連接開始時進行的HTTPS協(xié)商決定了后面使用HTTP/1.1還是HTTP/2)。
gRpc是谷歌開源的遠程過程調(diào)用框架,基于HTTP2 協(xié)議研發(fā)。
HTTP3
HTTP的下一個版本,目前正在開發(fā)中。它可能會在2020年末甚至2021年完成,您可能會在2020年末甚至2021年末看到一些廣泛應(yīng)用。
它將建立在稱為QUIC的基于UDP的傳輸之上(而不是HTTP/1.1和HTTP/2所基于的基于TCP的協(xié)議)。
它將在協(xié)議中包括HTTPS,因此HTTP/3僅可通過HTTPS使用。
HTTP/2到底有哪些具體變化?
二進制分幀
先來理解幾個概念:
幀:HTTP/2數(shù)據(jù)通信的最小單位。
消息:指 HTTP/2 中邏輯上的 HTTP 消息,例如請求和響應(yīng)等,消息由一個或多個幀組成。
流:存在于連接中的一個虛擬通道。流可以承載雙向消息,每個流都有一個唯一的整數(shù)ID。
HTTP/2采用二進制格式傳輸數(shù)據(jù),而非HTTP1.x的文本格式,二進制協(xié)議解析起來更高效。
HTTP / 1 的請求和響應(yīng)報文,都是由起始行、首部和實體正文(可選)組成,各部分之間以文本換行符分隔。
HTTP/2 將請求和響應(yīng)數(shù)據(jù)分割為更小的幀,并且它們采用二進制編碼。
HTTP/2 中,同域名下所有通信都在單個連接上完成,該連接可以承載任意數(shù)量的雙向數(shù)據(jù)流。
每個數(shù)據(jù)流都以消息的形式發(fā)送,而消息又由一個或多個幀組成,多個幀之間可以亂序發(fā)送,根據(jù)幀首部的流標識可以重新組裝。
多路復用
多路復用,代替原來的序列和阻塞機制, 所有請求都是通過一個TCP連接并發(fā)完成。
HTTP 1.x 中,如果想并發(fā)多個請求,必須使用多個TCP連接,且瀏覽器為了控制資源,還會對單個域名有 6-8個的TCP連接請求限制,如下圖,紅色圈出來的請求就因域名鏈接數(shù)已超過限制,而被掛起等待了一段時間:

在 HTTP/2 中,有了二進制分幀之后,HTTP/2不再依賴 TCP連接去實現(xiàn)多流并行了,在 HTTP/2中:
?同域名下所有通信都在單個連接上完成。?單個連接可以承載任意數(shù)量的雙向數(shù)據(jù)流。?數(shù)據(jù)流以消息的形式發(fā)送,而消息又由一個或多個幀組成,多個幀之間可以亂序發(fā)送,因為根據(jù)幀首部的流標識可以重新組裝。
這一特性,使性能有了極大提升:
?同個域名只需要占用一個 TCP 連接,消除了因多個 TCP 連接而帶來的延時和內(nèi)存消耗。?單個連接上可以并行交錯的請求和響應(yīng),之間互不干擾。?在HTTP/2中,每個請求都可以帶一個31bit的優(yōu)先值,0表示最高優(yōu)先級, 數(shù)值越大優(yōu)先級越低。有了這個優(yōu)先值,客戶端和服務(wù)器就可以在處理不同的流時采取不同的策略,以最優(yōu)的方式發(fā)送流、消息和幀。
服務(wù)器推送
服務(wù)端可以在發(fā)送頁面HTML時主動推送其它資源,而不用等到瀏覽器解析到相應(yīng)位置,發(fā)起請求再響應(yīng)。
例如服務(wù)端可以主動把JS和CSS文件推送給客戶端,而不需要客戶端解析HTML時再發(fā)送這些請求。
服務(wù)端可以主動推送,客戶端也有權(quán)利選擇是否接收。如果服務(wù)端推送的資源已經(jīng)被瀏覽器緩存過,瀏覽器可以通過發(fā)送RST_STREAM幀來拒收。主動推送也遵守同源策略,服務(wù)器不會隨便推送第三方資源給客戶端。
頭部壓縮
HTTP 1.1請求的大小變得越來越大,有時甚至會大于TCP窗口的初始大小,因為它們需要等待帶著ACK的響應(yīng)回來以后才能繼續(xù)被發(fā)送。
HTTP/2對消息頭采用HPACK(專為http/2頭部設(shè)計的壓縮格式)進行壓縮傳輸,能夠節(jié)省消息頭占用的網(wǎng)絡(luò)的流量。而HTTP/1.x每次請求,都會攜帶大量冗余頭信息,浪費了很多帶寬資源。
HTTP每一次通信都會攜帶一組頭部,用于描述這次通信的的資源、瀏覽器屬性、cookie等,例如

為了減少這塊的資源消耗并提升性能, HTTP/2對這些首部采取了壓縮策略:
?HTTP/2在客戶端和服務(wù)器端使用“首部表”來跟蹤和存儲之前發(fā)送的鍵-值對,對于相同的數(shù)據(jù),不再通過每次請求和響應(yīng)發(fā)送;?首部表在HTTP/2的連接存續(xù)期內(nèi)始終存在,由客戶端和服務(wù)器共同漸進地更新;?每個新的首部鍵-值對要么被追加到當前表的末尾,要么替換表中之前的值。
例如:下圖中的兩個請求, 請求一發(fā)送了所有的頭部字段,第二個請求則只需要發(fā)送差異數(shù)據(jù),這樣可以減少冗余數(shù)據(jù),降低開銷。

我們來看一個實際的例子,下面是用WireShark抓取的訪問google首頁的包:

上圖是是訪問https://www.google.com/抓到的第一個請求的頭部,可以看到頭部的內(nèi)容,總共占用了437 bytes,我們選中頭部的cookie,可以看到cookie總共占用了118 bytes。接下來我們看看第二個請求的頭部:

從上圖可以看到,得益于頭部壓縮,第二個請求中cookie只占用了1個字節(jié),我們來看看變化了的Accept字段:

由于Accept字段與請求一中的內(nèi)容不同,需要發(fā)送給服務(wù)器,所以占用了29 bytes。
結(jié)語
HTTP/2的通過支持請求與響應(yīng)的多路復用來減少延遲,通過壓縮HTTP首部字段將協(xié)議開銷降至最低,同時增加對請求優(yōu)先級和服務(wù)器端推送的支持。
Ref
- https://zhuanlan.zhihu.com/p/26559480
