HTTP1.0,HTTP2,HTTP3的進化過程

發(fā)表日期:2022-04-15 文章編輯:洛壹網(wǎng)絡(luò) 文章來源:網(wǎng)站建設(shè)公司

    從 1989 年萬維網(wǎng)(www)誕生,HTTP(HyperText Transfer Protocol)經(jīng)歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發(fā)明。1996 年出現(xiàn)了 HTTP1.0。2015 年 HTTP2 正式發(fā)布。2020 年 HTTP3 或能正式使用。以下將會簡單介紹。


HTTP1.1 與 HTTP2
HTTP1.1 的缺陷

    高延遲 — 隊頭阻塞(Head-Of-Line Blocking)

    無狀態(tài)特性 — 阻礙交互

    明文傳輸 — 不安全性

    不支持服務(wù)端推送

隊頭阻塞

隊頭阻塞是指當(dāng)順序發(fā)送的請求序列中的一個請求因為某種原因被阻塞時,在后面排隊的所有請求也一并被阻塞,會導(dǎo)致客戶端遲遲收不到數(shù)據(jù)。

針對隊頭阻塞:

1.將同一頁面的資源分散到不同域名下,提升連接上限。雖然能公用一個 TCP 管道,但是在一個管道中同一時刻只能處理一個請求,在當(dāng)前的請求沒有結(jié)束之前,其他的請求只能處于阻塞狀態(tài)。

2.減少請求數(shù)量

3.內(nèi)聯(lián)一些資源:css、base64 圖片等

4.合并小文件減少資源數(shù)
無狀態(tài)特性

無狀態(tài)是指協(xié)議對于連接狀態(tài)沒有記憶能力。純凈的 HTTP 是沒有 cookie 等機制的,每一個連接都是一個新的連接。上一次請求驗證了用戶名密碼,而下一次請求服務(wù)器并不知道它與上一條請求有何關(guān)聯(lián),換句話說就是掉登錄態(tài)。
不安全性

傳輸內(nèi)容沒有加密,中途可能被篡改和劫持。
SPDY 協(xié)議

SPDY 是由 google 推行的改進版本的 HTTP1.1 (那時候還沒有 HTTP2)。

特性:

    多路復(fù)用 — 解決隊頭阻塞

    頭部壓縮 — 解決巨大的 HTTP 頭部

    請求優(yōu)先級 — 先獲取重要數(shù)據(jù)

    服務(wù)端推送 — 填補空缺

    提高安全性

多路復(fù)用

SPDY 允許在一個連接上無限制并發(fā)流。因為請求在一個通道上,TCP 效率更高(參考 TCP 擁塞控制 中的慢啟動)。更少的網(wǎng)絡(luò)連接,發(fā)出更密集的包。
頭部壓縮

使用專門的 HPACK 算法,每次請求和響應(yīng)只發(fā)送差異頭部,一般可以達(dá)到 50% ~90% 的高壓縮率。
請求優(yōu)先級

雖然無限的并發(fā)流解決了隊頭阻塞的問題,但如果帶寬受限,客戶端可能會因防止堵塞通道而阻止請求。在網(wǎng)絡(luò)通道被非關(guān)鍵資源堵塞時,高優(yōu)先級的請求會被優(yōu)先處理。
服務(wù)端推送

服務(wù)端推送(ServerPush),可以讓服務(wù)端主動把資源文件推送給客戶端。當(dāng)然客戶端也有權(quán)利選擇是否接收。
提高安全性

支持使用 HTTPS 進行加密傳輸。

HTTP2

HTTP2 基于 SPDY,專注于性能,最大的一個目標(biāo)是在用戶和網(wǎng)站間只用一個連接。

新增特性:

    二進制分幀 - HTTP2 性能增強的核心

    多路復(fù)用 - 解決串行的文件傳輸和連接數(shù)過多

二進制分幀

首先,HTTP2 沒有改變 HTTP1 的語義,只是在應(yīng)用層使用二進制分幀方式傳輸。因此,也引入了新的通信單位:幀、消息、流。

分幀有什么好處?服務(wù)器單位時間接收到的請求數(shù)變多,可以提高并發(fā)數(shù)。最重要的是,為多路復(fù)用提供了底層支持。
多路復(fù)用

一個域名對應(yīng)一個連接,一個流代表了一個完整的請求-響應(yīng)過程。幀是最小的數(shù)據(jù)單位,每個幀會標(biāo)識出該幀屬于哪個流,流也就是多個幀組成的數(shù)據(jù)流。多路復(fù)用,就是在一個 TCP 連接中可以存在多個流。演示
圖片.png
HTTP2 的缺陷

    TCP 以及 TCP+TLS 建立連接的延時

    TCP 的隊頭阻塞并沒有徹底解決

    多路復(fù)用導(dǎo)致服務(wù)器壓力上升

    多路復(fù)用容易 Timeout


