QUIC的前世今生——HTTP演变史
1.HTTP演變史
在我們更深入地研究 HTTP/3之前,讓我們快速了解一下 HTTP 多年來的演變,以便更好地理解為什么需要HTTP/3:
1.1 HTTP 0.9:只有一行的協(xié)議
Tim Berners-Lee 最初的HTTP 建議是以簡潔為出發(fā)點設(shè)計的,目的是推動他的另一個剛剛萌芽的思想——萬維網(wǎng)的應(yīng)用。1991年,是一個單純的年代,網(wǎng)上只有文字,看不了圖。
請求只有一行,包括GET 方法和要請求的文檔的路徑。響應(yīng)是一個超文本文檔,沒有首部,也沒有其他元數(shù)據(jù),只有HTML。HTTP 0.9 的功能:
◎客戶端 / 服務(wù)器、請求 / 響應(yīng)協(xié)議;
◎ASCII 協(xié)議,運行于 TCP/IP 鏈接之上;
◎設(shè)計用來傳輸超文本文檔(HTML);
◎服務(wù)器與客戶端之間的連接在每次請求之后都會關(guān)閉。
1.2 HTTP 1.0:迅速發(fā)展及參考性RFC
1991 年到1995 年,HTML 規(guī)范和一種新型的名叫“Web 瀏覽器”的軟件都獲得了快速發(fā)展。于是,1996 年,HTTP 工作組發(fā)布了RFC 1945,在該文檔中記錄了許多HTTP/1.0實現(xiàn)的通用方法,于是HTTP/1.0就誕生了。HTTP 1.0 的請求對我們而言應(yīng)該是非常熟悉的:
請求行中包含HTTP 版本號,隨后是請求首部;響應(yīng)狀態(tài),后跟響應(yīng)首部。該協(xié)議的關(guān)鍵變化:
◎請求可以由于多行首部字段構(gòu)成;
◎響應(yīng)對象前面添加了一個響應(yīng)狀態(tài)行;
◎響應(yīng)對象也有自己的由換行符分隔的首部 字段;
◎響應(yīng)對象不局限于超文本;
◎服務(wù)器與客戶端之間的連接在每次請求之后都會關(guān)閉。
1.3 HTTP 1.1:互聯(lián)網(wǎng)標(biāo)準(zhǔn)
在1997年1月,發(fā)布了HTTP/1.1的第一個正式標(biāo)準(zhǔn) RFC2068[2]。然后,在兩年半之后的1999年6月,許多改進(jìn)和更新被納入該標(biāo)準(zhǔn),并以 RFC 2616[3]的形式發(fā)布。
◎新增了POTIONS、PUT、DELETE、TRACE、CONNECT等新方法;
◎強化了緩存管理和控制;
◎支持維持持久連接,支持通知服務(wù)器棄用連接;也就是說TCP連接默認(rèn)不關(guān)閉,可以被多個請求復(fù)用,不用聲明Connection: keep-alive;
◎請求HTML文件的時候要求攜帶編碼、字符集、cookie元數(shù)據(jù)等信息;
◎支持原始HTML請求的分塊響應(yīng),利于傳輸大文件;
HTTP 1.1 改變了HTTP 協(xié)議的語義,默認(rèn)使用持久連接。換句話說,除非明確告知(通過Connection: close 首部),否則服務(wù)器默認(rèn)會保持連接打開。不過,這個功能也反向移植到了HTTP 1.0,可以通過Connection: Keep-Alive 首部來啟用。實際上,如果你使用的是HTTP 1.1,從技術(shù)上說不需要Connection: Keep-Alive 首部,但很多客戶端還是選擇加上它。
1.4 HTTP 1.X的缺陷
- 連接無法復(fù)用
連接無法復(fù)用會導(dǎo)致每次請求都經(jīng)歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對大量小文件請求影響較大(沒有達(dá)到最大窗口請求就被終止)。
◎HTTP/1.0 傳輸數(shù)據(jù)時,每次都需要重新建立連接,增加延遲。
◎HTTP/1.1 加入 keep-alive 可以復(fù)用一部分連接,當(dāng)頁面上有大量元素時,這樣的等待會造成頁面內(nèi)容的順序加載,為了提高吞吐量,現(xiàn)在瀏覽器會對每個域名至多打開6個連接,并且重用它們。然而這樣的提速仍不滿足當(dāng)前的性能要求,為此還有切分域名域(Sharding Dominant Domains)等優(yōu)化方法。 - Head-Of-Line Blocking(HOLB)
導(dǎo)致帶寬無法被充分利用。HOLB是指一系列包(package)因為第一個包被阻塞;當(dāng)頁面中需要請求很多資源的時候,HOLB(隊頭阻塞)會導(dǎo)致在達(dá)到最大請求數(shù)量時,剩余的資源需要等待其他資源請求完成后才能發(fā)起請求。
◎HTTP 1.0:下個請求必須在前一個請求返回后才能發(fā)出,request-response對按序發(fā)生。顯然,如果某個請求長時間沒有返回,那么接下來的請求就全部阻塞了。
◎HTTP 1.1:嘗試使用 pipeling 來解決,即瀏覽器可以一次性發(fā)出多個請求(同個域名,同一條 TCP 鏈接)。但 pipeling 要求返回是按序的,那么前一個請求如果很耗時(比如處理大圖片),那么后面的請求即使服務(wù)器已經(jīng)處理完,仍會等待前面的請求處理完才開始按序返回。所以,pipeling 只部分解決了 HOLB。
1.5 HTTP 2.0:改進(jìn)傳輸性能
隨著我們越來越多地把應(yīng)用(社交媒體、電子郵件、新聞和視頻,以及個人的生活與工作內(nèi)容)部署到Web 上,HTTP 的問題也出現(xiàn)了。今天,用戶和Web 開發(fā)者都迫切想要通過HTTP 1.1 達(dá)到一種幾近實時的響應(yīng)速度和協(xié)議性能,而要滿足這個需求,僅靠在原協(xié)議基礎(chǔ)上修修補補是不夠的。
2015 年,HTTP/2 發(fā)布。HTTP/2 是現(xiàn)行 HTTP 協(xié)議(HTTP/1.x)的替代,但它不是重寫,HTTP 方法/狀態(tài)碼/語義都與 HTTP/1.x 一樣。HTTP/2 基于 SPDY3,專注于性能,最大的一個目標(biāo)是在用戶和網(wǎng)站間只用一個連接(connection),主要有如下功能:
◎使用虛擬的流傳輸消息,解決了HTTP一個連接中應(yīng)用層的隊頭阻塞的問題;
◎使用了二進(jìn)制協(xié)議,不再是純文本,避免文本歧義,縮小了請求體積;
◎?qū)崿F(xiàn)了多路復(fù)用,提高了連接的利用率,在擁塞控制方面有了更好的能力提升;
◎使用HPACK首部壓縮方案壓縮頭部信息,大大節(jié)約了帶寬;
◎增強了安全性,使用HTTP/2,要求必須至少用TLS1.2;
◎允許服務(wù)器主動向客戶端推送數(shù)據(jù);
在 HTTP/2 中引入了多路復(fù)用的技術(shù)。多路復(fù)用很好的解決了瀏覽器限制同一個域名下的請求數(shù)量的問題,同時也接更容易實現(xiàn)全速傳輸,畢竟新開一個 TCP 連接都需要慢慢提升傳輸速度。大家可以直觀感受下 HTTP/2 比 HTTP/1 到底快了多少。有關(guān)HTTP/2的原理實現(xiàn)資料可見文末的參考資料。
目前騰訊云CDN也已支持HTTP2,只需在官網(wǎng)控制臺對加速域名進(jìn)行配置,即可完成對資源的http2支持,不需要源站支持http2。
2.HTTP3
雖然 HTTP/2 解決了很多之前舊版本的問題,但是它還是存在一個巨大的問題,主要是底層支撐的 TCP 協(xié)議造成的。上文提到 HTTP/2 使用了多路復(fù)用,一般來說同一域名下只需要使用一個 TCP 連接。但當(dāng)這個連接中出現(xiàn)了丟包的情況,那就會導(dǎo)致 HTTP/2 的表現(xiàn)情況反倒不如 HTTP/1 了。因為在出現(xiàn)丟包的情況下,整個 TCP 都要開始等待重傳,也就導(dǎo)致了后面的所有數(shù)據(jù)都被阻塞了。但是對于 HTTP/1.1 來說,可以開啟多個 TCP 連接,出現(xiàn)這種情況反到只會影響其中一個連接,剩余的 TCP 連接還可以正常傳輸數(shù)據(jù)。
那么可能就會有人考慮到去修改 TCP 協(xié)議,其實這已經(jīng)是一件不可能完成的任務(wù)了。因為 TCP 存在的時間實在太長,已經(jīng)充斥在各種設(shè)備中,并且這個協(xié)議是由操作系統(tǒng)實現(xiàn)的,更新起來不大現(xiàn)實。基于這個原因,Google 就更起爐灶搞了一個基于 UDP 協(xié)議的 QUIC 協(xié)議,并且使用在了 HTTP/3 上,HTTP/3 之前名為 HTTP-over-QUIC,從這個名字中我們也可以發(fā)現(xiàn),HTTP/3 最大的改造就是使用了 QUIC。
由于HTTP/3還處于草案階段,這里只對HTTP/3功能更做一個整體的介紹,下面是整體的架構(gòu)圖:
上面我們談到到了 head-of-line blocking 的問題,這也是 HTTP3 最大改變的地方。它不使用 TCP 作為會話的傳輸層,而是使用 QUIC,一種新的互聯(lián)網(wǎng)傳輸協(xié)議,除其他外,它在傳輸層引入了流作為最優(yōu)先的傳輸。QUIC 流共享相同的 QUIC 連接,所以創(chuàng)建新的 QUIC 流不需要額外的握手和緩慢的啟動,但是 QUIC 流是獨立交付的,因此在大多數(shù)情況下,影響一個流的數(shù)據(jù)包丟失不會影響其他流,因為 QUIC 數(shù)據(jù)包封裝在 UDP 數(shù)據(jù)包之上。
與 TCP 相比,使用 UDP 提供了更多的靈活性,并且使 QUIC 實現(xiàn)安裝在用戶空間(user-space)中ーー對協(xié)議實現(xiàn)的更新不像 TCP 那樣與操作系統(tǒng)更新綁定在一起。使用 QUIC,HTTP 級別的流可以簡單地映射到 QUIC 流之上,從而獲得 HTTP/2的所有好處,而不會出現(xiàn)“head-of-line blocking”。
QUIC 還將典型的 3-way TCP 握手與 TLS 1.3 的握手相結(jié)合。組合這些步驟意味著默認(rèn)情況下提供了加密和身份驗證,并且還支持更快的連接建立。換句話說,即使 HTTP 會話中的初始請求需要一個新的 QUIC 連接,在數(shù)據(jù)開始流動之前產(chǎn)生的延遲也低于使用 TLS 的 TCP。
◎底層采用了UDP,通過在用戶空間的QUIC協(xié)議保證了傳輸?shù)目煽啃?#xff1b;
◎引入了Connection ID,不再需要向TCP那樣基于IP和端口進(jìn)行綁定連接,支持連接遷移,也就是說,從移動網(wǎng)絡(luò),切換到WIFI,可以繼續(xù)使用同一個連接;
◎頭部壓縮算法由HPACK替換為了QPACK,以便能夠支持亂序發(fā)送,優(yōu)化壓縮率;
◎QUIC包含了一個內(nèi)嵌的TLS1.3,因此支持1-RTT快速建立連接;
3.CDN中QUIC實踐
騰訊云CDN當(dāng)前已支持HTTP3,您可在官網(wǎng)產(chǎn)品文檔中找到QUIC內(nèi)測申請鏈接,通過內(nèi)測審核后,只需要將域名接入到官網(wǎng)控制臺,開啟QUIC功能,即可完成對資源的HTTP3支持,不需要源站做任何改動,當(dāng)前支持的QUIC版本有H3-Q050,Q046,Q043。訪問流程如下所示:
3.1 協(xié)議協(xié)商
一般情況下,Chrome瀏覽器和服務(wù)器端協(xié)商使用QUIC協(xié)議要經(jīng)過如下步驟:
客戶端發(fā)出tcp請求
服務(wù)端如果支持quic可以通過響應(yīng)頭alt-svc告知客戶端
客戶端同時發(fā)起tcp連接和quic連接競賽
一旦quic建立連接獲勝則采用quic協(xié)議發(fā)送請求
如遇網(wǎng)絡(luò)或服務(wù)器不支持quic/udp,客戶端標(biāo)記quic為broken
傳輸中的請求通過tcp重發(fā)
alt-svc 主要包含以下信息:
◎quic:監(jiān)聽的端口;
◎ma:有效時間,單位是秒,承諾在這段時間內(nèi)都支持 QUIC;
◎版本號:QUIC 的迭代很快,這里列出所有支持的版本號。
在完成域名接入后,使用Chrome訪問需要啟動QUIC,chrome版本88.0.4324.182(正式版本)默認(rèn)支持的QUIC協(xié)議是Q050:
wireshark抓包分析:
[1] Web性能權(quán)威指南
[2] 一文讀懂 HTTP/2 及 HTTP/3 特性
[3] HTTP/3 原理與實踐
[4] HTTP探索之路 - HTTP1/HTTP2/QUIC
[5] HTTP/3:讓傳輸效率再一次起飛 | QUIC
[6] HTTP3 協(xié)議
關(guān)注騰訊云CDN公眾號,技術(shù)干貨一手掌握!
總結(jié)
以上是生活随笔為你收集整理的QUIC的前世今生——HTTP演变史的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应用于CDN的GSLB系统
- 下一篇: 执着