<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          HTTP1 到 HTTP3 的工程優(yōu)化

          共 14869字,需瀏覽 30分鐘

           ·

          2023-08-29 17:28

          HTTP/1.0

          存在的問(wèn)題

          1. 默認(rèn)為短連接,連接無(wú)法復(fù)用,網(wǎng)頁(yè)中的每個(gè)資源都會(huì)發(fā)起新的 TCP 連接
          2. 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking), 一個(gè) HTTP 請(qǐng)求響應(yīng)結(jié)束之后,才能發(fā)起下一個(gè) HTTP 請(qǐng)求 (如果沒(méi)有某個(gè)特別慢的請(qǐng)求,就卡頓了 ...)
          3. 不支持范圍數(shù)據(jù)請(qǐng)求,即使只是需要某個(gè)資源的一部分內(nèi)容 (例如視頻的某一段幀),也會(huì)將整個(gè)資源發(fā)送過(guò)來(lái)

          這幾個(gè)問(wèn)題已經(jīng)全部消失在歷史長(zhǎng)河中了,這里簡(jiǎn)單回顧下,不做詳細(xì)介紹了。

          HTTP/1.1

          首先增加了以下特性解決了 HTTP/1.0 存在的問(wèn)題:

          • 默認(rèn)啟用長(zhǎng)連接
          • 支持同時(shí)打開(kāi)多個(gè) TCP 連接,采用 Pipeline 請(qǐng)求方式,多個(gè)請(qǐng)求可以通過(guò)多個(gè)連接串行化請(qǐng)求
          • 支持資源分塊范圍數(shù)據(jù)傳輸

          此外,還新增了以下新特性:

          • 支持虛擬主機(jī)
          • 新增 Cache-Control、E-Tag, max-age 緩存處理指令
          • 新增 PUT、PATCH、HEAD、OPTIONS、DELETE 請(qǐng)求方法

          依然存在的問(wèn)題

          • 雖然 TCP 連接可以復(fù)用,但是服務(wù)端響應(yīng)只能按照客戶端請(qǐng)求順序返回,隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 并沒(méi)有完全解決
          • 客戶端需要使用多個(gè)連接才能實(shí)現(xiàn)并發(fā)和縮短延遲
          • 無(wú)法壓縮請(qǐng)求和響應(yīng)頭部,導(dǎo)致不必要的數(shù)據(jù)傳輸流量
          • 不支持有效的資源優(yōu)先級(jí),導(dǎo)致 TCP 連接的利用率低

          HTTP/2

          HTTP/1 是文本協(xié)議,其中 Header 頭信息是文本數(shù)據(jù),內(nèi)容體數(shù)據(jù)可以是文本格式,也可以是二進(jìn)制格式。HTTP/2 是二進(jìn)制協(xié)議,Header 頭信息和內(nèi)容體數(shù)據(jù)都是二進(jìn)制的。

          二進(jìn)制分幀層

          HTTP/2 在 應(yīng)用層(HTTP/2)和傳輸層(TCP or UDP)之間增加一個(gè)二進(jìn)制分幀層。在不改動(dòng) HTTP/1.1 的語(yǔ)義、方法、狀態(tài)碼、URI 以及頭部字段的情況下, 解決了 HTTP1.1 的性能限制,改進(jìn)傳輸性能,實(shí)現(xiàn)低延遲和高吞吐量。

          2f7513b67711095897c90155823f2c9a.webp

          圖片來(lái)源: https://hpbn.co/http2/

          HTTP/2 將一個(gè) HTTP 請(qǐng)求劃分為 3 個(gè)部分:

          1. 幀 (Frame) : 一段二進(jìn)制數(shù)據(jù),是 HTTP/2 傳輸?shù)淖钚挝唬總€(gè)幀包含一個(gè)幀頭,用于標(biāo)識(shí)該幀所屬的流,來(lái)自不同數(shù)據(jù)流的幀可以交錯(cuò)發(fā)送,然后再根據(jù)每個(gè)幀頭的數(shù)據(jù)流標(biāo)識(shí)符重新組裝數(shù)據(jù)
          2. 消息 (Message) : 和請(qǐng)求或響應(yīng)對(duì)應(yīng)的多個(gè)幀序列
          3. 流 (Stream) : 已建立的連接內(nèi)的雙向數(shù)據(jù)字節(jié)流,可以承載一條或多條消息,每個(gè)流都有一個(gè)唯一標(biāo)識(shí)符和可選的優(yōu)先級(jí)信息,由客戶端發(fā)起的流必須使用奇數(shù)編號(hào)作為標(biāo)識(shí)符;由服務(wù)器發(fā)起的必須使用偶數(shù)編號(hào)作為標(biāo)識(shí)符,流標(biāo)識(shí)符零(0x0)用于連接控制消息


          310548ca72c2e943d1381e2cf02f4023.webp

          圖片來(lái)源: https://hpbn.co/http2/

          請(qǐng)求/響應(yīng) 多路復(fù)用

          1bd281be22a5b13803fca510c3521f06.webp

          圖片來(lái)源: https://blog.cloudflare.com/http-2-for-web-developers/

          在整個(gè)通信過(guò)程中,只會(huì)有一個(gè) TCP 連接存在,它承載了任意數(shù)量的雙向數(shù)據(jù)流 (Stream)。

          e4aafcaf2d17e4d78d05463b7c53016c.webp

          圖片來(lái)源: https://hpbn.co/http2/

          如圖所示,客戶端正在向服務(wù)端傳輸 stream 5,服務(wù)端正在向客戶端交替?zhèn)鬏?stream 1 和 stream 3, 因此存在 3 個(gè)并行的流 (3 個(gè)流位于雙向的一條 TCP 連接上面)。

          這種單連接多資源的方式,減少服務(wù)端的鏈接壓力 (主要是握手和開(kāi)啟 HTTPS 后的驗(yàn)證), 內(nèi)存占用更少 (連接隊(duì)列), 連接吞吐量更大;而且由于 TCP 連接的減少而使網(wǎng)絡(luò)擁塞狀況得以改善 (減少 TCP 三次握手、開(kāi)啟 HTTPS 后的 TLS 握手), 同時(shí)慢啟動(dòng)時(shí)間的減少,使擁塞和丟包恢復(fù)速度更快 (因?yàn)楫?dāng)發(fā)生丟包時(shí),TCP 擁塞窗口大小會(huì)因?yàn)閾砣苊鈾C(jī)制而減小,從而降低整個(gè)連接的最大吞吐量)。

          通過(guò)二進(jìn)制分幀層,可以解決 HTTP/1.1 中依然存在的 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 和 客戶端需要多個(gè)連接 兩個(gè)問(wèn)題。

          ?? 該方案的本質(zhì)是多路復(fù)用,這里的「多路」指多個(gè)資源請(qǐng)求,「復(fù)用」指在同一個(gè) TCP 連接上傳輸。

          在 HTTP/1.1 協(xié)議中瀏覽器客戶端在同一時(shí)間,針對(duì)同一域名下的請(qǐng)求有一定數(shù)量限制。超過(guò)限制數(shù)目的請(qǐng)求會(huì)被阻塞。這也是為何一些站點(diǎn)會(huì)有多個(gè)靜態(tài)資源 CDN 域名的原因之一,而 HTTP/2 的多路復(fù)用(Multiplexing) 則允許同時(shí)通過(guò)單一的 HTTP/2 連接發(fā)起多重的請(qǐng)求-響應(yīng)消息。因此 HTTP/2 可以很容易地去實(shí)現(xiàn)多流并行而不用依賴建立多個(gè) TCP 連接,HTTP/2 把 HTTP 協(xié)議通信的基本單位縮小為一個(gè)一個(gè)的幀,這些幀對(duì)應(yīng)著邏輯流中的消息。并行地在同一個(gè) TCP 連接上雙向交換消息。

          為什么只有一個(gè) TCP 連接?

          在 HTTP/1.1 協(xié)議中瀏覽器打開(kāi)單個(gè)域名網(wǎng)站可能會(huì)使用多個(gè)連接 (實(shí)現(xiàn)多站點(diǎn)傳輸),結(jié)果就是單個(gè)站點(diǎn)頁(yè)面加載時(shí)會(huì)打開(kāi)數(shù)十個(gè) TCP 連接。一個(gè)應(yīng)用程序打開(kāi)如此多的 TCP 連接,這已經(jīng)遠(yuǎn)遠(yuǎn)超出了最初的 TCP 設(shè)計(jì)理念,而且由于每個(gè) TCP 連接都會(huì)響應(yīng)大量的數(shù)據(jù),會(huì)增加網(wǎng)絡(luò)緩沖區(qū)的溢出風(fēng)險(xiǎn),導(dǎo)致網(wǎng)絡(luò)擁塞事件并重新開(kāi)始數(shù)據(jù)傳輸。

          96c96b3f0cd9f06c9b887927d74ae620.webp

          圖片來(lái)源: https://halfrost.com/http2_begin/

          請(qǐng)求優(yōu)先級(jí)

          多個(gè) HTTP 請(qǐng)求同時(shí)發(fā)送時(shí),會(huì)產(chǎn)生多個(gè)數(shù)據(jù)流,每個(gè)數(shù)據(jù)流中有一個(gè)優(yōu)先級(jí)的標(biāo)識(shí),服務(wù)器端可以根據(jù)這個(gè)標(biāo)識(shí)來(lái)決定響應(yīng)的優(yōu)先順序。

          1. 每個(gè)數(shù)據(jù)流可以分配一個(gè) 1 到 256 之間的整數(shù)作為其權(quán)重值
          2. 每個(gè)數(shù)據(jù)流可以被指定對(duì)另一個(gè)數(shù)據(jù)流的顯式依賴

          對(duì)于瀏覽器來(lái)說(shuō),并非所有資源都擁有同樣的優(yōu)先級(jí) (例如大多數(shù)情況下 HTML 文件應(yīng)該比 CSS 文件擁有更高的優(yōu)先級(jí)),為了加速頁(yè)面訪問(wèn),現(xiàn)代瀏覽器都會(huì)根據(jù)資源的具體類型和在頁(yè)面上的位置進(jìn)行優(yōu)先級(jí)排序, 甚至?xí)鶕?jù)歷史訪問(wèn)響應(yīng)時(shí)間記錄來(lái)學(xué)習(xí)優(yōu)先級(jí),例如某個(gè)資源在之前訪問(wèn)時(shí)被阻塞了,那么這個(gè)資源在將來(lái)的訪問(wèn)中會(huì)獲得更好的優(yōu)先級(jí)。

          通過(guò)設(shè)置合理的請(qǐng)求優(yōu)先級(jí),可以有效緩解 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 和 TCP 連接的利用率低 兩個(gè)問(wèn)題。默認(rèn)情況下,瀏覽器的優(yōu)先級(jí)機(jī)制已經(jīng)優(yōu)化的足夠好,無(wú)需在代碼層面設(shè)置資源優(yōu)先級(jí)。

          服務(wù)端推送

          HTTP/2.0 在客戶端請(qǐng)求一個(gè)資源時(shí),會(huì)把相關(guān)的資源一起發(fā)送給客戶端,客戶端就不需要再次發(fā)起請(qǐng)求了。

          例如客戶端請(qǐng)求 page.html 頁(yè)面,服務(wù)端順帶著就把 script.js 和 style.css 等相關(guān)的資源一起發(fā)給客戶端。

          5f7a32e3cbd3db067d1bfae36686a246.webp

          HTTP/2 Server Push

          推送的資源有如下特點(diǎn):

          • 可以被客戶端 (一般指瀏覽器) 緩存
          • 可以被不同的頁(yè)面進(jìn)行復(fù)用
          • 可以被服務(wù)端確定優(yōu)先級(jí)
          • 客戶端完全控制服務(wù)端的推送行為: 限制并發(fā)推送流的數(shù)量、調(diào)整初始流量控制窗口、控制流首次打開(kāi)時(shí)推送的數(shù)據(jù)量、或者完全禁用服務(wù)端推送,這些首選項(xiàng)在 HTTP/2 建立連接時(shí)通過(guò)設(shè)置幀進(jìn)行傳遞,并且可以隨時(shí)更新
          • 每個(gè)被推送的資源都是一個(gè)流,這允許客戶端單獨(dú)對(duì)其進(jìn)行多路復(fù)用、優(yōu)先級(jí)排序和數(shù)據(jù)處理,當(dāng)然,推送的資源必須遵守同源策略

          PUSH_PROMISE 幀

          服務(wù)端的所有推送都是通過(guò) PUSH_PROMISE 幀發(fā)起的,它表示服務(wù)端會(huì)將資源推送到客戶端,并且允許服務(wù)端在客戶端請(qǐng)求之前就發(fā)送相關(guān)資源給客戶端。這些資源可能是客戶端未直接請(qǐng)求的,但服務(wù)端認(rèn)為客戶端可能會(huì)需要的資源。通過(guò)推送可以避免客戶端發(fā)起額外的請(qǐng)求來(lái)獲取這些資源,從而加快頁(yè)面加載速度。PUSH_PROMISE 幀包含了推送資源的相關(guān)信息,如資源的 URL、HTTP 頭部等,客戶端接收到 PUSH_PROMISE 幀,可以選擇拒絕流 (通過(guò) RST_STREAM 幀),例如資源已經(jīng)存在于客戶端的緩存中。

          HPACK 壓縮

          HTTP/2 要求客戶端和服務(wù)器同時(shí)維護(hù)和更新一個(gè)包含之前見(jiàn)過(guò)的頭部字段表,從而避免了重復(fù)傳輸。HTTP/2 中通信雙方各自緩存一份頭部字段表,如:把 Content-Type:text/html 存入索引表中,后續(xù)如果要用到這個(gè)頭,只需要發(fā)送對(duì)應(yīng)的索引號(hào)就可以了。

          通過(guò)頭部壓縮,解決了 HTTP/1.1 中頭部重復(fù)導(dǎo)致的不必要的數(shù)據(jù)傳輸問(wèn)題。

          6e33bd51609833f3f0c63230819b37b3.webp

          HTTP/2 Header Compress

          作為進(jìn)一步的優(yōu)化,HPACK 壓縮上下文 由靜態(tài)和動(dòng)態(tài)表組成:

          • 靜態(tài)表中定義了規(guī)范標(biāo)準(zhǔn),主要提供連接可能會(huì)使用到的常見(jiàn) HTTP 報(bào)頭字段 (例如 host, path, method ...)
          • 動(dòng)態(tài)表初始時(shí)為空,但是會(huì)根據(jù)特定連接內(nèi)的不同字段值進(jìn)行更新,通過(guò)對(duì)新出現(xiàn)的字段值使用 Huffman 編碼,以及對(duì) 客戶端/服務(wù)端 雙方靜態(tài)表或動(dòng)態(tài)表中已經(jīng)存在的字段值更新索引,可以減少每個(gè)請(qǐng)求的大小

          f4d62db0b672bed8ad99862311136ffe.webp

          HTTP/2 Header Compress

          流控制

          流控制是一種發(fā)送方與接收方之間的協(xié)商機(jī)制,防止雙方向?qū)Ψ桨l(fā)送大量數(shù)據(jù)時(shí),造成對(duì)方負(fù)載過(guò)重,或者限制特定資源的流量速率。例如客戶端請(qǐng)求了一個(gè)高優(yōu)先級(jí)的大視頻流,但是用戶觀看幾秒后暫停了,此時(shí)客戶端應(yīng)該暫?;蛳拗破鋸姆?wù)器端的數(shù)據(jù)傳輸,避免請(qǐng)求和緩沖不必要的數(shù)據(jù)。

          本質(zhì)上這是一個(gè)流量控制問(wèn)題,也許你會(huì)想到 TCP 中的流量控制機(jī)制,但是 HTTP/2 是使用單個(gè) TCP 連接進(jìn)行多路復(fù)用的,這樣一來(lái), TCP 傳輸層流量控制既沒(méi)有足夠的流量控制粒度 (沒(méi)有辦法以 HTTP 請(qǐng)求資源為粒度進(jìn)行控制,因?yàn)榈貌粌斒?,?huì)直接浪費(fèi)掉多路復(fù)用帶來(lái)的所有好處), 也沒(méi)有必要提供應(yīng)用層的 API 來(lái)控制單個(gè)流的傳輸控制。為了解決這個(gè)問(wèn)題,HTTP/2 提供了一組簡(jiǎn)單的構(gòu)建塊,允許客戶端和服務(wù)端實(shí)現(xiàn)自己的連接控制和流控制。

          HTTP/2 流控制具體的規(guī)則如下:

          • 流控制是定向的,接收方 (客戶端/服務(wù)端都是彼此的接收方) 可以選擇為每個(gè)流和整個(gè)連接設(shè)置窗口大小
          • 流控制是基于窗口機(jī)制的,接收方會(huì)其初始連接和流控制窗口(以字節(jié)為單位),當(dāng)發(fā)送方發(fā)出數(shù)據(jù)幀時(shí),該窗口就會(huì)減少,當(dāng)發(fā)送方接收到來(lái)自接收方發(fā)送的 WINDOW_UPDATE 幀時(shí),該窗口就會(huì)增加
          • 無(wú)法禁用流控制,當(dāng)建立 HTTP/2 連接時(shí),客戶端和服務(wù)器交換 SETTINGS 幀,用來(lái)設(shè)置兩個(gè)方向的流量控制窗口大小,流量控制窗口的默認(rèn)值設(shè)置為 65535 字節(jié), 最大窗口大小為(2^31 - 1 字節(jié)),并通過(guò)在接收到數(shù)據(jù)時(shí)發(fā)送 WINDOW_UPDATE 幀來(lái)更新

          HTTP/2 沒(méi)有指定任何特定的算法來(lái)實(shí)現(xiàn)流量控制,它僅提供了簡(jiǎn)單的構(gòu)建塊,并將實(shí)現(xiàn)委托給客戶端和服務(wù)器,客戶端和服務(wù)器可以使用它實(shí)現(xiàn)自定義策略調(diào)節(jié)資源分配。應(yīng)用層流量控制允許瀏覽器只獲取特定資源的一部分,通過(guò)將流量控制窗口 (WINDOW_UPDATE) 減少到零來(lái)實(shí)現(xiàn)暫停資源獲取,然后在合適的時(shí)間再進(jìn)行恢復(fù)。例如獲取圖像的預(yù)覽圖 (該圖像內(nèi)容的一部分),顯示預(yù)覽圖的同時(shí)允許其他高優(yōu)先級(jí)的請(qǐng)求繼續(xù)獲取,并在優(yōu)先級(jí)更高的資源完成加載后恢復(fù)繼續(xù)圖像的獲取請(qǐng)求。

          一次 HTTP/2 通信示例

          dce0a88fad7128669263354b3d71af47.webp

          HTTP/2 通信過(guò)程
          1. 首次訪問(wèn)時(shí),瀏覽器請(qǐng)求頭部加上 upgrade: h2c 標(biāo)識(shí),聲明客戶端支持 HTTP/2,詢問(wèn)服務(wù)器要不要更換協(xié)議
          2. 瀏覽器同時(shí)發(fā)送 HTTP/2-Settings 頭部,帶上 base64 編碼的 SETTINGS frame
          3. 對(duì)于 HTTPS 請(qǐng)求,是在 TLS 握手階段進(jìn)行協(xié)商,瀏覽器發(fā)送 ClientHello 時(shí),帶上 h2 標(biāo)志,表明客戶端支持 HTTP/2
          4. 如果服務(wù)器不支持,則忽略 upgrade 頭部,正常響應(yīng)。如果支持,則發(fā)送 101 響應(yīng),以空行結(jié)束響應(yīng),并開(kāi)始發(fā)送 HTTP/2 幀
          5. 服務(wù)器要先響應(yīng) connection preface,帶上 SETTINGS frame
          6. 服務(wù)器創(chuàng)建新流,推送 a.js。然后繼續(xù)發(fā)送 index.html 文件和 a.js 文件的 response header、response body
          7. 瀏覽器收到 PUSH_PROMISE 幀,發(fā)現(xiàn)服務(wù)器要推送的內(nèi)容已經(jīng)在瀏覽器緩存里了,發(fā)送 RST_STREAM 拒絕推送
          8. 服務(wù)器收到 RST_STREAM 幀后,不再推送 a.js 文件剩余的數(shù)據(jù)
          9. 服務(wù)器想要關(guān)閉連接,發(fā)送 GOAWAY 幀

          檢測(cè)是否支持 HTTP/2

          通過(guò) CURL 命令來(lái)檢測(cè)網(wǎng)站是否支持 HTTP/2 協(xié)議。

                
                $ curl -I "https://dbwu.tech"

          #
           輸出如下

          HTTP/2 200
          date: Sun, 22 Jan 2023 04:15:29 GMT
          content-type: text/html; charset=utf-8
          ...

          直接使用 --http/2 參數(shù)指定 CURL 請(qǐng)求使用 HTTP/2 協(xié)議。

                
                
                  $
                   curl --http/2 "https://dbwu.tech"
                  

          也可以通過(guò) 在線工具[1] 進(jìn)行檢測(cè)。

          04e85141ac8a96951c2547409bfe3c38.webp

          HTTP/2 在線檢測(cè)工具

          HTTP/1 升級(jí)后過(guò)時(shí)的優(yōu)化方案

          升級(jí)到 HTTP/2 之后,很多 HTTP/1 中的優(yōu)化方案,在 HTTP/2 中就沒(méi)有存在的必要了,例如下面這些曾經(jīng)的 “經(jīng)典” 優(yōu)化方案:

          • Sprites: 將很多小圖合并成一張大圖,再利用 CSS 和 JavaScript 將小圖定位并切割出來(lái) (常見(jiàn)的業(yè)務(wù)場(chǎng)景如 Logo 圖集、網(wǎng)頁(yè)游戲道具等)

          40cd56ada7698b996b8a3e4b2ea05e06.webp

          圖片來(lái)源: https://www.formget.com/css-image-sprites
          • Inlining: 將圖片的原始數(shù)據(jù) base64 編碼之后嵌入到 CSS 屬性中 (可以節(jié)約一次 HTTP 請(qǐng)求)

          effca260e694a5b6ff507d3ed6840a68.webp

          圖片來(lái)源: https://stackoverflow.com/questions/41762836/what-is-base-64-fonts-for-css
          • Concatenation: 將許多小的靜態(tài)文件合并到一個(gè)大的靜態(tài)文件中

          d78ba3940c7f3037f9c050bd1a199f68.webp

          圖片來(lái)源: https://blog.cloudflare.com/http-2-for-web-developers/

          8ad506f86ad7c79bc5582f067657e902.webp

          圖片來(lái)源: https://blog.cloudflare.com/http-2-for-web-developers/
          • Sharding: 將靜態(tài)資源分發(fā)到不同的域名 (即使沒(méi)有 HTTP/2, 這個(gè)方案也可以使用 CDN 來(lái)替代,方案的核心在于并發(fā) TCP 連接以及優(yōu)化 cookies)

          c34144b70d0894c452e101abcfcb18fd.webp

          圖片來(lái)源: https://blog.cloudflare.com/http-2-for-web-developers/

          HTTP/1 升級(jí)后仍然有效的的優(yōu)化方案

          除了上述升級(jí)到 HTTP/2 失效的優(yōu)化方案外,大部分在 HTTP/1 優(yōu)化的方案在 HTTP/2 中仍然有效嗎,例如下面這些方案:

          • 降低 DNS 輪詢 (可以參考主流云計(jì)算廠商提供的解決方案及實(shí)現(xiàn)原理)
          • 使用 CDN (并且根據(jù)業(yè)務(wù)場(chǎng)景和服務(wù)進(jìn)行設(shè)計(jì)拆分)
          • 盡可能使用瀏覽器緩存機(jī)制
          • 盡可能優(yōu)化請(qǐng)求響應(yīng)時(shí)間和響應(yīng)內(nèi)容大小
          • 盡可能消除重定向

          HTTP/2 的優(yōu)化空間

          HTTP/2 針對(duì)基于 TCP 協(xié)議棧的 HTTP 優(yōu)化,幾乎上已經(jīng)達(dá)到了最大化,如果需要繼續(xù)深入優(yōu)化,只能從協(xié)議棧本身的架構(gòu)做調(diào)整,當(dāng)然也就是 HTTP/3 協(xié)議主要做的工作。

          優(yōu)化核心目標(biāo)依然是 TCP 的可靠性機(jī)制導(dǎo)致的傳輸效率和延遲問(wèn)題:

          • TCP 建立連接時(shí)的三次握手,增加了請(qǐng)求延時(shí)
          • TCP 內(nèi)部的擁塞控制、慢啟動(dòng)、擁塞避免等機(jī)制,可能導(dǎo)致傳輸效率不足
          • HTTP/2 雖然解決了 HTTP/1 協(xié)議中的 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 問(wèn)題,但是 TCP 協(xié)議也存在類似的問(wèn)題: TCP 在傳輸時(shí)使用序列號(hào)標(biāo)識(shí)數(shù)據(jù)的順序,一旦某個(gè)數(shù)據(jù)丟失,后面的數(shù)據(jù)需要等待這個(gè)數(shù)據(jù)重傳后才能進(jìn)行下一步處理
          • 根據(jù)測(cè)試表明,在較差的網(wǎng)絡(luò)環(huán)境中 (丟包率 >= 2%),HTTP/2 的性能甚至不如 HTTP/1, 因?yàn)?HTTP/1 一般會(huì)打開(kāi)多個(gè) TCP 連接,即使其中一個(gè)或多個(gè)連接出現(xiàn)丟包,剩下的連接依然可以進(jìn)行數(shù)據(jù)傳輸

          HTTP/3

          HTTP/3 是基于 QUIC(Quick UDP Internet Connections)協(xié)議的新一代 HTTP 協(xié)議。

          QUIC

          QUIC 是由 Google 提出的基于 UDP 進(jìn)行多路復(fù)用的傳輸協(xié)議,是一個(gè) UDP 版的 TCP + TLS + HTTP/2 替代方案實(shí)現(xiàn)。QUIC 沒(méi)有連接的概念,不需要三次握手,在應(yīng)用程序?qū)用?,?shí)現(xiàn)了 TCP 的可靠性,TLS 的安全性和 HTTP2 的并發(fā)性。在設(shè)備支持層面,只需要客戶端和服務(wù)端的應(yīng)用程序支持 QUIC 協(xié)議即可,無(wú)操作系統(tǒng)和中間設(shè)備的限制。

          QUIC 丟掉了 TCP 的包袱,基于 UDP,實(shí)現(xiàn)了一個(gè)安全高效可靠的 HTTP 通信協(xié)議。憑借著 0-RTT 建立連接、傳輸層多路復(fù)用、連接遷移、改進(jìn)的擁塞控制、流量控制等特性,QUIC 在絕大多數(shù)場(chǎng)景下獲得了比 HTTP/2 更好的效果。

          47ebadfe9e9540c595caa7b460b259b4.webp

          HTTP/2 和 HTTP/3 的協(xié)議棧比較

          題外話

          為什么不發(fā)明一個(gè)新的傳輸協(xié)議?

          事實(shí)上,面對(duì)傳統(tǒng)傳輸層 TCP 和 UDP 協(xié)議的各種問(wèn)題和不足,創(chuàng)新型的傳輸層協(xié)議最終都沒(méi)有能成為行業(yè)標(biāo)準(zhǔn)。因?yàn)檫@不單單是技術(shù)問(wèn)題, 客戶端與服務(wù)端之間要經(jīng)過(guò)網(wǎng)絡(luò)中的運(yùn)營(yíng)商防火墻、路由器、NAT 等,這些設(shè)備中很多默認(rèn)只支持 TCP 和 UDP 協(xié)議,那么可想而知,新型協(xié)議根本無(wú)法在互聯(lián)網(wǎng)普及。而且,即使上述所有的中間設(shè)備想要支持新型協(xié)議,那么更新和部署新的網(wǎng)絡(luò)協(xié)議棧、操作系統(tǒng)內(nèi)核等基礎(chǔ)設(shè)施和軟件,必然是一個(gè)十分緩慢的過(guò)程,在此期間造成的停機(jī)等問(wèn)題引起的經(jīng)濟(jì)損失可能是無(wú)法估量的。

          核心優(yōu)化

          最重要的優(yōu)化就是使用 QUIC 協(xié)議代替了 HTTP/2 中的依賴的 TCP 協(xié)議棧。

          0-RTT

          QUIC 協(xié)議可以實(shí)現(xiàn) 0-RTT 建立連接 (0-RTT 是指通信雙方發(fā)起通信連接時(shí),第一個(gè)數(shù)據(jù)包就可以攜帶有效的業(yè)務(wù)數(shù)據(jù)),而 TCP 需要 3-RTT 建立連接,這個(gè)優(yōu)勢(shì)不止體現(xiàn)在初始建立連接時(shí),在網(wǎng)絡(luò)發(fā)生變化時(shí)同樣適用。

          3a09a939ce00e2fa2b63162804538b45.webp

          圖片來(lái)源: https://en.wikipedia.org/wiki/QUIC

          關(guān)于 0-RTT,需要說(shuō)明的是: 如果客戶端和服務(wù)器是第一次通信,那么需要經(jīng)過(guò) 1-RTT (主要是客戶端獲取服務(wù)端加密配置),如果已經(jīng)有過(guò)一次通信之后, 后續(xù)客戶端和服務(wù)端的通信連接就是 0-RTT。限于篇幅,第一次客戶端連接到服務(wù)端獲取密鑰及加密配置的過(guò)程,本文不再展開(kāi)描述。

          多路復(fù)用

          18e9b3060b96c9fdb95ca9e6a51f37f0.webp

          圖片來(lái)源: https://www.debugbear.com/blog/http3-quic-protocol-guide

          QUIC 中的每個(gè) stream 之間是相互獨(dú)立的,單個(gè) stream 丟失了,不會(huì)影響到其他 stream,QUIC 協(xié)議在發(fā)送數(shù)據(jù)時(shí)會(huì)拆分為多個(gè)包, 這樣就完全解決了 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 問(wèn)題。盡管 QUIC 消除了 HTTP/2 的隊(duì)列頭部請(qǐng)求阻塞問(wèn)題,但其依賴的 UDP 本身是無(wú)序交付的,也就是數(shù)據(jù)不一定按照發(fā)送時(shí)的順序到達(dá), (所以并不是切換到 HTTP/3 就萬(wàn)事大吉了,客戶端和服務(wù)端必須要根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景,嘗試做更多的優(yōu)化工作)。

          單調(diào)遞增的序列號(hào)

          TCP 中,每一個(gè)數(shù)據(jù)包都有一個(gè)序列號(hào)標(biāo)識(shí)(seq),如果接收端超時(shí)沒(méi)有收到,就會(huì)要求重發(fā)標(biāo)識(shí)為 seq 的包,如果此時(shí)恰好接受到了超時(shí)的包, 則無(wú)法區(qū)分哪個(gè)是超時(shí)的包,哪個(gè)是重傳的包。

          • RTT: Round Trip Time, 往返事件
          • RTO: Retransmission Timeout, 超時(shí)重傳時(shí)間

          如果客戶端認(rèn)為收到的包是重傳包,但是實(shí)際是超時(shí)的包,這樣就會(huì)導(dǎo)致計(jì)算出來(lái)的 RTT 值偏小,反之計(jì)算出來(lái)的 RTT 值偏大。

          57b2678bb03c4232f5df41dc51a1a378.webp

          示例: RTT 值偏小

          在上面的示例圖中,RTT 計(jì)算出來(lái)的 RTT 值比實(shí)際值要小。

          d80d8427c47c32421d788c986516ba94.webp

          示例: RTT 值偏大

          在上面的示例圖中,RTT 計(jì)算出來(lái)的 RTT 值比實(shí)際值要大。

          QUIC 中的每一個(gè)包的標(biāo)識(shí)(Packet Number)都是單調(diào)遞增的,重傳的序號(hào)一定大于超時(shí)的序號(hào),這樣就能有效地區(qū)分超時(shí)和重傳。

          禁止 Reneging

          TCP 中,如果接收方內(nèi)存不夠或 Buffer 溢出,則可能會(huì)把已接收的包丟棄,這種行為對(duì)數(shù)據(jù)重傳產(chǎn)生了很大的干擾,在 QUIC 中是明確禁止的。在 QUIC 中,一個(gè)包只要被 ACK ,就認(rèn)為一定會(huì)被正確接收。

          批量 ACK

          TCP 中每收到 3 個(gè)數(shù)據(jù)包就要返回一個(gè) ACK,而 QUIC 最多可以收到 256 個(gè)包之后,才返回 ACK。在丟包率比較嚴(yán)重的網(wǎng)絡(luò)下,更多的 ACK 塊可以減少重傳量,提升網(wǎng)絡(luò)效率。

          ACK Delay

          TCP 計(jì)算 RTT 時(shí)沒(méi)有考慮接收方接收到數(shù)據(jù)到發(fā)送確認(rèn)消息之間的延遲,也就是所謂的 ACK Delay。QUIC 充分考慮到 ACK Delay,這樣 RTT 的計(jì)算會(huì)更加準(zhǔn)確。

          5e10a42abf6594bab5c69453c0676f3a.webp

          圖片來(lái)源: https://assets.extrahop.com/whitepapers/TCP-Optimization-Guide-by-ExtraHop.pdf

          流量控制

          TCP 通過(guò)滑動(dòng)窗口來(lái)控制流量,如果某一個(gè)包丟失了,滑動(dòng)窗口并不能跨過(guò)丟失的包繼續(xù)滑動(dòng),而是會(huì)卡在丟失的位置,等待數(shù)據(jù)重傳后,才能繼續(xù)滑動(dòng)。

          QUIC 流量控制的核心是:不能建立太多的連接,以免響應(yīng)端處理不過(guò)來(lái);不能讓某一個(gè)連接占用大量的資源,讓其他連接沒(méi)有資源可用。為此 QUIC 流量控制分為 連接級(jí)別和 Stream 級(jí)別 :

          • Stream 級(jí)別流量控制中,接收窗口 = 最大接收窗口 - 已接收數(shù)據(jù)
          • 連接級(jí)別流量控制中,接收窗口 = Stream1 接收窗口 + Stream2 接收窗口 + ... + StreamN 接收窗口

          連接遷移

          TCP 連接是由(源 IP,源端口,目的 IP,目的端口)組成,這個(gè)四元組中一旦有一項(xiàng)值發(fā)生改變,這個(gè)連接也就不能用了。如果我們從 wifi 網(wǎng)絡(luò)切換到 4G 網(wǎng)絡(luò),IP 地址就會(huì)改變,這個(gè)時(shí)候 TCP 連接也自然斷掉了。

          QUIC 使用客戶端生成的 64 位 ID 來(lái)表示一條連接,只要 ID 不變,這條連接也就一直維持著,不會(huì)中斷。

          前向糾錯(cuò)機(jī)制

          QUIC 使用前向糾錯(cuò)(FEC,F(xiàn)orward Error Correction)技術(shù)增加協(xié)議的容錯(cuò)性。

          728dbf3bf69fc8a04017efd85fb71cdd.webp

          圖片來(lái)源: https://www.xoriant.com/blog/quic-is-around-it-is-being-tested-on-you

          如圖所示,一段數(shù)據(jù)被切分為 10 個(gè)包后,依次對(duì)每個(gè)包進(jìn)行異或運(yùn)算,運(yùn)算結(jié)果會(huì)作為 FEC 包與數(shù)據(jù)包一起被傳輸,如果不幸在傳輸過(guò)程中有一個(gè)數(shù)據(jù)包丟失, 那么就可以根據(jù)剩余 9 個(gè)包以及 FEC 包推算出丟失的那個(gè)包的數(shù)據(jù),這樣就大大增加了協(xié)議的容錯(cuò)性。

          這是符合現(xiàn)階段網(wǎng)絡(luò)技術(shù)的一種方案,現(xiàn)階段帶寬已經(jīng)不是網(wǎng)絡(luò)傳輸?shù)钠款i,往返時(shí)間才是,所以新的網(wǎng)絡(luò)傳輸協(xié)議可以適當(dāng)增加數(shù)據(jù)冗余,減少重傳操作。當(dāng)然這種情況只適用于丟失一個(gè)包的情況下,如果丟失了多個(gè)包,就只能進(jìn)行重傳了。

          QPACK 壓縮

          QPACK 壓縮是 HTTP/3 中使用的字段壓縮格式,可以使 HTTP/2 中使用的 HPACK 壓縮格式與 QUIC 協(xié)議兼容,兩種壓縮格式通過(guò)使用不同的機(jī)制來(lái)滿足傳輸層協(xié)議的要求。

          那么 HTTP/3 中為什么不能繼續(xù)使用 HPACK 壓縮格式呢

          因?yàn)?HPACK 格式是為 TCP 協(xié)議創(chuàng)建的格式,這種格式工作的前提就是默認(rèn)數(shù)據(jù)字節(jié)流按照順序達(dá)到,如果 HTTP/3 中繼續(xù)使用 HPACK 壓縮格式, 就會(huì)導(dǎo)致額外的 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 問(wèn)題,因?yàn)?HPACK 依賴于對(duì)已經(jīng)到達(dá)字段的引用。但是,HTTP/3 中的 QUIC 的傳輸層協(xié)議為 UDP, 數(shù)據(jù)字節(jié)不會(huì)按照順序到達(dá),因此 HPACK 格式中的動(dòng)態(tài)表中可能會(huì)包含還未達(dá)到的數(shù)據(jù)的引用,于是就會(huì)阻塞直到被引用的數(shù)據(jù)到達(dá)。

          為了解決這個(gè)問(wèn)題,QPACK 引入了兩種單向流類型: 編碼器流和解碼器流,除了傳遞 HTTP/3 消息的雙向字節(jié)流之外,客戶端和服務(wù)端可以選擇性地打開(kāi)這兩個(gè)單向編碼流, 將具體的指令傳輸給對(duì)方。因?yàn)榱魇菃蜗虻?,所以發(fā)送方只需要發(fā)送數(shù)據(jù)即可,無(wú)需等到接收方的響應(yīng)。

          最終,雖然增加額外的單向字節(jié)流會(huì)帶來(lái)一定的性能開(kāi)銷,但是卻可以徹底解決 隊(duì)列頭部請(qǐng)求阻塞 (head of line blocking) 問(wèn)題,而且 QPACK 格式規(guī)范為客戶端和服務(wù)器實(shí)現(xiàn)提供了很高的自由度, 可以由實(shí)現(xiàn)方來(lái)決定具體的問(wèn)題重要程度和方案傾向性: 緩解并解決隊(duì)列頭部請(qǐng)求阻塞還是實(shí)現(xiàn)更高級(jí)別的壓縮效果。

          QUIC 相比 TCP 的優(yōu)勢(shì)

          • QUIC 在用戶空間實(shí)現(xiàn)而非內(nèi)核,這樣可以快速部署最新版本或自定義版本,TCP 在內(nèi)核中實(shí)現(xiàn),基本不太可能隨時(shí)部署新版本
          • QUIC 具有更高級(jí)別的加密 (例如大部分 QUIC Header 都是加密的),TCP 本身不做數(shù)據(jù)加密,需要依賴于 TLS
          • QUIC 建立在傳輸層協(xié)議棧上,意味著可以隨時(shí)切換傳輸協(xié)議,有著非常高的靈活性 (例如可以將底層的 UDP 切換到 TCP)

          QUIC 存在的限制

          • 性能提升很大程度上取決于 QUIC 方案的實(shí)施,這包括操作系統(tǒng)發(fā)行版、協(xié)議棧實(shí)現(xiàn)版本、QUIC 的實(shí)現(xiàn)版本等因素
          • 使用 HTTP/3 之前需要進(jìn)行 HTTP 版本協(xié)商,瀏覽器默認(rèn)不支持 HTTP/3, 通常需要基于建立在 TCP 上的 HTTP/1 或 HTTP/2 來(lái)發(fā)送協(xié)商請(qǐng)求
          • 增加網(wǎng)絡(luò)管理復(fù)雜度,由于 QUIC 會(huì)加密大部分?jǐn)?shù)據(jù),因此排查網(wǎng)絡(luò)錯(cuò)誤、優(yōu)化網(wǎng)絡(luò)性能和安全性、設(shè)置報(bào)警規(guī)則等工作都變得更加困難,由于這些原因,很多防火墻還未支持 QUIC
          • 許多網(wǎng)絡(luò)攻擊都是利用 UDP 發(fā)起的,據(jù)統(tǒng)計(jì)大概有 3% - 5% 的網(wǎng)絡(luò)會(huì)直接過(guò)濾 UDP 請(qǐng)求 (DNS 等網(wǎng)絡(luò)基礎(chǔ)協(xié)議除外)

          是否支持 HTTP/3

          網(wǎng)站檢測(cè)

          可以通過(guò) 在線工具[2] 進(jìn)行檢測(cè)。

          914d073f63dbfb126246ba54cd98963e.webp

          HTTP/3 在線檢測(cè)工具

          瀏覽器支持情況

          可以通過(guò) 瀏覽器在線工具[3] 進(jìn)行檢測(cè),下面是筆者的 Chrome 支持情況。

          8e45ee088d178fa74120ecf445a829e0.webp

          HTTP/3 在線檢測(cè)工具

          小結(jié)

          本文介紹了從 HTTP/1 到 HTTP/3 中間四次比較大的協(xié)議升級(jí)變更,著重分析了每次升級(jí)前后的性能差異及相關(guān)特性變更 (安全方面的變更未分析,感興趣的讀者可以自行閱讀相關(guān) RFC)。作為開(kāi)發(fā)者,平時(shí)可能不會(huì)去關(guān)注這些網(wǎng)絡(luò)底層細(xì)節(jié),但是深入理解整個(gè) HTTP 協(xié)議的升級(jí)變遷過(guò)程,可以幫助我們理解這背后的工程挑戰(zhàn)以及解決思路,這才是最有價(jià)值的部分。

          終極用戶體驗(yàn)?zāi)J?/h3>

          瀏覽器作為操作系統(tǒng),站點(diǎn)作為應(yīng)用軟件,這算不算是從 B/S 架構(gòu)又回到了 C/S 架構(gòu)?

          Reference

          • Hypertext Transfer Protocol Version 2 (HTTP/2) [4]
          • QUIC: A UDP-Based Multiplexed and Secure Transport [5]
          • HTTP/3 [6]
          • HTTP/2 explained [7]
          • HTTP/2 [8]
          • Introduction to HTTP/2 [9]
          • what-is-http3 [10]
          • HTTP/2 is here, let’s optimize! [11]

          擴(kuò)展閱讀

          • HTTP Documentation Core Specifications [12]
          • HTTP/2 服務(wù)器推送(Server Push)教程 [13]
          • HTTP/2 For Web Developers [14]
          • Web Almanac [15]
          • HTTP/2 HPACK 實(shí)際應(yīng)用舉例 [16]
          • 詳解 HTTP/2 頭壓縮算法 —— HPACK [17]
          • QUIC 協(xié)議原理分析 [18]
          • HTTP/3 From A To Z: Core Concepts [19]
          • A Comprehensive Guide To HTTP/3 And QUIC [20]
          • A Comparison between SCTP and QUIC [21]
          • HTTP RFCs have evolved: A Cloudflare view of HTTP usage trends [22]
          • Introducing HTTP/3 Prioritization [23]
          • Caddy [24]
          • Report: State of the Web [25]

          鏈接

          [1]

          在線工具: https://http2.pro/check

          [2]

          在線工具: https://domsignal.com/http3-test

          [3]

          瀏覽器在線工具: https://caniuse.com/http3

          [4]

          Hypertext Transfer Protocol Version 2 (HTTP/2): https://datatracker.ietf.org/doc/html/rfc7540

          [5]

          QUIC: A UDP-Based Multiplexed and Secure Transport: https://datatracker.ietf.org/doc/html/rfc9000

          [6]

          HTTP/3: https://datatracker.ietf.org/doc/rfc9114/

          [7]

          HTTP/2 explained: https://daniel.haxx.se/http2/

          [8]

          HTTP/2: https://hpbn.co/http2/

          [9]

          Introduction to HTTP/2: https://web.dev/performance-http2/

          [10]

          what-is-http3: https://www.cloudflare.com/zh-cn/learning/performance/what-is-http3/

          [11]

          HTTP/2 is here, let’s optimize!: https://docs.google.com/presentation/d/1r7QXGYOLCh4fcUq0jDdDwKJWNqWK1o4xMtYpKZCJYjM/edit?pli=1#slide=id.p19

          [12]

          HTTP Documentation Core Specifications: https://httpwg.org/specs/

          [13]

          HTTP/2 服務(wù)器推送(Server Push)教程: https://www.ruanyifeng.com/blog/2018/03/http2_server_push.html

          [14]

          HTTP/2 For Web Developers: https://blog.cloudflare.com/http-2-for-web-developers/

          [15]

          Web Almanac: https://github.com/HTTPArchive/almanac.httparchive.org

          [16]

          HTTP/2 HPACK 實(shí)際應(yīng)用舉例: https://halfrost.com/http2-hpack-example/

          [17]

          詳解 HTTP/2 頭壓縮算法 —— HPACK: https://halfrost.com/http2-header-compression/

          [18]

          QUIC協(xié)議原理分析: https://zhuanlan.zhihu.com/p/32553477

          [19]

          HTTP/3 From A To Z: Core Concepts: https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/

          [20]

          A Comprehensive Guide To HTTP/3 And QUIC: https://www.debugbear.com/blog/http3-quic-protocol-guide

          [21]

          A Comparison between SCTP and QUIC: https://datatracker.ietf.org/doc/html/draft-joseph-quic-comparison-quic-sctp-00

          [22]

          HTTP RFCs have evolved: A Cloudflare view of HTTP usage trends: https://blog.cloudflare.com/cloudflare-view-http3-usage/

          [23]

          Introducing HTTP/3 Prioritization: https://blog.cloudflare.com/better-http-3-prioritization-for-a-faster-web/

          [24]

          Caddy: https://github.com/caddyserver/caddy

          [25]

          Report: State of the Web: https://httparchive.org/reports/state-of-the-web

          瀏覽 65
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  俺也去www色官方网站 | 亚洲精品乱码久久久久久9色 | 天天操夜夜爱 | 国产豆花视频在线播放 | 色婷婷无码在线 |