建連延時

TCP 連接需要和服務(wù)器進行三次握手,即消耗完 1.5 個 RTT 之后才能進行數(shù)據(jù)傳輸。

TLS 連接有兩個版本—— TLS1.2 和 TLS1.3,每個版本建立連接所花的時間不同,大致需要 1~2 個 RTT。

RTT(Round-Trip Time):往返時延。表示從發(fā)送端發(fā)送數(shù)據(jù)開始,到發(fā)送端收到來自接收端的確認(rèn)(接收端收到數(shù)據(jù)后便立即發(fā)送確認(rèn)),總共經(jīng)歷的時延。
隊頭阻塞沒有徹底解決

TCP 為了保證可靠傳輸,有一個“超時重傳”機制,丟失的包必須等待重傳確認(rèn)。HTTP2 出現(xiàn)丟包時,整個 TCP 都要等待重傳,那么就會阻塞該 TCP 連接中的所有請求。
圖片

RTO:英文全稱是 Retransmission TimeOut,即重傳超時時間;RTO 是一個動態(tài)值,會根據(jù)網(wǎng)絡(luò)的改變而改變。RTO 是根據(jù)給定連接的往返時間 RTT 計算出來的。接收方返回的 ack 是希望收到的下一組包的序列號。
多路復(fù)用導(dǎo)致服務(wù)器壓力上升

多路復(fù)用沒有限制同時請求數(shù)。請求的平均數(shù)量與往常相同,但實際會有許多請求的短暫爆發(fā),導(dǎo)致瞬時 QPS 暴增。
多路復(fù)用容易 Timeout

大批量的請求同時發(fā)送,由于 HTTP2 連接內(nèi)存在多個并行的流,而網(wǎng)絡(luò)帶寬和服務(wù)器資源有限,每個流的資源會被稀釋,雖然它們開始時間相差更短,但卻都可能超時。

即使是使用 Nginx 這樣的負(fù)載均衡器,想正確進行節(jié)流也可能很棘手。其次,就算你向應(yīng)用程序引入或調(diào)整排隊機制,但一次能處理的連接也是有限的。如果對請求進行排隊,還要注意在響應(yīng)超時后丟棄請求,以避免浪費不必要的資源。引用

QUIC
簡介

Google
在推 SPDY 的時候就已經(jīng)意識到了這些問題,于是就另起爐灶搞了一個基于 UDP 協(xié)議的 QUIC 協(xié)議。而這個就是 HTTP3。它真正“完美”地解決了“隊頭阻塞”問題。
圖片
主要特點

    改進的擁塞控制、可靠傳輸

    快速握手

    集成了 TLS 1.3 加密

    多路復(fù)用

    連接遷移

改進的擁塞控制、可靠傳輸

從擁塞算法和可靠傳輸本身來看,QUIC 只是按照 TCP 協(xié)議重新實現(xiàn)了一遍,那么 QUIC 協(xié)議到底改進在哪些方面呢?主要有如下幾點:

1. 可插拔 — 應(yīng)用程序?qū)用婢湍軐崿F(xiàn)不同的擁塞控制算法。

一個應(yīng)用程序的不同連接也能支持配置不同的擁塞控制。應(yīng)用程序不需要停機和升級就能實現(xiàn)擁塞控制的變更,可以針對不同業(yè)務(wù),不同網(wǎng)絡(luò)制式,甚至不同的 RTT,使用不同的擁塞控制算法。

關(guān)于應(yīng)用層的可插拔擁塞控制模擬,可以對 socket 上的流為對象進行實驗。

2. 單調(diào)遞增的 Packet Number — 使用 Packet Number 代替了 TCP 的 seq。

每個 Packet Number 都嚴(yán)格遞增,也就是說就算 Packet N 丟失了,重傳的 Packet N 的 Packet Number 已經(jīng)不是 N,而是一個比 N 大的值。而 TCP 重傳策略存在二義性,比如客戶端發(fā)送了一個請求,一個 RTO 后發(fā)起重傳,而實際上服務(wù)器收到了第一次請求,并且響應(yīng)已經(jīng)在路上了,當(dāng)客戶端收到響應(yīng)后,得出的 RTT 將會比真實 RTT 要小。當(dāng) Packet N 唯一之后,就可以計算出正確的 RTT。

3. 不允許 Reneging — 一個 Packet 只要被 Ack,就認(rèn)為它一定被正確接收。

