Http前世今生
現(xiàn)在開發(fā)者離不開網(wǎng)絡(luò),所以都應(yīng)該了解http協(xié)議以及它在整個(gè)網(wǎng)絡(luò)中所起的作用。知道了這些,對(duì)開發(fā)更好的應(yīng)用起到很好的幫助作用。
下來,開始講述HTTP是什么,它的由來,現(xiàn)在的發(fā)展以及它是如何走到這一步的。
HTTP是什么?
HTTP(HyperText Transfer Protocol),名為超文本傳輸協(xié)議。之所以叫超文本,是源于當(dāng)時(shí)Tim Beners-Lee博士共享知識(shí)的設(shè)想,最初的理念是希望通過多文檔的互聯(lián)繼而形成超文本,連接可相互參閱的WWW(萬維網(wǎng))。
HTTP是基于TCP/IP的應(yīng)用層通信協(xié)議,它是客戶端和服務(wù)器之間相互通信的標(biāo)準(zhǔn)。它規(guī)定了如何在互聯(lián)網(wǎng)上請(qǐng)求和傳輸內(nèi)容。通過應(yīng)用層協(xié)議,我的意思是,它只是一個(gè)規(guī)范了主機(jī)(客戶端和服務(wù)器)如何通信的抽象層,并且它本身依賴于TCP/IP來獲取客戶端和服務(wù)器之間的請(qǐng)求和響應(yīng)。默認(rèn)的TCP端口是80端口,當(dāng)然,使用其他端口也是可以的。比如,HTTPS使用的端口是443端口。
HTTP出生
自從在 1989-1991 年間被 CERN(譯注:即“歐洲核子研究組織”的原稱 - Conseil Européen pour la Recherche Nucléaire)的 Tim Berners-Lee 發(fā)明出來以后,HTTP(超文本傳輸協(xié)議) 就一直是萬維網(wǎng)的基礎(chǔ)傳輸協(xié)議。在 C/S 計(jì)算模型中,HTTP 起到了一個(gè)“請(qǐng)求/響應(yīng)”協(xié)議的作用。HTTP 標(biāo)準(zhǔn)由 IETF(因特網(wǎng)工程任務(wù)組) 和 W3C(萬維網(wǎng)聯(lián)盟)負(fù)責(zé)開發(fā),并以一系列注釋請(qǐng)求(RFCs - Requests for Comments)的形式被發(fā)布。HTTP 有 4 個(gè)版本:HTTP/0.9、HTTP/1.0、HTTP/1.1 以及 HTTP/2.0。當(dāng)前通常使用 HTTP/1.1 版本, HTTP/2.0 ,未來是 HTTP/3.0(quic)。
HTTP/0.9 - 極簡版(1991)
第一版的HTTP文檔是1991年提出來的 HTTP/0.9。這是有史以來最簡單的協(xié)議;它僅有一個(gè)GET方法。如果客戶端要訪問服務(wù)器上的一些網(wǎng)頁,它會(huì)作出如下的簡單請(qǐng)求:
telnet xxx.com 80
(連接1建立 - TCP 三次握手) Connected to xxx.xxx.xxx.xxx(請(qǐng)求) GET /my-page.html 并且來自服務(wù)器的響應(yīng)內(nèi)容如下:(超文本響應(yīng))(response body) <HTML> A very simple HTML page </HTML>(connection closed)也就是說,服務(wù)器會(huì)得到這個(gè)請(qǐng)求,然后通過HTML格式回復(fù)響應(yīng)內(nèi)容,且一旦響應(yīng)內(nèi)容發(fā)送完畢,就會(huì)關(guān)閉這個(gè)連接。歸納一下:
- 沒有header數(shù)據(jù)塊(無法傳輸其他內(nèi)容類型的文件), 沒有 status/error 代碼, 沒有 URLs, 沒有版本控制
- GET方法是唯一允許的方法
- 必須以HTML格式響應(yīng),響應(yīng)類型: 僅 超文本
- 響應(yīng)后馬上結(jié)束的連接
正如你所見,這個(gè)協(xié)議只不過是未來版本的一個(gè)墊腳石罷了。
HTTP/1.0 - 1996
1996年,HTTP的下一個(gè)版本,即 HTTP/1.0 誕生了,它在原版本上做出了極大的改善。不像 HTTP/0.9 僅能以HTML格式響應(yīng),HTTP/1.1 現(xiàn)在可以處理其他的響應(yīng)格式了,例如:圖像,視頻文件,純文本或其他任何的內(nèi)容類型。它增加了更多的方法(即 POST 和 HEAD),請(qǐng)求/響應(yīng)的格式也發(fā)生了改變,請(qǐng)求和響應(yīng)中均加入了HTTP頭信息,響應(yīng)數(shù)據(jù)還增加了狀態(tài)碼標(biāo)識(shí),還介紹了字符集的支持、多部分發(fā)送、權(quán)限、緩存、內(nèi)容編碼等很多內(nèi)容。
構(gòu)建可擴(kuò)展性
- 對(duì)瀏覽器友好的協(xié)議
- 提供了對(duì)請(qǐng)求和響應(yīng)都包含豐富元數(shù)據(jù)的 header 域 (HTTP 版本號(hào)、status code 和 content type)
- 響應(yīng):不再只限于超文本 (Content-Type 頭部提供了傳輸 HTML 之外文件的能力 — 如腳本、樣式或媒體文件)
- 支持的方法: GET , HEAD , POST
- 響應(yīng)后馬上結(jié)束的連接
- session/cookie,解決無連接,無狀態(tài)的請(qǐng)求。
如下所示,這是一個(gè)通過 HTTP/1.0 請(qǐng)求和響應(yīng)的例子:
GET / HTTP/1.0 Host: kamranahmed.info User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) Accept: */*正如你所見,客戶端除了發(fā)送請(qǐng)求以外,它還發(fā)送了它的個(gè)人信息,要求響應(yīng)類型等。而在 HTTP/0.9 中因?yàn)闆]有頭信息,客戶端是不會(huì)發(fā)送這些信息的。
上面的例子對(duì)應(yīng)的服務(wù)器響應(yīng)結(jié)果如下:
HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 137582 Expires: Thu, 05 Dec 1997 16:00:00 GMT Last-Modified: Wed, 5 August 1996 15:55:28 GMT Server: Apache 0.84(response body) (connection closed)最開始的響應(yīng)內(nèi)容是 HTTP/1.0(HTTP后面的是版本號(hào)),然后是狀態(tài)碼200,再往后是原因短語(或狀態(tài)碼的描述)。
在這個(gè)新版本中,請(qǐng)求和響應(yīng)的頭信息仍然采用 ASCII 編碼方式,但具體的響應(yīng)內(nèi)容可以是任何類型的,例如:圖像、視頻、HTML、純文本或任何其他的內(nèi)容類型。因此,現(xiàn)在的服務(wù)器端可以向客戶端發(fā)送任何內(nèi)容類型的數(shù)據(jù);不久之后,HTTP介紹中的“超文本”術(shù)語就變得名不副實(shí)了。也許用HMTP或超媒體傳輸協(xié)議可能會(huì)更有意義一些,但是,我想,我們還是會(huì)一直用HTTP這個(gè)名字的。
HTTP/1.0的主要缺點(diǎn)之一是,你不能在每個(gè)連接中發(fā)送多個(gè)請(qǐng)求。也就是說,每當(dāng)客戶端要向服務(wù)器端請(qǐng)求東西時(shí),它都會(huì)打開一個(gè)新的TCP連接,并且在這個(gè)單獨(dú)請(qǐng)求完成后,該連接就會(huì)被關(guān)閉。且對(duì)于下個(gè)需求時(shí),它必須再創(chuàng)建一個(gè)新的連接。為什么會(huì)如此糟糕呢?好吧,來讓我們做個(gè)假設(shè),假設(shè)你需要訪問一個(gè)包含10張圖片、5個(gè)樣式表和5個(gè)JS文件的網(wǎng)頁,這是一個(gè)共20項(xiàng)內(nèi)容要請(qǐng)求的網(wǎng)頁。由于服務(wù)器會(huì)在每個(gè)請(qǐng)求完成后將連接關(guān)閉,所以,這將會(huì)有一系列的20個(gè)獨(dú)立的連接,每個(gè)項(xiàng)目均有一個(gè)單獨(dú)的連接。因?yàn)槿挝帐趾推浜蟮木徛龁?dòng)機(jī)制,若每次請(qǐng)求都創(chuàng)建一個(gè)新的TCP連接,這就會(huì)帶來明顯的性能損失,最終的結(jié)果就是,這些大量的連接會(huì)導(dǎo)致嚴(yán)重的性能下降。
三次握手協(xié)議
HTTP/0.9 和 HTTP/1.0都需要為每次請(qǐng)求建立一個(gè)新的連接(并在收到對(duì)應(yīng)的響應(yīng)后立即關(guān)閉該連接)。每次新連接建立時(shí),都要經(jīng)歷一遍 TCP 三次握手,并在開始共享應(yīng)用數(shù)據(jù)之前會(huì)先共享一系列的數(shù)據(jù)包。
- SYN - 客戶端創(chuàng)建一個(gè)隨機(jī)數(shù)(稱為x),并且將x發(fā)送給服務(wù)器。
- SYN ACK - 服務(wù)器確認(rèn)請(qǐng)求后,當(dāng)確認(rèn)x是從客戶端發(fā)來時(shí)會(huì)發(fā)送一個(gè)ACK數(shù)據(jù)包(稱為y,y=x+1)返回給客戶端。
- ACK - 客戶端收到從服務(wù)器發(fā)來的增量y后,向服務(wù)器發(fā)送ACK(x+1)確認(rèn)包。
當(dāng)三次握手完成后,客戶端和服務(wù)器之間的數(shù)據(jù)共享就可以開始了。需要注意的是,客戶端可能會(huì)在處理完最后一個(gè)ACK數(shù)據(jù)包之后,就開始發(fā)送應(yīng)用數(shù)據(jù)了。但服務(wù)器為了完成請(qǐng)求,仍然需要等待ACK數(shù)據(jù)包收到才行。
問題
然而,一些 HTTP/1.0 的實(shí)現(xiàn)試圖通過引入一個(gè)新的頭信息 Connection: keep-alive 來解決這個(gè)問題,這是為了告訴服務(wù)器:“嘿,服務(wù)器,請(qǐng)不要關(guān)閉這個(gè)連接,我還要用它呢”。但這并沒有得到廣泛的支持,所以問題仍然存在。
除了是無連接的, HTTP 也是一個(gè)無狀態(tài)的協(xié)議,例如:服務(wù)器不會(huì)維護(hù)客戶端的信息,因此,在它自己與任何舊的請(qǐng)求沒有任何關(guān)聯(lián)的情況下,服務(wù)器為了能完成請(qǐng)求,就需要每一個(gè)請(qǐng)求都必須帶有服務(wù)器所需要的信息才行。所以,這簡直就是“火上澆油”啊:客戶端除了要打開大量的連接,它還必須要發(fā)送一些冗余的數(shù)據(jù),這就導(dǎo)致了需要使用更多的帶寬。
HTTP/1.0+
在發(fā)布 HTTP/1.0 之后,網(wǎng)絡(luò)飛速發(fā)展,很多流程web客戶端和服務(wù)器都在飛快地向HTTP中添加各種特性,以滿足快速擴(kuò)張且在商業(yè)上十分成功的萬維網(wǎng)的需要。其中很多特性,包括keep-alive連接、虛擬機(jī)支持,以及代理連接支持都被加入到HTTP之中,并成為非官方的事實(shí)標(biāo)準(zhǔn)。這種非正式的HTTP擴(kuò)展版本稱為 HTTP/1.0+。
HTTP/1.1 - 1999
HTTP/1.0僅發(fā)布了3年之后,它的下一個(gè)版本,即HTTP/1.1便在1999年問世了,它在之前的基礎(chǔ)上做了很多的改進(jìn)。基于HTTP/1.0的主要改進(jìn)內(nèi)容包含:
- 這是當(dāng)前普遍使用的 HTTP 版本
- 進(jìn)行了重大的性能優(yōu)化和特性增強(qiáng),分塊傳輸、壓縮/解壓、內(nèi)容緩存磋商、虛擬主機(jī)(有單個(gè) IP 地址的主機(jī)具有多個(gè)域名)、更快的響應(yīng),以及通過增加緩存節(jié)省了更多的帶寬
- 新增的HTTP方法 PUT、PATCH、HEAD、OPTIONS、DELETE
- 主機(jī)名標(biāo)識(shí) 在 HTTP/1.0 中,Host頭信息不是必須項(xiàng),但 HTTP/1.1 中要求必須要有Host頭信息。
- 持久性連接 正如前面所說,在 HTTP/1.0 中每個(gè)連接只有一個(gè)請(qǐng)求 ,且在這個(gè)請(qǐng)求完成后該連接就會(huì)被關(guān)閉,從而會(huì)導(dǎo)致嚴(yán)重的性能下降及延遲問題。HTTP/1.1 引入了對(duì)持久性連接的支持,例如: 默認(rèn)情況下連接不會(huì)被關(guān)閉,在多個(gè)連續(xù)的請(qǐng)求下它會(huì)保存連接的打開狀態(tài)。想要關(guān)閉這些連接,需要將 Connection: close 加入到請(qǐng)求的頭信息中。客戶端通常會(huì)在最后一次請(qǐng)求中發(fā)送這個(gè)頭信息用來安全的關(guān)閉連接。
- 管道機(jī)制 HTTP/1.1也引入了對(duì)管道機(jī)制的支持,客戶端可以向服務(wù)器發(fā)送多個(gè)請(qǐng)求,而無需等待來自同一連接上的服務(wù)器響應(yīng),并且當(dāng)收到請(qǐng)求時(shí)服務(wù)器必須以相同的順序來響應(yīng)。但你可能會(huì)問:客戶端是怎么知道第一個(gè)響應(yīng)下載完成和下一個(gè)響應(yīng)內(nèi)容開始的?要解決這個(gè)問題,必須要有Content-Length頭信息,客戶端可以用它來確定響應(yīng)結(jié)束,然后開始等待下一個(gè)響應(yīng)。
http請(qǐng)求過程
(連接1建立 - TCP 三次握手) Connected to xxx.xxx.xxx.xxx(請(qǐng)求1) GET /en-US/docs/Glossary/Simple_header HTTP/1.1 Host: developer.mozilla.org User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header(響應(yīng)1) HTTP/1.1 200 OK Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Date: Wed, 20 Jul 2016 10:55:30 GMT Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a" Keep-Alive: timeout=5, max=1000 Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT Server: Apache Transfer-Encoding: chunked Vary: Cookie, Accept-Encoding[content](請(qǐng)求2) GET /static/img/header-background.png HTTP/1.1 Host: developer.cdn.mozilla.net User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header(響應(yīng)2) HTTP/1.1 200 OK Age: 9578461 Cache-Control: public, max-age=315360000 Connection: keep-alive Content-Length: 3077 Content-Type: image/png Date: Thu, 31 Mar 2016 13:34:46 GMT Last-Modified: Wed, 21 Oct 2015 18:27:50 GMT Server: Apache[image content of 3077 bytes](連接1關(guān)閉 - 斷掉 TCP)性能優(yōu)化和特性增強(qiáng)
應(yīng)該注意的是,為了從持久性連接或管道機(jī)制中獲益,Content-Length頭信息必須在可用的響應(yīng)中,因?yàn)檫@會(huì)讓客戶端知道當(dāng)傳輸完成后,它可以發(fā)送下一個(gè)請(qǐng)求(用正常順序發(fā)送請(qǐng)求的方式)或者開始等待下一個(gè)響應(yīng)(當(dāng)啟用了管道機(jī)制時(shí))。
但這種方法仍然存在一個(gè)問題:如果數(shù)據(jù)是動(dòng)態(tài)的,且服務(wù)器找不到之前的內(nèi)容長度時(shí)怎么辦?那么,在這種情況下,你就真的不能從持久性連接中收益了,不是嗎?!為了解決這個(gè)問題,在 HTTP/1.1 中引入了分塊編碼的支持。在這種情況下,服務(wù)器可能會(huì)忽略 Content-Length 并支持分塊編碼。然而,如果他們沒有可用的數(shù)據(jù),那么連接必須在請(qǐng)求結(jié)束時(shí)關(guān)閉。
- 分塊傳輸 在動(dòng)態(tài)內(nèi)容的情況下,當(dāng)傳輸開始時(shí)服務(wù)器無法找到 Content-Length 頭信息的話,它也可以開始以塊的方式發(fā)送內(nèi)容(一塊一塊的發(fā)),并且當(dāng)每個(gè)小塊發(fā)送后,它會(huì)給每個(gè)塊添加一個(gè) Content-Length 頭信息。當(dāng)所有的塊發(fā)送完成后(即整個(gè)傳輸已經(jīng)完成),它會(huì)發(fā)送一個(gè)空的塊(即 Content-Length 為零的塊)以確定客戶端的傳輸已經(jīng)完成。為了通知客戶端采用分塊傳輸?shù)姆绞?#xff0c;服務(wù)器需要在頭信息中包含Transfer-Encoding: chunked
- 不像HTTP/1.0 只有基本的身份驗(yàn)證,HTTP/1.1 還包含摘要和代理驗(yàn)證
- 高速緩存
- 字節(jié)范圍
- 字符集
- 談判語言
- 客戶端cookie
- 加強(qiáng)對(duì)壓縮的支持
- 新的狀態(tài)代碼
- 以及更多。。。
1.0 vs 1.1
TCP 三次握手會(huì)在任何連接被建立之前發(fā)生一次。最終,當(dāng)發(fā)送了所有數(shù)據(jù)之后,服務(wù)器發(fā)送一個(gè)消息,表示不會(huì)再有更多數(shù)據(jù)向客戶端發(fā)送了;則客戶端才會(huì)關(guān)閉連接(斷開 TCP)。HTTP/1.0 存在的問題是,對(duì)于每個(gè) 請(qǐng)求/響應(yīng) 輪回,也要建立并關(guān)閉一個(gè)連接。而改用 HTTP/1.1 后的優(yōu)點(diǎn)則在于,可以復(fù)用同一個(gè)連接,來完成多次 請(qǐng)求/響應(yīng) 輪回。
pipeline
特點(diǎn)
- 管線化機(jī)制通過持久連接(persistent connection)完成,僅 HTTP/1.1 支持此技術(shù)(HTTP/1.0不支持)
- 只有 GET 和 HEAD 請(qǐng)求可以進(jìn)行管線化,而 POST 則有所限制
- 初次創(chuàng)建連接時(shí)不應(yīng)啟動(dòng)管線機(jī)制,因?yàn)閷?duì)方(服務(wù)器)不一定支持 HTTP/1.1 版本的協(xié)議
- 管線化不會(huì)影響響應(yīng)到來的順序,如上面的例子所示,響應(yīng)返回的順序并未改變
- HTTP /1.1 要求服務(wù)器端支持管線化,但并不要求服務(wù)器端也對(duì)響應(yīng)進(jìn)行管線化處理,只是要求對(duì)于管線化的請(qǐng)求不失敗即可
- 由于上面提到的服務(wù)器端問題,開啟管線化很可能并不會(huì)帶來大幅度的性能提升,而且很多服務(wù)器端和代理程序?qū)芫€化的支持并不好,因此現(xiàn)代瀏覽器如 Chrome 和 Firefox 默認(rèn)并未開啟管線化支持
- pipeline中有一個(gè)請(qǐng)求被卡住后面的請(qǐng)求都會(huì)被阻塞的隊(duì)頭阻塞問題
HTTP Pipelining是這樣一種技術(shù):在等待上一個(gè)請(qǐng)求響應(yīng)的同時(shí),發(fā)送下一個(gè)請(qǐng)求。(譯者注:作者這個(gè)解釋并不完全正確,HTTP Pipelining其實(shí)是把多個(gè)HTTP請(qǐng)求放到一個(gè)TCP連接中一一發(fā)送,而在發(fā)送過程中不需要等待服務(wù)器對(duì)前一個(gè)請(qǐng)求的響應(yīng);只不過,客戶端還是要按照發(fā)送請(qǐng)求的順序來接收響應(yīng)。)但就像在超市收銀臺(tái)或者銀行柜臺(tái)排隊(duì)時(shí)一樣,你并不知道前面的顧客是干脆利索的還是會(huì)跟收銀員/柜員磨蹭到世界末日(譯者注:不管怎么說,服務(wù)器(即收銀員/柜員)是要按照順序處理請(qǐng)求的,如果前一個(gè)請(qǐng)求非常耗時(shí)(顧客磨蹭),那么后續(xù)請(qǐng)求都會(huì)受到影響),這就是所謂的線頭阻塞(Head of line blocking)。
即使在2019年的今天,大部分桌面瀏覽器也默認(rèn)關(guān)閉了HTTP pipelining功能。
不足與缺陷
HTTP/1.1是在1999年發(fā)布的,成為標(biāo)準(zhǔn)有很多年了。 雖然它對(duì)上一版協(xié)議進(jìn)行了很多改進(jìn),但web世界每天都在改變,它開始顯現(xiàn)出了它的不足。現(xiàn)在訪問的網(wǎng)頁與以前相比包含的資源更多。一個(gè)簡單的網(wǎng)頁都會(huì)至少打開30個(gè)連接。 我們知道 HTTP/1.1 是持久連接,那為什么還需要這么多連接?你會(huì)說這是由于HTTP/1.1在任何時(shí)刻都只有一個(gè)有效連接。 HTTP/1.1嘗試通過pipeline來解決這個(gè)問題,但是它并沒有完全的解決,因?yàn)樵趐ipeline中有一個(gè)請(qǐng)求被卡住后面的請(qǐng)求都會(huì)被阻塞的隊(duì)頭阻塞問題。它將不得不等待下一個(gè)請(qǐng)求。 為了克服HTTP/1.1的這些缺點(diǎn), 開發(fā)人員開始嘗試一些解決方案,如:在CSS中使用雪碧圖、圖像編碼 ,合并CSS或Javascript文件, 域分片(將多個(gè)資源分別放入不同的子域名下)等等。
SPDY - 2009
Google走在前面,它開始試驗(yàn)一種可替換的協(xié)議來減少網(wǎng)頁的延遲,使得網(wǎng)頁加載更快、提升web安全性 。 2009年, 他們稱這種協(xié)議為SPDY。
SPDY是谷歌的一個(gè)商標(biāo),不是一個(gè)縮寫詞。
它們意識(shí)到如果繼續(xù)增加帶寬來提升網(wǎng)絡(luò)性能的過程中,必然在到達(dá)某一個(gè)點(diǎn)后不會(huì)再帶來更多提升。在有延遲的情況下如果我們不斷減少延遲,那么性能將會(huì)是一個(gè)常數(shù)。這是 SPDY性能提升背后的核心理概念,減少延遲來提升網(wǎng)絡(luò)性能。
對(duì)于那些不知道這兩個(gè)概念的人, 延遲即數(shù)據(jù)從源傳輸?shù)侥繕?biāo)的耗時(shí)(以毫秒為單位),帶寬就是每秒傳輸?shù)臄?shù)據(jù)量(比特/秒).
SPDY的功能包含: 多路復(fù)用, 壓縮, 優(yōu)先級(jí), 安全等。我不打算進(jìn)入SPDY的細(xì)節(jié),在進(jìn)入下一節(jié)HTTP / 2后就會(huì)明白,HTTP / 2主要受SPDY的啟發(fā)。
SPDY 沒有真正試圖替換HTTP,它任然是存在于應(yīng)用層的基于HTTP的傳輸層,它在請(qǐng)求發(fā)送前進(jìn)行一些修改。 它開始成為一個(gè)事實(shí)上的標(biāo)準(zhǔn),大多數(shù)的瀏覽器開始實(shí)現(xiàn)它。
2015年,谷歌不想存在兩個(gè)相互競爭的標(biāo)準(zhǔn),因此他們決定把它合并到HTTP中成為HTTP/2,同時(shí)放棄SPDY。
HTTP/2 - 2015
現(xiàn)在,你已經(jīng)知道我們?yōu)槭裁葱枰粋€(gè)HTTP協(xié)議的修訂版了。 HTTP/2 是專為低延遲傳輸?shù)膬?nèi)容而設(shè)計(jì)。 關(guān)鍵特征或與 HTTP / 1.1 舊版本的差異,如下:
- 二進(jìn)制,而不是文本
- 多路復(fù)用- 在單個(gè)連接中多個(gè)異步HTTP請(qǐng)求
- 使用HPACK報(bào)頭壓縮
- 服務(wù)器推送 - 單請(qǐng)求多個(gè)響應(yīng)
- 請(qǐng)求優(yōu)先級(jí)
- 安全
特點(diǎn)
二進(jìn)制協(xié)議
HTTP/2 傾向于使用二進(jìn)制協(xié)議來減少HTTP/1.x中的延遲。二進(jìn)制協(xié)議更容易解析,而不具有像HTTP/1.x 中那樣對(duì)人的可讀性。HTTP/2中的數(shù)據(jù)塊是: 幀和流。
幀和流
HTTP 消息是由一個(gè)或多個(gè)幀組成的。有一個(gè)叫做 HEADERS 的幀存放元數(shù)據(jù),真正的數(shù)據(jù)是放在 DATA 幀中的,幀類型定義在the HTTP/2 specs(HTTP/2規(guī)范),如(HEADERS, DATA, RST_STREAM, SETTINGS, PRIORITY 等)。
每個(gè)HTTP / 2請(qǐng)求和響應(yīng)都被賦予一個(gè)唯一的流ID且放入了幀中。幀就是一塊二進(jìn)制數(shù)據(jù)。 一系列幀的集合就稱為流。 每個(gè)幀都有一個(gè)流id,用于標(biāo)識(shí)它屬于哪一個(gè)流,每一個(gè)幀都有相同的頭。同時(shí),除了流標(biāo)識(shí)是唯一的,值得一提的是,客戶端發(fā)起的任何請(qǐng)求都使用奇數(shù)和服務(wù)器的響應(yīng)是偶數(shù)的流id。
除了 HEADERS和 DATA, 另外一個(gè)值得說一說幀類型是RST_STREAM,它是一個(gè)特殊的幀類型用于中止流,如:客戶端發(fā)送這幀來告訴服務(wù)器我不再需要這個(gè)流了。在 HTTP/1.1 中只有一種方式來實(shí)現(xiàn)服務(wù)器停止發(fā)送響應(yīng)給客戶端,那就是關(guān)閉連接引起延遲增加,因?yàn)楹罄m(xù)的請(qǐng)求就需要打開一個(gè)新的連接。 在HTTP/2中,客戶端可以使用RST_FRAME來停止接收指定的流而不關(guān)閉連接且還可以在此連接中接收其它流。
多路復(fù)用
由于HTTP / 2現(xiàn)在是一個(gè)二進(jìn)制協(xié)議,且是使用幀和流來實(shí)現(xiàn)請(qǐng)求和響應(yīng),一旦TCP 連接打開了, 所有的流都通過這一連接來進(jìn)行異步的發(fā)送而不需要打開額外的連接。反過來,服務(wù)器的響應(yīng)也是異步的方式,如:響應(yīng)是無序的、客戶端使用流id來標(biāo)識(shí)屬于流的包。 這就解決了存在于HTTP/1.x 中head-of-line 阻塞問題,如: 客戶端將不必耗時(shí)等待請(qǐng)求,而其他請(qǐng)求將被處理。
HPACK 頭部壓縮
它是一個(gè)單獨(dú)的用于明確優(yōu)化發(fā)送header RFC的一部分。它的本質(zhì)是,當(dāng)我們同一個(gè)客戶端不斷的訪問服務(wù)器時(shí),在header中發(fā)送很多冗余的數(shù)據(jù),有時(shí)cookie 就增大header,且消耗帶寬和增加了延遲。為了解決這個(gè)問題, HTTP/2 引入了頭部壓縮。
與請(qǐng)求和響應(yīng)不同,header不是使用的 gzip 或 compress等壓縮格式,它有不同的機(jī)制,它使用了霍夫曼編碼和在客戶端和服務(wù)器維護(hù)的頭部表來消除重復(fù)的 headers (如:user agent),在后續(xù)的請(qǐng)求中就只使用頭部表中引用。
既然談到了header,那就再多說一點(diǎn),它與HTTP/1.1中的一樣,不過增加了偽header,如: :method, :scheme,:host 和:path
服務(wù)器推送
在服務(wù)器段,Server push是HTTTP/2的另外一個(gè)重要功能,我們知道,客戶端是通過請(qǐng)求來獲取資源的,它可以通過推送資源給客戶端而不需客戶端主動(dòng)請(qǐng)求。 例如,瀏覽器載入了一個(gè)頁面,瀏覽器解析頁面時(shí)發(fā)現(xiàn)了需要從服務(wù)器端載入的內(nèi)容,接著它就發(fā)送一個(gè)請(qǐng)求來獲取這些內(nèi)容。
Server push允許服務(wù)器推送數(shù)據(jù)來減少客戶端請(qǐng)求。 它是如何實(shí)現(xiàn)的呢,服務(wù)器在一個(gè)新的流中發(fā)送一個(gè)特殊的幀 PUSH_PROMISE,來通知客戶端:“嘿,我要把這個(gè)資源發(fā)給你!你就不要請(qǐng)求了。”
請(qǐng)求優(yōu)先級(jí)
客戶端可以在一個(gè)打開的流中在流的HEADERS 幀中放入優(yōu)先級(jí)信息。 在任何時(shí)間,客戶端都可以發(fā)送一個(gè)PRIORITY 的幀來改變流的優(yōu)先級(jí)。
如果沒有優(yōu)先級(jí)信息,服務(wù)器就會(huì)異步的處理請(qǐng)求,比如:無序處理。如果流被賦予了優(yōu)先級(jí),它就會(huì)基于這個(gè)優(yōu)先級(jí)來處理,由服務(wù)器決定需要多少資源來處理該請(qǐng)求。
安全
大家對(duì)HTTP/2是否強(qiáng)制使用安全連接(通過TLS)進(jìn)行了充分的討論。最后的決定是不強(qiáng)制使用。 然而,大多數(shù)廠商表示,他們將只支持基于TLS的 HTTP / 2 。 所以,盡管HTTP / 2規(guī)范不需要加密,但它已經(jīng)成為默認(rèn)的強(qiáng)制執(zhí)行的。 在這種情況下,基于TLS實(shí)現(xiàn)的 HTTP/2需要的TLS版本最低要求是1.2。 因此必須有最低限度的密鑰長度,臨時(shí)密鑰等。
HTTP/2超越了SPDY的變動(dòng)也對(duì)它進(jìn)行了增強(qiáng)。HTTP/2有很多性能提升,我們是時(shí)候開始使用它。
參考資料
HTTP2 即未來
HTTP2.0原理詳細(xì)解析
QUIC - 2013
基于SPDY原理,使用UDP快速網(wǎng)絡(luò)連接。
QUIC是快速UDP網(wǎng)絡(luò)連線(英語:Quick UDP Internet Connections)的縮寫,這是一種實(shí)驗(yàn)性的傳輸層網(wǎng)絡(luò)傳輸協(xié)議,由Google公司開發(fā),在2013年實(shí)現(xiàn)。QUIC使用UDP協(xié)議,它在兩個(gè)端點(diǎn)間創(chuàng)建連線,且支持多路復(fù)用連線。在設(shè)計(jì)之初,QUIC希望能夠提供等同于SSL/TLS層級(jí)的網(wǎng)絡(luò)安全保護(hù),減少數(shù)據(jù)傳輸及創(chuàng)建連線時(shí)的延遲時(shí)間,雙向控制帶寬,以避免網(wǎng)絡(luò)擁塞。Google希望使用這個(gè)協(xié)議來取代TCP協(xié)議,使網(wǎng)頁傳輸速度加快,計(jì)劃將QUIC提交至互聯(lián)網(wǎng)工程任務(wù)小組(IETF),讓它成為下一代的正式網(wǎng)絡(luò)規(guī)范。
- QUIC(Quick UDP Internet Connections),直譯過來就是“快速的 UDP 互聯(lián)網(wǎng)連接”,是 Google 基于 UDP 提出的一種改進(jìn)的通信協(xié)議,作為傳統(tǒng) HTTP over TCP 的替代品,開源于 Chromium 項(xiàng)目中。
- 為了加快 TCP 的傳輸效率,Google 提出了 BBR 擁塞控制算法,將 TCP 的性能發(fā)揮到了極致。由于 TCP 和 UDP 協(xié)議是系統(tǒng)內(nèi)核實(shí)現(xiàn)的,要提出新的協(xié)議不是不行,只是普及起來會(huì)非常困難,就連 BBR 算法,都需要更新系統(tǒng)內(nèi)核才能支持。那么,TCP 的性能已經(jīng)到了極致,還能更快嗎?
- UDP 相比于 TCP,沒有那么多的要求,只要將數(shù)據(jù)發(fā)出去就行了,不需要考慮數(shù)據(jù)是否送達(dá)了、不需要考慮數(shù)據(jù)的到達(dá)順序、不需要考慮數(shù)據(jù)的正確性和完整性,所以效率比 TCP 要高出幾個(gè)檔次。
- UDP 協(xié)議曾經(jīng)被普遍用于視頻直播、網(wǎng)絡(luò)游戲之類實(shí)時(shí)性要求較高的應(yīng)用,即使少數(shù)幾個(gè)包沒有送達(dá)對(duì)應(yīng)用整體的影響也不大。可是,對(duì)于 HTTP 之類的協(xié)議,是需要保證數(shù)據(jù)的正確性、完整性的,所以 UDP 本身并不適合作為 TCP 的替代品。
- UDP 不適合替代 TCP 是因?yàn)樗旧聿粚?duì)數(shù)據(jù)進(jìn)行校驗(yàn),那么如果將數(shù)據(jù)校驗(yàn)放到其他地方去實(shí)現(xiàn),是不是就可以使用 UDP 了呢?
- 于是,QUIC 就誕生了,它匯集了 TCP 和 UDP 的優(yōu)點(diǎn),使用 UDP 來傳輸數(shù)據(jù)以加快網(wǎng)絡(luò)速度,降低延遲,由 QUIC 來保證數(shù)據(jù)的順序、完整性和正確性,即使發(fā)生了丟包,也由 QUIC 來負(fù)責(zé)數(shù)據(jù)的 糾錯(cuò)。
QUIC 的優(yōu)點(diǎn)
QUIC 的缺點(diǎn)
現(xiàn)在很多網(wǎng)絡(luò)運(yùn)營商會(huì)降低 UDP 包的優(yōu)先級(jí),使得 UDP 丟包率特別高。(QUIC 不可用時(shí),瀏覽器一般會(huì) Fallback 到 TCP)
目前只有 Chrome、Opera 瀏覽器支持
什么時(shí)候更適合使用 QUIC?
移動(dòng)端
由于 QUIC 并不使用 IP + 端口來標(biāo)識(shí)客戶身份,而是使用 ID,這使得在網(wǎng)絡(luò)環(huán)境切換后還可以保持連接,非常適合用在移動(dòng)網(wǎng)站上面,在手機(jī)信號(hào)不穩(wěn)定的情況下,TCP + TLS 的開銷是非常大的!QUIC 的 0-RTT 可以極大限度地提升訪問速度。
總結(jié)
QUIC 實(shí)現(xiàn)的目標(biāo),就是利用 UDP 實(shí)現(xiàn)一個(gè) TCP,支持 TCP 的所有特性,并且比 TCP 更快更好用。
QUIC 是從 2012 年開始的項(xiàng)目,到目前也還只是草案階段,并且同樣處于草案階段的 TLS1.3 也同樣擁有了 QUIC 中的很多優(yōu)點(diǎn)(比如 0-RTT)。對(duì)于訪問速度的優(yōu)化方式越來越多,適當(dāng)?shù)倪x擇可以為網(wǎng)站增色許多。
quic落地
QUIC在微博中的落地
騰訊云落地
手機(jī)端落地
展望
http 協(xié)議發(fā)展迅速,和我們現(xiàn)在的技術(shù)生活息息相關(guān)。5G 的出現(xiàn)也促進(jìn)了 http 協(xié)議的發(fā)展。
我們的生活會(huì)因?yàn)榧夹g(shù)的進(jìn)步,越來越好!
如果你喜歡我的文章,可以關(guān)注我的掘金、公眾號(hào)、博客、簡書或者Github!
簡書: https://www.jianshu.com/u/a2591ab8eed2
GitHub: https://github.com/bugyun
Blog: https://ruoyun.vip
掘金: https://juejin.im/user/56cbef3b816dfa0059e330a8/posts
CSDN: https://blog.csdn.net/zxloveooo
歡迎關(guān)注微信公眾號(hào)
總結(jié)
- 上一篇: 华为机试(JAVA)真题Od【A卷+B卷
- 下一篇: 春考计算机组装维修知识点,山东春考计算机