摘要:消息與邏輯請(qǐng)求或響應(yīng)消息對(duì)應(yīng)的完整的一系列幀。聲明數(shù)據(jù)流依賴關(guān)系指出,應(yīng)盡可能先向父數(shù)據(jù)流分配資源,然后再向其依賴項(xiàng)分配資源。數(shù)據(jù)流應(yīng)先于和獲得完整資源分配和應(yīng)先于和獲得相同的資源分配和應(yīng)基于其權(quán)重獲得比例分配。
轉(zhuǎn)載自 | 小米運(yùn)維(公眾號(hào) ID:MI-SRE)
HTTP/2 是現(xiàn)行 HTTP 協(xié)議(HTTP/1.x)的替代,但它不是重寫,HTTP 方法 / 狀態(tài)碼 / 語義都與 HTTP/1.x 一樣。不過,HTTP/2 修改了數(shù)據(jù)格式化(分幀)以及在客戶端與服務(wù)器間傳輸?shù)姆绞?。HTTP/2 基于 SPDY3,專注于性能,最大的一個(gè)目標(biāo)是在用戶和網(wǎng)站間只用一個(gè)連接。
HTTP/2 通過支持完整的請(qǐng)求與響應(yīng)復(fù)用來減少延遲,通過有效壓縮 HTTP 報(bào)頭字段將協(xié)議開銷降至最低,同時(shí)增加對(duì)請(qǐng)求優(yōu)先級(jí)和服務(wù)器推送的支持。
HTTP/2 協(xié)議由以下兩個(gè) RFC 組成:
RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2); RFC 7541 -
HPACK: Header Compression for HTTP/2;
HTTP/2 解決的問題影響一個(gè) HTTP 網(wǎng)絡(luò)請(qǐng)求的因素主要有兩個(gè):帶寬和延遲。在當(dāng)今的網(wǎng)絡(luò)情況下,帶寬一般不再是瓶頸,所以我們主要討論下延遲。延遲一般由下面幾個(gè)因素所造成:
瀏覽器線頭阻塞(Head-Of-Line Blocking):瀏覽器會(huì)因?yàn)橐恍┰蜃枞?qǐng)求。
DNS 查詢。
建立連接(Initial connection):HTTP 基于 TCP 協(xié)議,TCP 的 3 次握手和慢啟動(dòng)極大增加延遲。
HTTP/1.x 中存在的問題連接無法復(fù)用:
連接無法復(fù)用會(huì)導(dǎo)致每次請(qǐng)求都經(jīng)歷三次握手和慢啟動(dòng)。三次握手在高延遲的場(chǎng)景下影響較明顯,慢啟動(dòng)則對(duì)文件類大請(qǐng)求影響較大。
HTTP/1.0 傳輸數(shù)據(jù)時(shí),每次都需要重新建立連接,增加延遲。
HTTP/1.1 雖然加入 keep-alive,可以復(fù)用一部分連接,但域名分片等情況下仍然需要建立多個(gè) connection,耗費(fèi)資源,給服務(wù)器帶來性能壓力。
線頭阻塞(Head-Of-Line Blocking):
導(dǎo)致帶寬無法被充分利用,以及后續(xù)健康請(qǐng)求被阻塞。HOLB 是指在 HTTP/1.x 中,由于服務(wù)器必須按接受請(qǐng)求的順序發(fā)送響應(yīng)的規(guī)則限制,那么假設(shè)瀏覽器在一個(gè)(tcp)連接上發(fā)送了兩個(gè)請(qǐng)求,那么服務(wù)器必須等第一個(gè)請(qǐng)求響應(yīng)完畢才能發(fā)送第二個(gè)響應(yīng)——HOLB。雖然現(xiàn)在瀏覽器允許每個(gè) origin 建立 6 個(gè) connection,但大量網(wǎng)頁(yè)動(dòng)輒幾十個(gè)或上百個(gè)資源,HOLB 依然是主要問題。
協(xié)議開銷大:
HTTP/1.x 中 header 內(nèi)容過大(每次請(qǐng)求 header 基本不怎么變化),增加了傳輸?shù)某杀尽?br>安全因素:
在 HTTP 中傳輸?shù)膬?nèi)容都是明文,客戶端和服務(wù)端雙方無法驗(yàn)證身份。
連接復(fù)用:
在用戶和網(wǎng)站之間只用一個(gè)連接,避免后續(xù)建立連接過程中的幾個(gè)往返和慢啟動(dòng),同時(shí)減少了服務(wù)器的資源消耗。
沒有線頭阻塞:
采用新的二進(jìn)制分幀層的機(jī)制,組成消息的幀可以亂序發(fā)送,幀到達(dá)對(duì)端重新組裝,不需要等待前面的幀到達(dá)后再發(fā)送。
報(bào)頭壓縮:
HTTP/2 協(xié)議中采用 HPACK 來壓縮請(qǐng)求頭和響應(yīng)頭,降低協(xié)議開銷。
更加安全:
當(dāng)前主流瀏覽器,都只支持基于 HTTPS 部署的 HTTP/2。
HTTP 2.0 性能增強(qiáng)的核心,全在于新增的二進(jìn)制分幀層,它定義了如何封裝 HTTP 消息并在客戶端和服務(wù)器之間傳輸,和 HTTP/1.x 對(duì)比如下圖:
這里所謂的 “層”,指的是位于套接字接口與應(yīng)用可見的高級(jí) HTTP API 之間一個(gè)經(jīng)過優(yōu)化的新編碼機(jī)制:HTTP 的語義(包括各種動(dòng)詞、方法、標(biāo)頭)都不受影響,不同的是傳輸期間對(duì)它們的編碼方式變了。HTTP/1.x 協(xié)議以換行符作為純文本的分隔符,而 HTTP/2 將所有傳輸?shù)男畔⒎指顬楦〉南⒑蛶?,并采用二進(jìn)制格式對(duì)它們編碼。
這樣一來,客戶端和服務(wù)器為了相互理解,都必須使用新的二進(jìn)制編碼機(jī)制:HTTP/1.x 客戶端無法理解只支持 HTTP/2 的服務(wù)器,反之亦然。不過不要緊,現(xiàn)有的應(yīng)用不必?fù)?dān)心這些變化,因?yàn)榭蛻舳撕头?wù)器會(huì)替我們完成必要的分幀工作。
新的二進(jìn)制分幀機(jī)制改變了客戶端與服務(wù)器之間交換數(shù)據(jù)的方式。 為了說明這個(gè)過程,我們需要了解 HTTP/2 的三個(gè)概念:
數(shù)據(jù)流:已建立的連接內(nèi)的雙向字節(jié)流,可以承載一條或多條消息。
消息:與邏輯請(qǐng)求或響應(yīng)消息對(duì)應(yīng)的完整的一系列幀。
幀:HTTP/2 通信的最小單位,每個(gè)幀都包含幀頭,至少也會(huì)標(biāo)識(shí)出當(dāng)前幀所屬的數(shù)據(jù)流。
這些概念的關(guān)系總結(jié)如下:
所有通信都在一個(gè) TCP 連接上完成,此連接可以承載任意數(shù)量的雙向數(shù)據(jù)流。
每個(gè)數(shù)據(jù)流都有一個(gè)唯一的標(biāo)識(shí)符和可選的優(yōu)先級(jí)信息,用于承載雙向消息。
每條消息都是一條邏輯 HTTP 消息(例如請(qǐng)求或響應(yīng)),包含一個(gè)或多個(gè)幀。
幀是最小的通信單位,承載著特定類型的數(shù)據(jù),例如 HTTP 標(biāo)頭、消息負(fù)載等等。 來自不同 數(shù)據(jù)流的幀可以交錯(cuò)發(fā)送,然后再根據(jù)每個(gè)幀頭的數(shù)據(jù)流標(biāo)識(shí)符重新組裝,如下圖:
簡(jiǎn)言之,HTTP/2 將 HTTP 協(xié)議通信分解為二進(jìn)制編碼幀的交換,這些幀對(duì)應(yīng)著特定數(shù)據(jù)流中的消息。所有這些都在一個(gè) TCP 連接內(nèi)復(fù)用。這是 HTTP/2 協(xié)議所有其他功能和性能優(yōu)化的基礎(chǔ)。
多路復(fù)用在 HTTP/1.x 中,如果客戶端要想發(fā)起多個(gè)并行請(qǐng)求以提升性能,則必須使用多個(gè) TCP 連接。這是 HTTP/1.x 交付模型的直接結(jié)果,該模型可以保證每個(gè)連接每次只交付一個(gè)響應(yīng)(響應(yīng)排隊(duì))。更糟糕的是,這種模型也會(huì)導(dǎo)致隊(duì)首阻塞,從而造成底層 TCP 連接的效率低下。
HTTP/2 中新的二進(jìn)制分幀層突破了這些限制,實(shí)現(xiàn)了完整的請(qǐng)求和響應(yīng)復(fù)用:客戶端和服務(wù)器可以將 HTTP 消息分解為互不依賴的幀,然后交錯(cuò)發(fā)送,最后再在另一端把它們重新組裝起來。
上圖捕捉了同一個(gè)連接內(nèi)并行的多個(gè)數(shù)據(jù)流??蛻舳苏谙蚍?wù)器傳輸一個(gè) DATA 幀(數(shù)據(jù)流 5),與此同時(shí),服務(wù)器正向客戶端交錯(cuò)發(fā)送數(shù)據(jù)流 1 和數(shù)據(jù)流 3 的一系列幀。因此,一個(gè)連接上同時(shí)有三個(gè)并行數(shù)據(jù)流。
將 HTTP 消息分解為獨(dú)立的幀,交錯(cuò)發(fā)送,然后在另一端重新組裝是 HTTP 2 最重要的一項(xiàng)增強(qiáng)。事實(shí)上,這個(gè)機(jī)制會(huì)在整個(gè)網(wǎng)絡(luò)技術(shù)棧中引發(fā)一系列連鎖反應(yīng),從而帶來巨大的性能提升,讓我們可以:
并行交錯(cuò)地發(fā)送多個(gè)請(qǐng)求,請(qǐng)求之間互不影響。
并行交錯(cuò)地發(fā)送多個(gè)響應(yīng),響應(yīng)之間互不干擾。
使用一個(gè)連接并行發(fā)送多個(gè)請(qǐng)求和響應(yīng)。
不必再為繞過 HTTP/1.x 限制而做很多工作(對(duì) HTTP/1.x 進(jìn)行優(yōu)化,例如級(jí)聯(lián)文件、image sprites 和域名分片。
消除不必要的延遲和提高現(xiàn)有網(wǎng)絡(luò)容量的利用率,從而減少頁(yè)面加載時(shí)間。
等等…
HTTP/2 中的新二進(jìn)制分幀層解決了 HTTP/1.x 中存在的隊(duì)首阻塞問題,也消除了并行處理和發(fā)送請(qǐng)求及響應(yīng)時(shí)對(duì)多個(gè)連接的依賴。結(jié)果,應(yīng)用速度更快、開發(fā)更簡(jiǎn)單、部署成本更低。
請(qǐng)求重置HTTP 1.1 的有一個(gè)缺點(diǎn)是:當(dāng)一個(gè)含有確切值的 Content-Length 的 HTTP 消息被送出之后,你就很難中斷它了。當(dāng)然,通常你可以斷開整個(gè) TCP 連接(但也不總是可以這樣),但這樣導(dǎo)致的代價(jià)就是需要通過三次握手來重新建立一個(gè)新的 TCP 連接。
一個(gè)更好的方案是只終止當(dāng)前傳輸?shù)南⒉⒅匦掳l(fā)送一個(gè)新的。在 HTTP/2 里面,我們可以通過發(fā)送 RST_STREAM 幀來實(shí)現(xiàn)這種需求,從而避免浪費(fèi)帶寬和中斷已有的連接。
將 HTTP 消息分解為很多獨(dú)立的幀之后,我們就可以復(fù)用多個(gè)數(shù)據(jù)流中的幀,客戶端和服務(wù)器交錯(cuò)發(fā)送和傳輸這些幀的順序就成為關(guān)鍵的性能決定因素。為了做到這一點(diǎn),HTTP/2 標(biāo)準(zhǔn)允許每個(gè)數(shù)據(jù)流都有一個(gè)關(guān)聯(lián)的權(quán)重和依賴關(guān)系:
可以向每個(gè)數(shù)據(jù)流分配一個(gè)介于 1 至 256 之間的整數(shù)。
每個(gè)數(shù)據(jù)流與其他數(shù)據(jù)流之間可以存在顯式依賴關(guān)系。
數(shù)據(jù)流依賴關(guān)系和權(quán)重的組合讓客戶端可以構(gòu)建和傳遞 “優(yōu)先級(jí)樹”,表明它傾向于如何接收響應(yīng)。反過來,服務(wù)器可以使用此信息通過控制 CPU、內(nèi)存和其他資源的分配設(shè)定數(shù)據(jù)流處理的優(yōu)先級(jí),在資源數(shù)據(jù)可用之后,帶寬分配可以確保將高優(yōu)先級(jí)響應(yīng)以最優(yōu)方式傳輸至客戶端。
如上圖,HTTP/2 內(nèi)的數(shù)據(jù)流依賴關(guān)系通過將另一個(gè)數(shù)據(jù)流的唯一標(biāo)識(shí)符作為父項(xiàng)引用進(jìn)行聲明;如果忽略標(biāo)識(shí)符,相應(yīng)數(shù)據(jù)流將依賴于 “根數(shù)據(jù)流”。聲明數(shù)據(jù)流依賴關(guān)系指出,應(yīng)盡可能先向父數(shù)據(jù)流分配資源,然后再向其依賴項(xiàng)分配資源。換句話說,“請(qǐng)先處理和傳輸響應(yīng) D,然后再處理和傳輸響應(yīng) C”。
共享相同父項(xiàng)的數(shù)據(jù)流(即,同級(jí)數(shù)據(jù)流)應(yīng)按其權(quán)重比例分配資源。 例如,如果數(shù)據(jù)流 A 的權(quán)重為 12,其同級(jí)數(shù)據(jù)流 B 的權(quán)重為 4,那么要確定每個(gè)數(shù)據(jù)流應(yīng)接收的資源比例,請(qǐng)執(zhí)行以下操作:
將所有權(quán)重求和:4 + 12 = 16
將每個(gè)數(shù)據(jù)流權(quán)重除以總權(quán)重:A = 12/16, B = 4/16 因此,數(shù)據(jù)流 A 應(yīng)獲得四分之三的可用資源,數(shù)據(jù)流 B 應(yīng)獲得四分之一的可用資源;數(shù)據(jù)流 B 獲得的資源是數(shù)據(jù)流 A 所獲資源的三分之一。 我們來看一下上圖中的其他幾個(gè)動(dòng)手示例:順序?yàn)閺淖蟮接遥?/p>
數(shù)據(jù)流 A 和數(shù)據(jù)流 B 都沒有指定父依賴項(xiàng),依賴于顯式 “根數(shù)據(jù)流”;A 的權(quán)重為 12,B 的權(quán)重為 4。因此,根據(jù)比例權(quán)重:數(shù)據(jù)流 B 獲得的資源是 A 所獲資源的三分之一。 數(shù)據(jù)流 D 依賴于根數(shù)據(jù)流;C 依賴于 D。因此,D 應(yīng)先于 C 獲得完整資源分配。權(quán)重不重要,因?yàn)?C 的依賴關(guān)系擁有更高的優(yōu)先級(jí)。 數(shù)據(jù)流 D 應(yīng)先于 C 獲得完整資源分配;C 應(yīng)先于 A 和 B 獲得完整資源分配;數(shù)據(jù)流 B 獲得的資源是 A 所獲資源的三分之一。 數(shù)據(jù)流 D 應(yīng)先于 E 和 C 獲得完整資源分配;E 和 C 應(yīng)先于 A 和 B 獲得相同的資源分配;A 和 B 應(yīng)基于其權(quán)重獲得比例分配。
如上面的示例所示,數(shù)據(jù)流依賴關(guān)系和權(quán)重的組合明確表達(dá)了資源優(yōu)先級(jí),這是一種用于提升瀏覽性能的關(guān)鍵功能,網(wǎng)絡(luò)中擁有多種資源類型,它們的依賴關(guān)系和權(quán)重各不相同。不僅如此,HTTP/2 協(xié)議還允許客戶端隨時(shí)更新這些優(yōu)先級(jí),進(jìn)一步優(yōu)化了瀏覽器性能。換句話說,我們可以根據(jù)用戶互動(dòng)和其他信號(hào)更改依賴關(guān)系和重新分配權(quán)重。
注:數(shù)據(jù)流依賴關(guān)系和權(quán)重表示傳輸優(yōu)先級(jí),而不是要求,因此不能保證特定的處理或傳輸順序。即,客戶端無法強(qiáng)制服務(wù)器通過數(shù)據(jù)流優(yōu)先級(jí)以特定順序處理數(shù)據(jù)流。 盡管這看起來違反直覺,但卻是一種必要行為。 我們不希望在優(yōu)先級(jí)較高的資源受到阻止時(shí),還阻止服務(wù)器處理優(yōu)先級(jí)較低的資源。
每個(gè)來源一個(gè)連接有了新的分幀機(jī)制后,HTTP/2 不再依賴多個(gè) TCP 連接去并行復(fù)用數(shù)據(jù)流;每個(gè)數(shù)據(jù)流都拆分成很多幀,而這些幀可以交錯(cuò),還可以分別設(shè)定優(yōu)先級(jí)。因此,所有 HTTP/2 連接都是永久的,而且僅需要每個(gè)來源一個(gè)連接,隨之帶來諸多性能優(yōu)勢(shì)。
大多數(shù) HTTP 傳輸都是短暫且急促的,而 TCP 則針對(duì)長(zhǎng)時(shí)間的批量數(shù)據(jù)傳輸進(jìn)行了優(yōu)化。 通過重用相同的連接,HTTP/2 既可以更有效地利用每個(gè) TCP 連接,也可以顯著降低整體協(xié)議開銷。不僅如此,使用更少的連接還可以減少占用的內(nèi)存和處理空間,也可以縮短完整連接路徑(即,客戶端、可信中介和源服務(wù)器之間的路徑)這降低了整體運(yùn)行成本并提高了網(wǎng)絡(luò)利用率和容量。 因此,遷移到 HTTP/2 不僅可以減少網(wǎng)絡(luò)延遲,還有助于提高通量和降低運(yùn)行成本。
在 HTTP/2 RFC 文檔中建議實(shí)現(xiàn)時(shí)客戶端不應(yīng)該在給定的目的地上打開多個(gè) HTTP/2 連接,目的地是由給定的 URI 確定的 IP 地址及 TCP 端口,或者配置的代理 IP 和端口。當(dāng)然客戶端可以使用不相同的服務(wù)端名稱標(biāo)識(shí)值或者提供不一樣的 ssl 證書對(duì)相同的 IP 地址及 TCP 端口打開多個(gè)連接,但應(yīng)該避免對(duì)相同的配置上創(chuàng)建多個(gè)連接。
注:連接數(shù)量減少對(duì)提升 HTTPS 部署的性能來說是一項(xiàng)特別重要的功能:可以減少開銷較大的 TLS 連接數(shù)、提升會(huì)話重用率,以及從整體上減少所需的客戶端和服務(wù)器資源。
流量控制是一種阻止發(fā)送方向接收方發(fā)送大量數(shù)據(jù)的機(jī)制,以免超出后者的需求或處理能力:發(fā)送方可能非常繁忙、處于較高的負(fù)載之下,也可能僅僅希望為特定數(shù)據(jù)流分配固定量的資源。例如,客戶端可能請(qǐng)求了一個(gè)具有較高優(yōu)先級(jí)的大型視頻流,但是用戶已經(jīng)暫停視頻,客戶端現(xiàn)在希望暫停或限制從服務(wù)器的傳輸,以免提取和緩沖不必要的數(shù)據(jù)。再比如,一個(gè)代理服務(wù)器可能具有較快的下游連接和較慢的上游連接,并且也希望調(diào)節(jié)下游連接傳輸數(shù)據(jù)的速度以匹配上游連接的速度來控制其資源利用率;等等。
不過,由于 HTTP/2 數(shù)據(jù)流在一個(gè) TCP 連接內(nèi)復(fù)用,TCP 流控制既不夠精細(xì),也無法提供必要的應(yīng)用級(jí) API 來調(diào)節(jié)各個(gè)數(shù)據(jù)流的傳輸。為了解決這一問題,HTTP/2 提供了一組簡(jiǎn)單的構(gòu)建塊,這些構(gòu)建塊允許客戶端和服務(wù)器實(shí)現(xiàn)其自己的數(shù)據(jù)流和連接級(jí)流量控制:
流量控制具有方向性,每個(gè)接收方都可以根據(jù)自身需要選擇為每個(gè)數(shù)據(jù)流和整個(gè)連接設(shè)置任意的窗口大小。
流量控制基于窗口更新幀進(jìn)行,即接收方廣播自己準(zhǔn)備接收某個(gè)數(shù)據(jù)流的多少字節(jié),以及對(duì)整個(gè)連接要接收多少字節(jié)。
流量控制窗口大小通過 WINDOW_UPDATE 幀更新,這個(gè)字段制定了流 ID 和窗口遞增值。
流量控制可以由接收方禁用,包括針對(duì)個(gè)別的流和針對(duì)整個(gè)連接。
流量控制基于每一跳進(jìn)行,而非端到端控制。即,可信中介可以使用它來控制資源使用,以及基于自身?xiàng)l件和啟發(fā)式算法實(shí)現(xiàn)資源分配機(jī)制。
HTTP/2 未指定任何特定算法來實(shí)現(xiàn)流量控制。不過,它提供了簡(jiǎn)單的構(gòu)建塊并推遲了客戶端和服務(wù)器實(shí)現(xiàn),可以實(shí)現(xiàn)自定義策略來調(diào)節(jié)資源使用和分配,以及實(shí)現(xiàn)新傳輸能力,同時(shí)提升網(wǎng)絡(luò)應(yīng)用的實(shí)際性能和感知性能。
例如,應(yīng)用層流量控制允許瀏覽器僅提取一部分特定資源,通過將數(shù)據(jù)流流控制窗口減小為零來暫停提取,稍后再行恢復(fù)。換句話說,它允許瀏覽器提取圖像預(yù)覽或首次掃描結(jié)果,進(jìn)行顯示并允許其他高優(yōu)先級(jí)提取繼續(xù),然后在更關(guān)鍵的資源完成加載后恢復(fù)提取。
服務(wù)器推送HTTP/2 新增的另一個(gè)強(qiáng)大的新功能是,服務(wù)器可以對(duì)一個(gè)客戶端請(qǐng)求發(fā)送多個(gè)響應(yīng)。 換句話說,除了對(duì)最初請(qǐng)求的響應(yīng)外,服務(wù)器還可以向客戶端推送額外資源(如下圖),而無需客戶端明確地請(qǐng)求。
注:HTTP/2 打破了嚴(yán)格的請(qǐng)求 - 響應(yīng)語義,支持一對(duì)多和服務(wù)器發(fā)起的推送工作流,在瀏覽器內(nèi)外開啟了全新的互動(dòng)可能性。這是一項(xiàng)使能功能,對(duì)我們思考協(xié)議、協(xié)議用途和使用方式具有重要的長(zhǎng)期影響。
為什么在瀏覽器中需要一種此類機(jī)制呢?一個(gè)典型的網(wǎng)絡(luò)應(yīng)用包含多種資源,客戶端需要檢查服務(wù)器提供的文檔才能逐個(gè)找到它們。那為什么不讓服務(wù)器提前推送這些資源,從而減少額外的延遲時(shí)間呢?服務(wù)器已經(jīng)知道客戶端下一步要請(qǐng)求什么資源,這時(shí)候服務(wù)器推送即可派上用場(chǎng)。
事實(shí)上,如果在網(wǎng)頁(yè)中內(nèi)聯(lián)過 CSS、JavaScript,或者通過數(shù)據(jù) URI 內(nèi)聯(lián)過其他資產(chǎn),那么就已經(jīng)親身體驗(yàn)過服務(wù)器推送了。對(duì)于將資源手動(dòng)內(nèi)聯(lián)到文檔中的過程,我們實(shí)際上是在將資源推送給客戶端,而不是等待客戶端請(qǐng)求。使用 HTTP/2,我們不僅可以實(shí)現(xiàn)相同結(jié)果,還會(huì)獲得其他性能優(yōu)勢(shì)。 推送資源可以進(jìn)行以下處理:
由客戶端緩存
在不同頁(yè)面之間重用
與其他資源一起復(fù)用
由服務(wù)器設(shè)定優(yōu)先級(jí)
被客戶端拒絕
PUSH_PROMISE 101所有服務(wù)器推送數(shù)據(jù)流都由 PUSH_PROMISE 幀發(fā)起,表明了服務(wù)器向客戶端推送所述資源的意圖,并且需要先于請(qǐng)求推送資源的響應(yīng)數(shù)據(jù)傳輸。這種傳輸順序非常重要:客戶端需要了解服務(wù)器打算推送哪些資源,以免為這些資源創(chuàng)建重復(fù)請(qǐng)求。滿足此要求的最簡(jiǎn)單策略是先于父響應(yīng)(即,DATA 幀)發(fā)送所有 PUSH_PROMISE 幀,其中包含所承諾資源的 HTTP 標(biāo)頭。
在客戶端接收到 PUSH_PROMISE 幀后,它可以根據(jù)自身情況選擇拒絕數(shù)據(jù)流(通過 RST_STREAM 幀)。 (如果資源已經(jīng)位于緩存中,可能會(huì)發(fā)生這種情況。) 這是一個(gè)相對(duì)于 HTTP/1.x 的重要提升。 相比之下,使用資源內(nèi)聯(lián)(一種受歡迎的 HTTP/1.x“優(yōu)化”)等同于 “強(qiáng)制推送”:客戶端無法選擇拒絕、取消或多帶帶處理內(nèi)聯(lián)的資源。
使用 HTTP/2,客戶端仍然完全掌控服務(wù)器推送的使用方式。客戶端可以限制并行推送的數(shù)據(jù)流數(shù)量;調(diào)整初始的流控制窗口以控制在數(shù)據(jù)流首次打開時(shí)推送的數(shù)據(jù)量;或完全停用服務(wù)器推送。這些優(yōu)先級(jí)在 HTTP/2 連接開始時(shí)通過 SETTINGS 幀傳輸,可能隨時(shí)更新。
推送的每個(gè)資源都是一個(gè)數(shù)據(jù)流,與內(nèi)嵌資源不同,客戶端可以對(duì)推送的資源逐一復(fù)用、設(shè)定優(yōu)先級(jí)和處理。 瀏覽器強(qiáng)制執(zhí)行的唯一安全限制是,推送的資源必須符合原點(diǎn)相同這一政策:服務(wù)器對(duì)所提供內(nèi)容必須具有權(quán)威性。
每個(gè) HTTP 傳輸都承載一組報(bào)頭,這些報(bào)頭說明了傳輸?shù)馁Y源及其屬性。 在 HTTP/1.x 中,此元數(shù)據(jù)始終以純文本形式,通常會(huì)給每個(gè)傳輸增加 500–800 字節(jié)的開銷。如果使用 HTTP Cookie,增加的開銷有時(shí)會(huì)達(dá)到上千字節(jié)。為了減少此開銷和提升性能, HTTP/2 使用 HPACK 壓縮格式壓縮請(qǐng)求和響應(yīng)標(biāo)頭元數(shù)據(jù),這種格式采用兩種簡(jiǎn)單但是強(qiáng)大的技術(shù):
這種格式支持通過靜態(tài) Huffman 編碼對(duì)傳輸?shù)臉?biāo)頭字段進(jìn)行編碼,從而減小了各個(gè)傳輸?shù)拇笮 ?/p>
這種格式要求客戶端和服務(wù)器同時(shí)維護(hù)和更新一個(gè)包含之前見過的標(biāo)頭字段的索引列表(換句話說,它可以建立一個(gè)共享的壓縮上下文),此列表隨后會(huì)用作參考,對(duì)之前傳輸?shù)闹颠M(jìn)行有效編碼。
利用 Huffman 編碼,可以在傳輸時(shí)對(duì)各個(gè)值進(jìn)行壓縮,而利用之前傳輸值的索引列表,我們可以通過傳輸索引值的方式對(duì)重復(fù)值進(jìn)行編碼,索引值可用于有效查詢和重構(gòu)完整的標(biāo)頭鍵值對(duì)。
作為一種進(jìn)一步優(yōu)化方式,HPACK 壓縮上下文包含一個(gè)靜態(tài)表和一個(gè)動(dòng)態(tài)表:靜態(tài)表在規(guī)范中定義,并提供了一個(gè)包含所有連接都可能使用的常用 HTTP 標(biāo)頭字段(例如,有效標(biāo)頭名稱)的列表;動(dòng)態(tài)表最初為空,將根據(jù)在特定連接內(nèi)交換的值進(jìn)行更新。因此,為之前未見過的值采用靜態(tài) Huffman 編碼,并替換每一側(cè)靜態(tài)表或動(dòng)態(tài)表中已存在值的索引,可以減小每個(gè)請(qǐng)求的大小。
注:在 HTTP/2 中,請(qǐng)求和響應(yīng)標(biāo)頭字段的定義保持不變,僅有一些微小的差異:所有標(biāo)頭字段名稱均為小寫,請(qǐng)求行現(xiàn)在拆分成各個(gè) :method、:scheme、:authority 和 :path 偽標(biāo)頭字段。
至于 HPACK 壓縮的詳細(xì)介紹,請(qǐng)點(diǎn)擊這里:HTTP/2 頭部壓縮技術(shù)介紹或者官方 RFC。
HTTP/2 協(xié)議實(shí)際性能測(cè)試與分析為了測(cè)試 HTTP/2 對(duì) web 訪問的性能提升,本人借助 bbs 產(chǎn)品線的 miui 官方網(wǎng)站,開啟了 tengine 的 HTTP/2 的支持,取一周的訪問數(shù)據(jù)與 HTTPS、HTTP 訪問數(shù)據(jù)進(jìn)行對(duì)比分析,詳細(xì)結(jié)果如下:
采集數(shù)據(jù)量響應(yīng)類型分布
請(qǐng)求類別 | http | https | http2 |
---|---|---|---|
2xx | 945144 | 927482 | 505702 |
3xx | 243075 | 258331 | 681997 |
4xx | 2372 | 4750 | 2813 |
5xx | 9 | 37 | 88 |
sum | 1190600 | 1190600 | 1190600 |
2xx 請(qǐng)求各個(gè)響應(yīng)時(shí)間段占比(基于 nginx log 的 request_time 數(shù)據(jù))
時(shí)間 | http | https | http2 |
---|---|---|---|
<50ms | 79.75% | 78.89% | 82.60% |
<100ms | 87.24% | 87.47% | 89.86% |
<150ms | 91.12% | 91.90% | 93.19% |
<200ms | 92.72% | 93.82% | 94.54% |
<2s | 98.99% | 99.71% | 99.48% |
2xx 請(qǐng)求響應(yīng)時(shí)間大于 7 秒的數(shù)量 (基于 nginx log 的 request_time 數(shù)據(jù))
時(shí)間 | http | https | http2 |
---|---|---|---|
>7s | 1960(0.207%) | 603(0.065%) | 950(0.187%) |
>10s | 1519(0.160%) | 420(0.045%) | 638(0.126%) |
>30s | 594(0.062%) | 165(0.017%) | 190(0.037%) |
>60s | 259(0.027%) | 104(0.011%) | 97(0.019%) |
2xx 請(qǐng)求后端響應(yīng)時(shí)間超過 7 秒的數(shù)量(基于 nginx log 的 upstream_response_time)
時(shí)間 | http | https | http2 |
---|---|---|---|
>7s | 68(0.007%) | 88(0.017%) | 58(0.006%) |
301 請(qǐng)求響應(yīng)大?。ɑ?nginx 的 request_length 和 bytes_sent 數(shù)據(jù))
/static/image/common/miui9.jpg | 請(qǐng)求數(shù) | 總大小(byte) | avg(byte) | 請(qǐng)求總大小(byte) | 請(qǐng)求avg(byte) |
---|---|---|---|---|---|
http | 2722 | 1460146 | 536 | 3194589 | 1173 |
https | 4695 | 2618278 | 415 | 8019924 | 1708 |
http2 | 16239 | 6751609 | 557 | 1209570 | 74 |
200 請(qǐng)求響應(yīng)大小(基于 nginx log 的 request_length 和 bytes_sent 數(shù)據(jù))
/favicon.ico | 請(qǐng)求數(shù) | 響應(yīng)總大小(byte) | 響應(yīng)avg(byte) | 請(qǐng)求總大小(byte) | 請(qǐng)求avg(byte) |
---|---|---|---|---|---|
http | 17658 | 23552229 | 1413 | 15300656 | 866 |
https | 117178 | 165623779 | 1413 | 122356406 | 1044 |
http2 | 80856 | 105496656 | 1304 | 10015908 | 123 |
客戶端分析(基于 nginx log 的 user_agent 數(shù)據(jù))
協(xié)議 | chrome | MSIE | safari | FireFox | Crawlers | others | unknown | |
---|---|---|---|---|---|---|---|---|
http | 23.53% | 4.26% | 3.56% | 0.67% | 4.01% | 15.07% | 48.22% | |
https | 79.24% | 5.93% | 3.67% | 1.54% | 7.87% | 1.42% | 0.1% | |
http2 | 88.57% | 4.93% | 1.91% | 1.57% | 0% | 2.9% | 0.03% |
平臺(tái)分析(基于 nginx log 的 user_agent 數(shù)據(jù))
協(xié)議 | Android | Windows | Linux | IOS | Darwin | unknown | |
---|---|---|---|---|---|---|---|
http | 28.4% | 16.07% | 0.29% | 2.46% | 0.12% | 51.86% | |
https | 64.85% | 24.65% | 0.62% | 0.54% | 0.29% | 9.05% | |
http2 | 40.06% | 57.62% | 1.49% | 0.44% | 0% | 0.02% |
典型網(wǎng)絡(luò) RTT 下(50~200ms),HTTP/2 對(duì)網(wǎng)絡(luò)延遲性能有一定程度的提升,優(yōu)于 HTTP/1.x 和 HTTPS。
在 2xx 和 3xx 請(qǐng)求下 HTTP/2 利用 HPACK 機(jī)制壓縮響應(yīng)頭和請(qǐng)求頭,有效降低了請(qǐng)求和響應(yīng)的大小,節(jié)省了流量,降低了協(xié)議消耗。
目前 HTTP/2 大部分流量來自于 chrome,其對(duì) HTTP/2 的支持性也是最好的。
HTTP/2 協(xié)議部署建議 建議一:現(xiàn)在是否需要遷移到 HTTP/2實(shí)現(xiàn) HTTP/2 很簡(jiǎn)單,不過,HTTP/2 并不是萬能的銀彈,它只對(duì)某些 Web 應(yīng)用有用,對(duì)另外一些則沒那么有用。
如果你使用 SSL/TLS(以后簡(jiǎn)稱 TLS),那么 HTTP/2 可以提升網(wǎng)站性能。如果你沒有,那在使用 HTTP/2 之前要先支持 TLS。這時(shí)候,使用 TLS 的性能損耗大致可以被使用 HTTP/2 的性能提升抵銷。不過還是建議你在實(shí)際應(yīng)用之前先測(cè)試一下。
HTTP/2 有五大優(yōu)勢(shì):
每個(gè)服務(wù)器只用一個(gè)連接。HTTP/2 對(duì)每個(gè)服務(wù)器只使用一個(gè)連接,而不是每個(gè)文件一個(gè)連接。這樣,就省掉了多次建立連接的時(shí)間,這個(gè)時(shí)間對(duì) TLS 尤其明顯,因?yàn)?TLS 連接費(fèi)時(shí)間。
加速 TLS 交付。HTTP/2 只需一次耗時(shí)的 TLS 握手,并且通過一個(gè)連接上的多路利用實(shí)現(xiàn)最佳性能。HTTP/2 還會(huì)壓縮首部數(shù)據(jù),省掉 HTTP/1.x 時(shí)代所需的一些優(yōu)化工作,比如拼接文件,從而提高緩存利用率。
簡(jiǎn)化 Web 應(yīng)用。使用 HTTP/2 可以讓 Web 開發(fā)者省很多事,因?yàn)椴挥迷僮瞿切┽槍?duì) HTTP/1.x 的優(yōu)化工作了。
適合內(nèi)容混雜的頁(yè)面。HTTP/2 特別適合混合了 HTML、CSS、JavaScript、圖片和有限多媒體的傳統(tǒng)頁(yè)面。瀏覽器可以優(yōu)先安排那些重要的文件請(qǐng)求,讓頁(yè)面的關(guān)鍵部分先出現(xiàn),快出現(xiàn)。
更安全。通過減少 TLS 的性能損失,可以讓更多應(yīng)用使用 TLS,從而讓用戶信息更安全。
相應(yīng)地,HTTP/2 也有五個(gè)不足之處。
單連接開銷比較大。HPACK 數(shù)據(jù)壓縮算法會(huì)更新兩端的查找表。這樣可以讓連接有狀態(tài),而破壞狀態(tài)就意味著要重建查找表,另外單連接占用內(nèi)存較多。
你可能不需要 SSL。如果你的數(shù)據(jù)不需要保護(hù),或者已經(jīng)使用 DRM 或其他編碼進(jìn)行保護(hù)了,那么 TLS 的安全性對(duì)你可能無所謂。
需要拋棄針對(duì) HTTP/1.x 的優(yōu)化。HTTP/1.x 優(yōu)化在支持 HTTP/2 的瀏覽器中會(huì)影響性能,因此可能需要花時(shí)間把它們推倒重來。
對(duì)下載大文件不利。如果你的應(yīng)用主要提供大文件下載或者流媒體播放,那可能不想用 TLS,而且在只有一個(gè)流的情況下,多路復(fù)用也體現(xiàn)不出什么優(yōu)勢(shì)。
你的客戶也許不在乎。你的客戶很可能不在乎他分享的自家貓咪的視頻是否受到 TLS 和 HTTP/2 的保護(hù)。
總之,一切要看性能。這方面,有好消息也有壞消息。
好消息是 nginx 官方團(tuán)隊(duì)在內(nèi)部對(duì) NGINX 做過測(cè)試,結(jié)果從理論上能夠得到印證:對(duì)于要通過典型網(wǎng)絡(luò)延遲請(qǐng)求的混合內(nèi)容網(wǎng)頁(yè),HTTP/2 的性能好于 HTTP/1.x 和 HTTPS?;谶B接的 RTT,結(jié)果可以分三種情況。
很低的 RTT(0-20ms):HTTP/1.x、HTTP/2 和 HTTPS 基本無差別。
典型網(wǎng)絡(luò) RTT(30-250ms):HTTP/2 比 HTTP/1.x 快,而且它們都比 HTTPS 快。美國(guó)兩個(gè)相鄰城市間的 RTT 約為 30 ms,而東西海岸間(約 3000 英里)則約為 70 ms。東京到倫敦間最短路徑的 RTT 大約 240 ms。
高 RTT(300ms 及以上):HTTP/1.x 比 HTTP/2 快,后者又比 HTTPS 快。
這張圖顯示了首次渲染的時(shí)間,也就是用戶第一次在自己屏幕上看到網(wǎng)頁(yè)內(nèi)容的時(shí)間。這個(gè)時(shí)間一般認(rèn)為關(guān)系到用戶對(duì)網(wǎng)站響應(yīng)速度的感知。
然而,每個(gè)網(wǎng)頁(yè)都不相同,實(shí)際上每個(gè)用戶的會(huì)話也不一樣。如果你托管流媒體或提供大文件下載,那你的決定可能不一樣,甚至相反。
建議二:終止 HTTP/2 和 TLS終止協(xié)議意味著客戶端使用期望的協(xié)議連接代理服務(wù)器,比如 TLS 或 HTTP/2,然后代理服務(wù)器再去連接應(yīng)用服務(wù)器、數(shù)據(jù)庫(kù)服務(wù)器等,但不需要使用相同的協(xié)議,如下圖所示。
使用獨(dú)立的服務(wù)器終止協(xié)議意味著使用多服務(wù)器架構(gòu)。多服務(wù)器可能是多個(gè)物理服務(wù)器、多個(gè)虛擬服務(wù)器,或者 AWS 這樣的云環(huán)境中的多個(gè)虛擬服務(wù)器實(shí)例。多服務(wù)器就比單服務(wù)器復(fù)雜,或者比應(yīng)用服務(wù)器 / 數(shù)據(jù)庫(kù)服務(wù)器的組合復(fù)雜。不過,多服務(wù)器架構(gòu)有很多好處,而且很多流量大的網(wǎng)站也必須用這種架構(gòu)。
配置了服務(wù)器或者虛擬服務(wù)器之后,很多事情都成為可能。新服務(wù)器可以分擔(dān)其他服務(wù)器的負(fù)載,可用于負(fù)載平衡、靜態(tài)文件緩存和其他用途。另外,也可以讓添加和替換應(yīng)用服務(wù)器或其他服務(wù)器更容易。
NGINX 和 NGINX Plus 經(jīng)常被用來終止 TLS 和 HTTP/2 協(xié)議、負(fù)載平衡。已有環(huán)境不必改動(dòng),除非要把 NGINX 服務(wù)器挪到前端。
在決定采用 HTTP/2 之前,首先得知道你的代碼有哪些是針對(duì) HTTP/1.x 優(yōu)化過的。大概有四方面的優(yōu)化。
分域存儲(chǔ)。為了實(shí)現(xiàn)并行請(qǐng)求文件,你可能把文件分散到了不同的域里,CDN 會(huì)自動(dòng)這么做。但分域存儲(chǔ)會(huì)影響 HTTP/2 的性能,建議使用 HTTP/2 友好的分域存儲(chǔ)(建議六),只針對(duì) HTTP/1.x 用戶分域。
雪碧圖。雪碧圖把很多圖片拼成一個(gè)文件,然后通過代碼按需取得每個(gè)圖片。雪碧圖在 HTTP/2 的環(huán)境下沒太大用處,但還是有點(diǎn)用的。
拼接的代碼文件。與使用雪碧圖的原因類似,很多獨(dú)立的文件也會(huì)被弄成一個(gè),然后瀏覽器再?gòu)钠渲姓业讲⑦\(yùn)行需要的文件。
插入行內(nèi)的文件。CSS 代碼、JavaScript 代碼,甚至圖片等被直接插到 HTML 文件中的內(nèi)容。這樣可以減少文件傳輸,代價(jià)是初始 HTML 文件較大。
后面三種優(yōu)化都涉及把小文件塞進(jìn)一個(gè)較大的文件里,目的是減少新建連接的初始化和握手,這些操作對(duì) TLS 而言非常費(fèi)時(shí)間。
第一種優(yōu)化即分域存儲(chǔ)恰恰相反,強(qiáng)制打開多個(gè)連接,目的是并行地從不同的域獲取文件。這兩種看似矛盾的技術(shù)對(duì)于 HTTP/1.x 下的站點(diǎn)卻十分有效。然而,要用好這兩種技術(shù),必須投入大量時(shí)間、精力和資源,用于實(shí)現(xiàn)、管理和運(yùn)維。
在采用 HTTP/2 之前,需要找出應(yīng)用了這些優(yōu)化的代碼,分析一下它們會(huì)不會(huì)影響你的應(yīng)用設(shè)計(jì)和工作流程。這樣在遷移到 HTTP/2 之后,就可以著手改造它們,甚至撤銷某些優(yōu)化。
建議四:部署 HTTP/2事實(shí)上,部署 HTTP/2 并不難。如果使用 NGINX,只要在配置文件中啟動(dòng)相應(yīng)的協(xié)議就可以了。瀏覽器和服務(wù)器會(huì)協(xié)商采用什么協(xié)議,如果瀏覽器支持 HTTP/2(而且也在使用 TLS),就會(huì)使用 HTTP/2。
配置完服務(wù)器后,使用支持 HTTP/2 瀏覽器的用戶就會(huì)基于 HTTP/2 運(yùn)行你的應(yīng)用,而使用舊版本瀏覽器的用戶則會(huì)繼續(xù)使用 HTTP/1.x 運(yùn)行你的應(yīng)用,如下圖所示。如果你的網(wǎng)站流量非常大,那么應(yīng)該監(jiān)測(cè)改變前后的性能,對(duì)于性能降低的情況,可能就得撤銷更改。
注意:使用 HTTP/2 及其單連接之后,NGINX 某些配置的重要性會(huì)很明顯,特別要注意的是 output_buffers、proxy_buffers 和 ssl_buffer_size 等指令,多測(cè)試一下。參見 general configuration notes,特定的 SSL 建議,以及 NGINX 關(guān)于 SSL 性能的白皮書。
注意:使用 HTTP/2 傳輸密文要格外注意。HTTP/2 的 RFC 中有一個(gè)長(zhǎng)長(zhǎng)的列表,列出了要避免的加密套件。建議你自己也搞一個(gè)表格,啟用 ssl_buffer_size,然后在所有常用的瀏覽器版本下測(cè)試你想用的加密套件。
你說奇怪不,撤銷和修改針對(duì) HTTP/1.x 優(yōu)化的代碼居然是實(shí)現(xiàn) HTTP/2 最有創(chuàng)意的部分。這里面有幾個(gè)問題要注意,因?yàn)楹芏嗍略趺醋龆际强梢缘摹?br>在開始運(yùn)作之前,必須考慮舊版本瀏覽器用戶是否好過。之后,可以采取三個(gè)策略撤銷和修改 HTTP/1.x 的優(yōu)化。
什么也不用做。假如你并沒有針對(duì) HTTP/1.x 做過優(yōu)化,或者只做過少量?jī)?yōu)化,那么你幾乎什么也不用做,就可以直接遷移到 HTTP/2。
有選擇地去做。第二種情況是減少合并某些文件,而不是完全不合并。比如,牽扯到很多場(chǎng)景的雪碧圖就不用動(dòng),而被塞得滿滿的 HTML 可能就要分離出來一些。
完全撤銷 HTTP/1.x 優(yōu)化。可以不再做以前做過的任何優(yōu)化。
緩存還是普適的。理論上,緩存操作非常適合小文件特別多的情況。但是,小文件多也意味著文件 I/O 多。因此一些相近文件的合并還是必要的,一方面要考慮工作流程,另一方面要考慮應(yīng)用性能。建議多關(guān)注一下其他人在過渡到 HTTP/2 過程中的一些經(jīng)驗(yàn)。
建議六:實(shí)現(xiàn)智能分域分域存儲(chǔ)可能是最極端但也最成功的 HTTP/1.x 優(yōu)化策略。它能夠提升 HTTP/1.x 下的應(yīng)用性能,但在 HTTP/2 之下,其性能提升可以忽略不講(因?yàn)橹挥幸粋€(gè)連接。)
對(duì) HTTP/2 友好的分域,要保證以下兩點(diǎn):
讓多個(gè)域名解析到同一個(gè) IP。
確保證書包含通配符,以便所有分域名都可以使用,適當(dāng)?shù)亩嘤蜃C書當(dāng)然也可以。
有了這些保障,分域還會(huì)繼續(xù)對(duì) HTTP/1.x 有效,即域名仍然可以觸發(fā)瀏覽器創(chuàng)建更多連接,但對(duì) HTTP/2 則無效,因?yàn)檫@些域名會(huì)被看成同一個(gè)域,一個(gè)連接就可以訪問所有域名了。
HTTP/2 協(xié)議客戶端和服務(wù)支持情況 客戶端如果業(yè)務(wù)提供的是 web 形式的內(nèi)容,通過瀏覽器進(jìn)行訪問,由于當(dāng)前大部分的瀏覽器都已經(jīng)支持 HTTP/2 了,所以基本不需進(jìn)行任何操作,以下為支持 HTTP/2 的瀏覽器列表:
瀏覽器 | 支持HTTP/2 | 基于的內(nèi)核 | 備注 | |
---|---|---|---|---|
Chrome(49) | 支持 | 從49版本開始支持 | ||
IE 11 | 不支持 | win10系統(tǒng)上的IE11支持h2 | ||
Edge(14) | 支持 | 從14版本開始支持 | ||
Safari(10.1) | 支持 | 從10.1版本開始支持,但都需要OSX10.11+以上系統(tǒng)版本 | ||
Firefox(52) | 支持 | 從52版本開始支持 | ||
Opera(47.0.2631.55) | 支持 | 從46版本開始支持 | ||
搜狗瀏覽器(7.1.5.25209) | 支持 | |||
獵豹瀏覽器(6.0.114.15532) | 支持 | |||
2345加速瀏覽器(8.7.0.16013) | 支持 | |||
百度瀏覽器(8.7.5000.4962) | 不支持 | chrome 47 | ||
QQ瀏覽器(9.6.4) | 支持 | chrome 53 | ||
360瀏覽器(9.1.0.346) | 支持 | chrome 55 | ||
360極速瀏覽器(8.7.0.306) | 支持 |
安卓 app 基本采用 JAVA 開發(fā),由于各個(gè)應(yīng)用采用的與服務(wù)端通信的 http 庫(kù)各不相同,有的是采用 jdk 自帶的 httpurlconnection 庫(kù)和 httpclient 庫(kù),有的用的是安卓系統(tǒng)自帶的 webview 或者 volley(volley 的 HTTP/2 支持依賴于所使用的 httpstack,默認(rèn)使用 httpurlconection,但現(xiàn)在也有很多開發(fā)者使用第三方的 okhttp 作為 volley 的 httpstack),而有的開發(fā)者直接使用的是第三方庫(kù)類似于 okhttp,netty 等,這些 http 庫(kù)對(duì) http2.0 的支持情況各不相同。
基于 java 開發(fā)的 http 庫(kù)對(duì) HTTP/2 的支持情況如下:
Jetty 從 9.3 版本開始支持,需要依賴于 JDK 8 及以上版本
Netty 從 4.1 版本開始支持
OkHttp 天然支持
Vert.xh 從 3.3.0 版本開始支持
Firefly 支持
Golang 的 net/http 庫(kù)從 Go1.6 版本開始支持 http2,并默認(rèn)開啟
服務(wù)端名稱 | 支持的版本 | 支持的協(xié)商機(jī)制 | |
---|---|---|---|
Apache HTTP Server 2.4.17+ | h2,h2c | ALPN,Upgrade,direct | |
Apache Tomcat 8.5+ | h2,h2c | ALPN,Upgrade,direct | |
Nginx | h2,h2c | ALPN,NPN,direct | |
Tengine 2.1.2+ | h2 | ALPN | |
Twisted | h2 | NPN,ALPN | |
Netty | h2,h2c | ALPN,NPN,Upgrade,direct |
在 HTTP/2 的 github 中維護(hù)了一份 HTTP/2 協(xié)議的實(shí)現(xiàn)列表,更加詳細(xì),可供參考。
擴(kuò)展閱讀 1.NPN 和 ALPN由于現(xiàn)有的 URI 結(jié)構(gòu)正在被 HTTP 1.x 使用而不能被更換,所以 HTTP/2 也必須沿用該結(jié)構(gòu)。因此不得不找到一種方式將使用的協(xié)議升級(jí)至 HTTP/2,比如可以要求服務(wù)器讓它作響應(yīng)時(shí)使用 HTTP/2 來替代舊的協(xié)議。
HTTP 1.1 本身就制定過 “升級(jí)” 的方案:提供一個(gè)首部字段,表示允許服務(wù)器在收到舊協(xié)議請(qǐng)求的同時(shí),可以向客戶端發(fā)送新協(xié)議的響應(yīng)。但這一方案往往需要花費(fèi)一次額外的往返通信來作為升級(jí)的代價(jià)。
而這一代價(jià)是 SPDY 團(tuán)隊(duì)不想接受的。因?yàn)樗麄冎粚?shí)現(xiàn)了基于 TLS 的 SPDY,所以他們開發(fā)了一個(gè) TLS 的擴(kuò)展去簡(jiǎn)化協(xié)議的協(xié)商。這個(gè)擴(kuò)展被稱作 NPN(Next Protocol Negotiation),借助于此,服務(wù)器會(huì)通知客戶端所有它支持的協(xié)議,讓客戶端從中選擇一個(gè)合適的來進(jìn)行通訊。
IETF 將這個(gè)非正式標(biāo)準(zhǔn) --NPN 進(jìn)行規(guī)范化,從而演變成了 ALPN(Application Layer Protocol Negotiation)。ALPN 會(huì)隨著 HTTP/2 的應(yīng)用被推廣,而 SPDY 的客戶端與服務(wù)器則會(huì)繼續(xù)使用 NPN。
由于 NPN 先于 ALPN 誕生,而 ALPN 又經(jīng)歷了一些標(biāo)準(zhǔn)化過程,所以許多早期的 HTTP/2 客戶端和服務(wù)器在協(xié)商 HTTP/2 時(shí)會(huì)將這兩者同時(shí)實(shí)現(xiàn)。與此同時(shí),考慮到 SPDY 會(huì)使用 NPN,而許多服務(wù)器又會(huì)同時(shí)提供 SPDY 以及 HTTP/2,所以在這些服務(wù)器上同時(shí)支持 ALPN 以及 NPN 顯然會(huì)成為最理所當(dāng)然的選擇。
ALPN 和 NPN 的主要區(qū)別在于:誰來決定通信協(xié)議。在 ALPN 的描述中,是讓客戶端先發(fā)送一個(gè)協(xié)議優(yōu)先級(jí)列表給服務(wù)器,由服務(wù)器最終選擇一個(gè)合適的。而 NPN 則正好相反,客戶端有著最終的決定權(quán)。
ALPN 擴(kuò)展的具體資料,可以參考 Jerry Qu 寫的這篇博客:談?wù)?HTTP/2 的協(xié)議協(xié)商機(jī)制
2.QUICQUIC (Quick UDP Internet Connection,快速 UDP 互聯(lián)網(wǎng)連接) 是一個(gè)新的基于 UDP 的多路復(fù)用且安全的傳輸協(xié)議,它從頭開始設(shè)計(jì),且為 HTTP/2 語義做了優(yōu)化。盡管以 HTTP/2 作為主要的應(yīng)用協(xié)議而構(gòu)建,然而 QUIC 的構(gòu)建是基于傳輸和安全領(lǐng)域數(shù)十年的經(jīng)驗(yàn)的,且實(shí)現(xiàn)了使它成為有吸引力的現(xiàn)代通用傳輸協(xié)議的機(jī)制。QUIC 提供了等價(jià)于
HTTP/2 的多路復(fù)用和流控,等價(jià)于 TLS 的安全機(jī)制,及等價(jià)于 TCP 的連接語義、可靠性和擁塞控制。
QUIC 完全運(yùn)行于用戶空間,它當(dāng)前作為 Chromium 瀏覽器的一部分發(fā)布給用戶,以便于快速的部署和實(shí)驗(yàn)。作為基于 UDP 的用戶空間傳輸協(xié)議,QUIC 可以做一些由于遺留的客戶端和中間設(shè)備,或曠日持久的操作系統(tǒng)開發(fā)和部署周期的阻礙,而被證明很難在現(xiàn)有的協(xié)議中部署的創(chuàng)新。
QUIC 的一個(gè)重要目標(biāo)是通過快速的實(shí)驗(yàn)獲得更好的傳輸設(shè)計(jì)相關(guān)的知識(shí)。
基于早期的部署的 QUIC 標(biāo)準(zhǔn)化建議為 [draft-hamilton-quic-transport-protocol],[draft-shade-quic-http2-mapping],[draft-iyengar-quic-loss-recovery],和 [draft-thomson-quic-tls]。
更加詳細(xì)的資料請(qǐng)參考這里:中文文檔; Chromium 的 QUIC 主頁(yè)。
參考資料web 性能權(quán)威指南
HTTP/2 RFC 文檔
HTTP/2 explained
Nginx HTTP/2 白皮書
HTTP/2 is here, let"s optimize! - Velocity SC 2015
Jerry Qu 的小站 - HTTP/2 資料匯總
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/8049.html
摘要:綜述經(jīng)調(diào)研,使用解決方案的占多數(shù),已經(jīng)能滿足絕大多數(shù)公司需求。但除了一些超級(jí)公司外,比如阿里,京東,他們是自己擼的一套網(wǎng)關(guān)。 綜述 經(jīng)調(diào)研,使用Spring Cloud Zuul解決方案的占多數(shù),已經(jīng)能滿足絕大多數(shù)公司需求。但除了一些超級(jí)公司外,比如阿里,京東,他們是自己擼的一套網(wǎng)關(guān)。此外,點(diǎn)評(píng)直接采用的nginx負(fù)載均衡前置網(wǎng)關(guān),而沒用第七層網(wǎng)關(guān),原因據(jù)說是七層網(wǎng)關(guān)會(huì)影響性能,但由于...
摘要:一國(guó)外云計(jì)算技術(shù)的發(fā)展隨著世界各國(guó)對(duì)云計(jì)算的大力投入,以及行業(yè)內(nèi)技術(shù)的快速發(fā)展,現(xiàn)階段整個(gè)產(chǎn)業(yè)公司均在進(jìn)行云計(jì)算的產(chǎn)業(yè)整合。由第三方統(tǒng)計(jì)機(jī)構(gòu)提供的數(shù)據(jù)顯示,與云計(jì)算相關(guān)的業(yè)務(wù)收入已達(dá)億美元,成為增長(zhǎng)最快的業(yè)務(wù)之一。云計(jì)算(cloud computing)技術(shù)是上世紀(jì)八十年代大型計(jì)算機(jī)到客戶端-服務(wù)器的大轉(zhuǎn)變之后的又一種巨變。隨著通信技術(shù)、網(wǎng)絡(luò)技術(shù)的快速發(fā)展,云計(jì)算被視為科技發(fā)展的下一次革命,...
摘要:然而此次調(diào)研結(jié)果表明,企業(yè)采用時(shí)面臨的挑戰(zhàn)中,復(fù)雜性僅排在第五位,用戶面臨的基礎(chǔ)設(shè)施相關(guān)的挑戰(zhàn)更大。在監(jiān)控方面,中型組織更可能會(huì)面臨挑戰(zhàn)。 人們?cè)谑褂眉安渴餕ubernetes時(shí)會(huì)遇到各種各樣的問題。一些挑戰(zhàn)是使用Kubernetes時(shí)獨(dú)有的,其他一些挑戰(zhàn)則是伴隨著一些技術(shù)的使用出現(xiàn)的典型問題。 The New Stack發(fā)布的《Kubernetes的生態(tài)系統(tǒng)狀況》報(bào)告總結(jié)了用戶在挑...
摘要:一前言對(duì)于很多還沒進(jìn)入社會(huì)或者之前沒有在互聯(lián)網(wǎng)公司呆過的人來說,會(huì)很好奇互聯(lián)網(wǎng)企業(yè)的開發(fā)流程是怎樣的,正好借著我最近這段時(shí)間的經(jīng)歷寫下這一篇介紹開發(fā)流程的文章。整體的開發(fā)流程涉及到的人員角色有項(xiàng)目經(jīng)理產(chǎn)品設(shè)計(jì)后端開發(fā)前端開發(fā)運(yùn)維測(cè)試。 ...
閱讀 3043·2023-04-26 02:29
閱讀 655·2019-08-30 15:54
閱讀 1746·2019-08-29 13:13
閱讀 672·2019-08-28 17:51
閱讀 2795·2019-08-26 13:58
閱讀 1596·2019-08-26 13:27
閱讀 2886·2019-08-26 11:39
閱讀 3511·2019-08-26 10:46