Reneging 的意思是,接收方有權(quán)把已經(jīng)報給發(fā)送端 SACK(Selective Acknowledgment) 里的數(shù)據(jù)給丟了(如接收窗口不夠而丟棄亂序的包)。

QUIC 中的 ACK 包含了與 TCP 中 SACK 等價的信息,但 QUIC 不允許任何(包括被確認(rèn)接受的)數(shù)據(jù)包被丟棄。這樣不僅可以簡化發(fā)送端與接收端的實現(xiàn)難度,還可以減少發(fā)送端的內(nèi)存壓力。

4. 前向糾錯(FEC)

早期的 QUIC 版本存在一個丟包恢復(fù)機制,但后來由于增加帶寬消耗和效果一般而廢棄。FEC 中,QUIC 數(shù)據(jù)幀的數(shù)據(jù)混合原始數(shù)據(jù)和冗余數(shù)據(jù),來確保無論到達(dá)接收端的 n 次傳輸內(nèi)容是什么,接收端都能夠恢復(fù)所有 n 個原始數(shù)據(jù)包。FEC 的實質(zhì)就是異或。示意圖:
圖片

5. 更多的 Ack 塊和增加 Ack Delay 時間。

QUIC 可以同時提供 256 個 Ack Block,因此在重排序時,QUIC 相對于 TCP(使用 SACK)更有彈性,這也使得在重排序或丟失出現(xiàn)時,QUIC 可以在網(wǎng)絡(luò)上保留更多的在途字節(jié)。在丟包率比較高的網(wǎng)絡(luò)下,可以提升網(wǎng)絡(luò)的恢復(fù)速度,減少重傳量。

TCP 的 Timestamp 選項存在一個問題:發(fā)送方在發(fā)送報文時設(shè)置發(fā)送時間戳,接收方在確認(rèn)該報文段時把時間戳字段值復(fù)制到確認(rèn)報文時間戳,但是沒有計算接收端接收到包到發(fā)送 Ack 的時間。這個時間可以簡稱為 Ack Delay,會導(dǎo)致 RTT 計算誤差。現(xiàn)在就是把這個東西加進去計算 RTT 了。

6. 基于 stream 和 connection 級別的流量控制。

為什么需要兩類流量控制呢?主要是因為 QUIC 支持多路復(fù)用。Stream 可以認(rèn)為就是一條 HTTP 請求。Connection 可以類比一條 TCP 連接。多路復(fù)用意味著在一條 Connetion 上會同時存在多條 Stream。

QUIC 接收者會通告每個流中最多想要接收到的數(shù)據(jù)的絕對字節(jié)偏移。隨著數(shù)據(jù)在特定流中的發(fā)送,接收和傳送,接收者發(fā)送 WINDOW_UPDATE 幀,該幀增加該流的通告偏移量限制,允許對端在該流上發(fā)送更多的數(shù)據(jù)。

除了每個流的流控制外,QUIC 還實現(xiàn)連接級的流控制,以限制 QUIC 接收者愿意為連接分配的總緩沖區(qū)。連接的流控制工作方式與流的流控制一樣,但傳送的字節(jié)和最大的接收偏移是所有流的總和。

最重要的是,我們可以在內(nèi)存不足或者上游處理性能出現(xiàn)問題時,通過流量控制來限制傳輸速率,保障服務(wù)可用性。
圖片

快速握手

由于 QUIC 是基于 UDP 的,所以 QUIC 可以實現(xiàn) 0-RTT 或者 1-RTT 來建立連接,可以大大提升首次打開頁面的速度。
集成了 TLS 1.3 加密

TLS 1.3 支持 3 種基本密鑰交換模式:

(EC)DHE (基于有限域或橢圓曲線的 Diffie-Hellman)
PSK - only
PSK with (EC)DHE

在完全握手情況下,需要 1-RTT 建立連接。TLS1.3 恢復(fù)會話可以直接發(fā)送加密后的應(yīng)用數(shù)據(jù),不需要額外的 TLS 握手,也就是 0-RTT。

TLS 1.3 0-RTT 簡單原理示意(基于 DHE):
圖片

但是 TLS1.3 也并不完美。TLS 1.3 的 0-RTT 無法保證前向安全性(Forward secrecy)。簡單講就是,如果當(dāng)攻擊者通過某種手段獲取到了 Session Ticket Key,那么該攻擊者可以解密以前的加密數(shù)據(jù)。

要緩解該問題可以通過設(shè)置使得與 Session Ticket Key 相關(guān)的 DH 靜態(tài)參數(shù)在短時間內(nèi)過期(一般幾個小時)。

多路復(fù)用

