HTTP 3.0 是 HTTP 協(xié)議的第三個(gè)主要版本,前兩個(gè)分別是 HTTP 1.0 和 HTTP 2.0 ,但其實(shí) HTTP 1.1 我認(rèn)為才是真正的 HTTP 1.0。
如果你對 HTTP 1.1 和 HTTP 2.0 不太了解的話,可以閱讀筆者的這兩篇文章。
看完這篇HTTP,跟面試官扯皮就沒問題了
HTTP 2.0 ,有點(diǎn)炸 !
我們大家知道,HTTP 是應(yīng)用層協(xié)議,應(yīng)用層產(chǎn)生的數(shù)據(jù)會(huì)通過傳輸層協(xié)議作為載體來傳輸?shù)交ヂ?lián)網(wǎng)上的其他主機(jī)中,而其中的載體就是 TCP 協(xié)議,這是 HTTP 2 之前的主流模式。
但是隨著 TCP 協(xié)議的缺點(diǎn)不斷暴露出來,新一代的 HTTP 協(xié)議 - HTTP 3.0 毅然決然切斷了和 TCP 的聯(lián)系,轉(zhuǎn)而擁抱了 UDP 協(xié)議,這么說不太準(zhǔn)確,其實(shí) HTTP 3.0 其實(shí)是擁抱了QUIC 協(xié)議,而 QUIC 協(xié)議是建立在 UDP 協(xié)議基礎(chǔ)上的。
HTTP 3.0
HTTP 3.0 于 2022 年 6 月 6 日正式發(fā)布,IETF 把 HTTP 3.0 標(biāo)準(zhǔn)制定在了 RFC 9114 中,HTTP 3.0 其實(shí)相較于 HTTP 2.0 要比 HTTP 2.0 相較于 HTTP 1.1 的變化來說小很多,最大的提升就在于效率,替換 TCP 協(xié)議為 UDP 協(xié)議,HTTP 3.0 具有更低的延遲,它的效率甚至要比 HTTP 1.1 快 3 倍以上。
其實(shí)每一代 HTTP 協(xié)議的不斷發(fā)展都是建立在上一代 HTTP 的缺點(diǎn)上的,就比如 HTTP 1.0 最大的問題就是傳輸安全性和不支持持久連接上,針對此出現(xiàn)了 HTTP 1.1 ,引入了 Keep-Alive 機(jī)制來保持長鏈接和 TLS 來保證通信安全性。但此時(shí)的 HTTP 協(xié)議并發(fā)性還做的不夠好。
隨著網(wǎng)絡(luò)的不斷發(fā)展,每個(gè)網(wǎng)站所需資源(CSS、JavaScript、圖像等)的數(shù)量逐年增加,瀏覽器發(fā)現(xiàn)自己在獲取和呈現(xiàn)網(wǎng)頁時(shí)需要越來越多的并發(fā)性。但是由于 HTTP 1.1 只能夠允許客戶端/服務(wù)器進(jìn)行一次 HTTP 請求交換,因此在網(wǎng)絡(luò)層獲得并發(fā)性的唯一方法是并行使用多個(gè) TCP 連接到同一個(gè)源,不過使用多個(gè) TCP 鏈接就失去了 ?keep-Alive 的意義。
然后出現(xiàn)了 SPDY 協(xié)議,主要解決 HTTP 1.1 效率不高的問題,包括降低延遲,壓縮 header 等等,這些已經(jīng)被 Chrome 瀏覽器證明能夠產(chǎn)生優(yōu)化效果,后來 HTTP 2.0 基于 SPDY ,并且引入了 **流( Stream )**的概念,它允許將不同的 HTTP 交換多路復(fù)用到同一個(gè) TCP 連接上,從而達(dá)到讓瀏覽器重用 TCP 鏈接的目的。
TCP 的主要作用是以正確的順序?qū)⒄麄€(gè)字節(jié)流從一個(gè)端點(diǎn)傳輸?shù)搅硪粋€(gè)端點(diǎn),但是當(dāng)流中的某些數(shù)據(jù)包丟失時(shí),TCP 需要重新發(fā)送這些丟失的數(shù)據(jù)包,等到丟失的數(shù)據(jù)包到達(dá)對應(yīng)端點(diǎn)時(shí)才能夠被 HTTP 處理,這被稱為 TCP 隊(duì)頭阻塞問題。
那么可能就會(huì)有人考慮到去修改 TCP 協(xié)議,其實(shí)這已經(jīng)是一件不可能完成的任務(wù)了。因?yàn)?TCP 存在的時(shí)間實(shí)在太長,已經(jīng)充斥在各種設(shè)備中,并且這個(gè)協(xié)議是由操作系統(tǒng)實(shí)現(xiàn)的,更新起來不大現(xiàn)實(shí)。
基于這個(gè)原因,Google 就更起爐灶搞了一個(gè)基于 UDP 協(xié)議的 QUIC 協(xié)議,并且使用在了 HTTP/3 上,HTTP/3 之前名為 HTTP-over-QUIC,從這個(gè)名字中我們也可以發(fā)現(xiàn),HTTP/3 最大的改造就是使用了 QUIC。
QUIC 協(xié)議
QUIC 的小寫是 quic,諧音 quick,意思就是快。它是 Google 提出來的一個(gè)基于 UDP 的傳輸協(xié)議,所以 QUIC 又被叫做快速 UDP 互聯(lián)網(wǎng)連接。
首先 QUIC 的第一個(gè)特征就是快,為什么說它快,它到底快在哪呢?
我們大家知道,HTTP 協(xié)議在傳輸層是使用了 TCP 進(jìn)行報(bào)文傳輸,而且 HTTPS 、HTTP/2.0 還采用了 TLS 協(xié)議進(jìn)行加密,這樣就會(huì)導(dǎo)致三次握手的連接延遲:即 TCP 三次握手(一次)和 TLS 握手(兩次),如下圖所示。
對于很多短連接場景,這種握手延遲影響較大,而且無法消除。畢竟 RTT 是人類和效率的終極斗爭。
相比之下,QUIC 的握手連接更快,因?yàn)樗褂昧?UDP 作為傳輸層協(xié)議,這樣能夠減少三次握手的時(shí)間延遲。而且 QUIC 的加密協(xié)議采用了 TLS 協(xié)議的最新版本 TLS 1.3,相對之前的 TLS 1.1-1.2,TLS1.3 允許客戶端無需等待 TLS 握手完成就開始發(fā)送應(yīng)用程序數(shù)據(jù)的操作,可以支持1 RTT 和 0 RTT,從而達(dá)到快速建立連接的效果。
我們上面還說過,HTTP/2.0 雖然解決了隊(duì)頭阻塞問題,但是其建立的連接還是基于 TCP,無法解決請求阻塞問題。
而 UDP 本身沒有建立連接這個(gè)概念,并且 QUIC 使用的 stream 之間是相互隔離的,不會(huì)阻塞其他 stream 數(shù)據(jù)的處理,所以使用 UDP 并不會(huì)造成隊(duì)頭阻塞。
在 TCP 中,TCP 為了保證數(shù)據(jù)的可靠性,使用了序號+確認(rèn)號機(jī)制來實(shí)現(xiàn),一旦帶有 synchronize sequence number 的包發(fā)送到服務(wù)器,服務(wù)器都會(huì)在一定時(shí)間內(nèi)進(jìn)行響應(yīng),如果過了這段時(shí)間沒有響應(yīng),客戶端就會(huì)重傳這個(gè)包,直到服務(wù)器收到數(shù)據(jù)包并作出響應(yīng)為止。
那么 TCP 是如何判斷它的重傳超時(shí)時(shí)間呢?
TCP 一般采用的是自適應(yīng)重傳算法,這個(gè)超時(shí)時(shí)間會(huì)根據(jù)往返時(shí)間 RTT 動(dòng)態(tài)調(diào)整的。每次客戶端都會(huì)使用相同的 syn 來判斷超時(shí)時(shí)間,導(dǎo)致這個(gè) RTT 的結(jié)果計(jì)算的不太準(zhǔn)確。
雖然 QUIC 沒有使用 TCP 協(xié)議,但是它也保證了可靠性,QUIC 實(shí)現(xiàn)可靠性的機(jī)制是使用了 Packet Number,這個(gè)序列號可以認(rèn)為是 synchronize ?sequence number 的替代者,這個(gè)序列號也是遞增的。與 syn 所不同的是,不管服務(wù)器有沒有接收到數(shù)據(jù)包,這個(gè) Packet Number 都會(huì) + 1,而 syn 是只有服務(wù)器發(fā)送 ack 響應(yīng)之后,syn 才會(huì) + 1。
比如有一個(gè) PN = 10 的數(shù)據(jù)包在發(fā)送的過程中由于某些原因遲遲沒到服務(wù)器,那么客戶端會(huì)重傳一個(gè) PN = 11 的數(shù)據(jù)包,經(jīng)過一段時(shí)間后客戶端收到 PN = 10 的響應(yīng)后再回送響應(yīng)報(bào)文,此時(shí)的 RTT 就是 PN = 10 這個(gè)數(shù)據(jù)包在網(wǎng)絡(luò)中的生存時(shí)間,這樣計(jì)算相對比較準(zhǔn)確。
雖然 QUIC 保證了數(shù)據(jù)包的可靠性,但是數(shù)據(jù)的可靠性是如何保證的呢?
QUIC 引入了一個(gè) stream offset 的概念,一個(gè) stream 可以傳輸多個(gè) stream offset,每個(gè) stream offset 其實(shí)就是一個(gè) PN 標(biāo)識的數(shù)據(jù),即使某個(gè) PN 標(biāo)識的數(shù)據(jù)丟失,PN + 1 后,它重傳的仍舊是 PN 所標(biāo)識的數(shù)據(jù),等到所有 PN 標(biāo)識的數(shù)據(jù)發(fā)送到服務(wù)器,就會(huì)進(jìn)行重組,以此來保證數(shù)據(jù)可靠性。到達(dá)服務(wù)器的 stream offset 會(huì)按照順序進(jìn)行組裝,這同時(shí)也保證了數(shù)據(jù)的順序性。
眾所周知,TCP 協(xié)議的具體實(shí)現(xiàn)是由操作系統(tǒng)內(nèi)核來完成的,應(yīng)用程序只能使用,不能對內(nèi)核進(jìn)行修改,隨著移動(dòng)端和越來越多的設(shè)備接入互聯(lián)網(wǎng),性能逐漸成為一個(gè)非常重要的衡量指標(biāo)。雖然移動(dòng)網(wǎng)絡(luò)發(fā)展的非??欤怯脩舳说母聟s非常緩慢,我仍然看見有很多地區(qū)很多計(jì)算機(jī)還仍舊使用 xp 系統(tǒng),盡管它早已發(fā)展了很多年。服務(wù)端系統(tǒng)不依賴用戶升級,但是由于操作系統(tǒng)升級涉及到底層軟件和運(yùn)行庫的更新,所以也比較保守和緩慢。
QUIC 協(xié)議的一個(gè)重要特點(diǎn)就是可插拔性,能夠動(dòng)態(tài)更新和升級,QUIC 在應(yīng)用層實(shí)現(xiàn)了擁塞控制算法,不需要操作系統(tǒng)和內(nèi)核的支持,遇到擁塞控制算法切換時(shí),只需要在服務(wù)器重新加載一邊即可,不需要停機(jī)和重啟。
我們知道 TCP 的流量控制是通過滑動(dòng)窗口來實(shí)現(xiàn)的,如果你對滑動(dòng)窗口不太熟悉,你可以看下我寫的這篇文章
TCP 基礎(chǔ)知識
在文章后面有提到了滑動(dòng)窗口的一些概念。
而 QUIC 也實(shí)現(xiàn)了流量控制,QUIC 的流量控制也是使用了窗口更新 window_update,來告訴對端它可以接受的字節(jié)數(shù)。
TCP 協(xié)議頭部沒有經(jīng)過加密和認(rèn)證,所以在傳輸?shù)倪^程中很可能被篡改,與之不同的是,QUIC 中的報(bào)文頭部都是經(jīng)過認(rèn)證,報(bào)文也經(jīng)過加密處理。這樣只要對 QUIC 的報(bào)文有任何修改,接收端都能夠及時(shí)發(fā)現(xiàn),保證了安全性。
總的來說,QUIC 具有下面這些優(yōu)勢
使用 UDP 協(xié)議,不需要三次連接進(jìn)行握手,而且也會(huì)縮短 TLS 建立連接的時(shí)間。
解決了隊(duì)頭阻塞問題。
實(shí)現(xiàn)動(dòng)態(tài)可插拔,在應(yīng)用層實(shí)現(xiàn)了擁塞控制算法,可以隨時(shí)切換。
報(bào)文頭和報(bào)文體分別進(jìn)行認(rèn)證和加密處理,保障安全性。
連接能夠平滑遷移。
連接平滑遷移指的是,你的手機(jī)或者移動(dòng)設(shè)備在 4G 信號下和 WiFi 等網(wǎng)絡(luò)情況下切換,不會(huì)斷線重連,用戶甚至無任何感知,能夠直接實(shí)現(xiàn)平滑的信號切換。
QUCI 協(xié)議已經(jīng)被寫在了 RFC 9000 中。
審核編輯:湯梓紅
評論
查看更多