QUIC 是為多路復(fù)用從頭設(shè)計的,攜帶個別流的的數(shù)據(jù)的包丟失時,通常只影響該流。QUIC 連接上的多個 stream 之間并沒有依賴,也不會有底層協(xié)議限制。假如 stream2 丟了一個包,也只會影響 stream2 的處理。
連接遷移

TCP 是按照 4 要素(客戶端 IP、端口, 服務(wù)器 IP、端口)確定一個連接的。而 QUIC 則是讓客戶端生成一個 Connection ID (64 位)來區(qū)別不同連接。只要 Connection ID 不變,連接就不需要重新建立,即便是客戶端的網(wǎng)絡(luò)發(fā)生變化。由于遷移客戶端繼續(xù)使用相同的會話密鑰來加密和解密數(shù)據(jù)包,QUIC 還提供了遷移客戶端的自動加密驗證。

挑戰(zhàn)
NAT 問題
NAT 概念

為了解決 IP 地址不足的問題,NAT 給一個局域網(wǎng)絡(luò)只分配一個 IP 地址,這個網(wǎng)絡(luò)內(nèi)的主機,則分配私有地址,這些私有地址對外是不可見的,他們對外的通信都要借助那個唯一分配的 IP 地址。所有離開本地網(wǎng)絡(luò)去往 Internet 的數(shù)據(jù)報的源 IP 地址需替換為相同的 NAT,區(qū)別僅在于端口號不同。
圖片
原因

TCP 和 UDP 的報文頭部不同導(dǎo)致 NAT 問題的出現(xiàn)。
NAT 設(shè)備的端口記憶問題

對于基于 TCP 的 HTTP、HTTPS 傳輸,NAT 設(shè)備可以根據(jù) TCP 報文頭的 SYN/FIN 狀態(tài)位,知道通信什么時候開始,什么時候結(jié)束,對應(yīng)記憶 NAT 映射的開始和結(jié)束。

但是基于 UDP 傳輸?shù)?HTTP3 ,不存在 SYN/FIN 狀態(tài)位。NAT 設(shè)備的記憶如果短于用戶會話時間,則用戶會話會中斷。NAT 設(shè)備的記憶時間如果長于用戶會話時間,則意味著 NAT 設(shè)備的端口資源會被白白占用。

最直接的解決方案是,在 QUIC 的頭部模仿 TCP 的 SYN/FIN 狀態(tài),讓沿途的 NAT 設(shè)備知道會話什么時候開始、什么時候結(jié)束。但這需要升級全球所有的 NAT 設(shè)備的軟件。

另外一個可行的方案是,讓 QUIC 周期性地發(fā)送 Keepalive 消息,刷新 NAT 設(shè)備的記憶,避免 NAT 設(shè)備自動釋放。
NAT 設(shè)備禁用 UDP

在一些 NAT 網(wǎng)絡(luò)環(huán)境下(如某些校園網(wǎng)),UDP 協(xié)議會被路由器等中間網(wǎng)絡(luò)設(shè)備禁止,這時客戶端會直接降級,選擇 HTTPS 等備選通道,保證正常業(yè)務(wù)請求。
NGINX 負(fù)載均衡問題概念

QUIC 客戶端存在網(wǎng)絡(luò)制式切換,就算是同一個移動機房,可能第一次業(yè)務(wù)請求時會落到 A 這臺服務(wù)器,后續(xù)再次連接,就會落到 B 實例上,重復(fù)走 1-RTT 的完整握手流程。
全局握手緩存

為所有 QUIC 服務(wù)器實例建立一個全局握手緩存。當(dāng)用戶網(wǎng)絡(luò)發(fā)生切換時,下一次的業(yè)務(wù)請求無論是落到哪一個機房或哪一臺實例上,握手建連都會是 0-RTT。

歷代 HTTP 速度測試


結(jié)尾

從古至今實時數(shù)據(jù)傳輸(音頻、視頻、游戲等)都面臨卡頓、延遲等問題,而 QUIC 基于 UDP 的架構(gòu)和改進的重傳等特性,能夠有效的提升用戶體驗。目前
B 站 也已經(jīng)接入 QUIC。

如果想要自己體驗 QUIC,可以使用 Libquic、Caddy 等。另外 github 上面也有 C++版本的 QUIC 實現(xiàn),利用 Nodejs 的 C++ 模塊,前端工程師也可以快速實現(xiàn)一個 node-quic。

您的瀏覽器版本太低

請升級您的瀏覽器: Internet Explorer11 或以下瀏覽器: Firefox  /  Chrome  /  360極速瀏覽器

国产亚洲首页精品_人人色欧美色2022_人人九九精品国产_国产上传中文字幕