大家好,我是Tom哥~
今天跟大家聊聊下 HTTP協(xié)議,歡迎留言討論
互聯(lián)網(wǎng)時(shí)代,足不出戶(hù),點(diǎn)點(diǎn)鼠標(biāo)就可以輕松了解外面的世界變化,這一切得益于網(wǎng)絡(luò)傳輸數(shù)據(jù)。
我們都知道網(wǎng)絡(luò)有7層模型,從底層到上層依次是:物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會(huì)話層、表示層、應(yīng)用層。
越往上,越接近用戶(hù)習(xí)慣,更容易被用戶(hù)直觀了解。
今天講的 HTTP 協(xié)議屬于應(yīng)用層協(xié)議,也是互聯(lián)網(wǎng)廣泛使用的基礎(chǔ)協(xié)議之一。
一、 HTTP/0.9
0.9 版本是HTTP最早的版本,誕生于 1991 年,比較簡(jiǎn)單。
1、只支持 GET 請(qǐng)求,沒(méi)有請(qǐng)求頭。每次請(qǐng)求都要單獨(dú)創(chuàng)建一個(gè)TCP連接,復(fù)用性差,性能不高
2、服務(wù)端響應(yīng)的數(shù)據(jù)只能是 HTML格式,服務(wù)器發(fā)送完畢,會(huì)關(guān)閉TCP連接。如果請(qǐng)求的頁(yè)面不存在,也不會(huì)返回任何錯(cuò)誤碼。
當(dāng)時(shí),互聯(lián)網(wǎng)剛起步,頁(yè)面展現(xiàn)形式更多是文本為主,能滿(mǎn)足基本需求。隨著用戶(hù)需求的多樣化,對(duì)展示形態(tài)和性能也提出了更高要求,HTTP協(xié)議也開(kāi)始了慢慢的升級(jí)之路。
二、 HTTP/1.0
1996年,HTTP/1.0 發(fā)布,相比之前版本增加了很多特性。
1、請(qǐng)求和響應(yīng)增加了頭信息(header),用來(lái)描述一些元數(shù)據(jù),如:
- Content-Type 讓響應(yīng)數(shù)據(jù)不只限于超文本
- Expires、Last-Modified 緩存
- Authorization 身份認(rèn)證
- Connection: keep-alive 支持長(zhǎng)連接,但非標(biāo)準(zhǔn)
2、請(qǐng)求方法,除了 GET,還增加了 POST、HEAD命令,豐富了互動(dòng)方式
3、豐富了傳輸內(nèi)容的格式,有文本、圖像、視頻、二進(jìn)制文件
4、請(qǐng)求時(shí)增加 HTTP 協(xié)議版本,響應(yīng)端增加狀態(tài)碼。
缺點(diǎn):
主要還是連接復(fù)用問(wèn)題,每個(gè)TCP連接只能發(fā)送一個(gè)請(qǐng)求。當(dāng)數(shù)據(jù)發(fā)送完畢后,連接就會(huì)關(guān)閉。由于TCP建立連接,需要三次握手,所以性能會(huì)比較差。
為了緩解這個(gè)問(wèn)題,請(qǐng)求頭引入一個(gè)非標(biāo)準(zhǔn)的Connection字段:Connection: keep-alive,要求服務(wù)器不要關(guān)閉TCP連接,從而達(dá)到復(fù)用效果。
當(dāng)然,這個(gè)不是標(biāo)準(zhǔn)字段,只是一個(gè)臨時(shí)方案。
三、 HTTP/1.1
1997年,HTTP/1.1 版本發(fā)布。進(jìn)一步完善了HTTP協(xié)議,也是目前最流行的版本,一直活躍至今。
1、默認(rèn)支持長(zhǎng)連接(PersistentConnection)和請(qǐng)求的流水線(Pipelining)處理,在一個(gè)TCP連接上可以傳送多個(gè)HTTP請(qǐng)求和響應(yīng),減少了建立和關(guān)閉連接的消耗和延遲
2、管線化技術(shù)。支持多個(gè) HTTP 請(qǐng)求批量發(fā)送,不用排隊(duì),這就解決了 HTTP 隊(duì)頭阻塞問(wèn)題。但批量發(fā)送的 HTTP 請(qǐng)求,必須按照發(fā)送的順序返回響應(yīng)
3、流式渲染,響應(yīng)端可以不用一次返回所有數(shù)據(jù),可以將數(shù)據(jù)拆分成多個(gè)模塊,產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊數(shù)據(jù),這樣客戶(hù)端就可以同步對(duì)數(shù)據(jù)進(jìn)行處理,減少響應(yīng)延遲,降低白屏?xí)r間。
4、請(qǐng)求頭引入了range頭域,它允許只請(qǐng)求資源的某個(gè)部分,即返回碼是206(Partial Content),這樣就方便了開(kāi)發(fā)者自由的選擇以便于充分利用帶寬和連接
5、增加 Host 頭,實(shí)現(xiàn)了虛擬主機(jī)技術(shù),將一臺(tái)服務(wù)器分成若干個(gè)主機(jī),這樣就可以在一臺(tái)服務(wù)器上部署多個(gè)網(wǎng)站了。通過(guò)配置 Host 的域名和端口號(hào),即可支持多個(gè) HTTP 服務(wù)
6、頭部增加一些緩存字段,如 E-Tag、Cache-Control 等
7、新增了24個(gè)錯(cuò)誤狀態(tài)響應(yīng)碼,如 409(Conflict)表示請(qǐng)求的資源與資源的當(dāng)前狀態(tài)發(fā)生沖突;410(Gone)表示服務(wù)器上的某個(gè)資源被永久性的刪除。
小結(jié):
請(qǐng)求和響應(yīng)成對(duì)出現(xiàn),順序串行。如果按QPS來(lái)理解的話,最大的并發(fā)數(shù)只能是 1
四、 HTTP/2
HTTP/2 誕生于 2015 年,最大特點(diǎn)是基于二進(jìn)制的特性,對(duì) HTTP 傳輸效率進(jìn)行了深度優(yōu)化。
新增了哪些特性?
1、二進(jìn)制幀
HTTP/2 將一個(gè) HTTP 請(qǐng)求劃分為 3 個(gè)部分:二進(jìn)制幀、消息、數(shù)據(jù)流
- 幀:一段二進(jìn)制數(shù)據(jù),是 HTTP/2 傳輸?shù)淖钚挝?/li>
- 消息:邏輯上的 HTTP 消息,比如請(qǐng)求、響應(yīng)等,由一或多個(gè)幀組成
- 數(shù)據(jù)流:連接中的一個(gè)虛擬信道,可以同時(shí)承載一條或多條消息,支持雙向承載
一個(gè)TCP連接上,承載著雙向消息,一條消息包含多個(gè)二進(jìn)制幀,每個(gè)幀都有唯一標(biāo)識(shí),來(lái)自不同數(shù)據(jù)流的幀可以交錯(cuò)發(fā)送,然后再根據(jù)每個(gè)幀頭的數(shù)據(jù)流標(biāo)識(shí)符重新組裝,這樣就實(shí)現(xiàn)了數(shù)據(jù)傳輸。
2、多路復(fù)用
HTTP/1.1 中的 KeepAlive 長(zhǎng)連接雖然可以傳輸很多請(qǐng)求,但它的吞吐量很低,因?yàn)樵诎l(fā)出請(qǐng)求等待響應(yīng)的那段時(shí)間里,這個(gè)長(zhǎng)連接不能做任何事!而 HTTP/2 通過(guò) Stream 這一設(shè)計(jì),允許請(qǐng)求并發(fā)傳輸。因此,HTTP/1.1 時(shí)代 Chrome 通過(guò) 6 個(gè)連接訪問(wèn)頁(yè)面的速度,遠(yuǎn)遠(yuǎn)比不上 HTTP/2 單連接的速度。
HTTP/2 的并發(fā)性能比 HTTP/1.1 通過(guò) TCP 連接實(shí)現(xiàn)并發(fā)要高。這是因?yàn)椋?dāng) HTTP/2 實(shí)現(xiàn) 100 個(gè)并發(fā) Stream 時(shí),只經(jīng)歷 1 次 TCP 握手、1 次 TCP 慢啟動(dòng)以及 1 次 TLS 握手,但 100 個(gè) TCP 連接會(huì)把上述 3 個(gè)過(guò)程都放大 100 倍!
3、頭部壓縮
HTTP/1.1 的頭部字段包含大量信息,而且每次請(qǐng)求都得帶上,占用了大量的帶寬。
HTTP/2 靜態(tài)表僅用一個(gè)數(shù)字來(lái)表示,其中,映射數(shù)字與字符串對(duì)應(yīng)關(guān)系的表格,被寫(xiě)死在 HTTP/2 實(shí)現(xiàn)框架中。這樣的編碼效率非常高,
什么是靜態(tài)表呢?HTTP/2 將 61 個(gè)高頻出現(xiàn)的頭部,比如描述瀏覽器的 User-Agent、GET 或 POST 方法、返回的 200 SUCCESS 響應(yīng)等,分別對(duì)應(yīng) 1 個(gè)數(shù)字再構(gòu)造出 ”字典“,并寫(xiě)入 HTTP/2 客戶(hù)端與服務(wù)端,用索引號(hào)表示重復(fù)的字符串,可以達(dá)到 50%~90% 的高壓縮率。
4、請(qǐng)求優(yōu)先級(jí)
由于采用多路復(fù)用,多個(gè)請(qǐng)求會(huì)同時(shí)產(chǎn)生多個(gè)數(shù)據(jù)流,數(shù)據(jù)流中有一個(gè)優(yōu)先級(jí)的標(biāo)識(shí),服務(wù)端根據(jù)這個(gè)標(biāo)識(shí)決定響應(yīng)的優(yōu)先順序。
流 ID 不能重用,只能順序遞增,客戶(hù)端發(fā)起的 ID 是奇數(shù),服務(wù)器端發(fā)起的 ID 是偶數(shù);
5、服務(wù)器端推送
HTTP/1.1 不支持服務(wù)器主動(dòng)推送消息,因此當(dāng)客戶(hù)端需要獲取通知時(shí),只能通過(guò)定時(shí)器不斷地輪詢(xún)拉取消息。HTTP/2 的消息推送結(jié)束了無(wú)效率的定時(shí)拉取,節(jié)約了大量帶寬和服務(wù)器資源。
例如:HTTP/1.1 中請(qǐng)求一個(gè)頁(yè)面時(shí),瀏覽器會(huì)先發(fā)送一個(gè) HTTP 請(qǐng)求,然后得到響應(yīng)的 HTML 內(nèi)容并開(kāi)始解析,如果發(fā)現(xiàn)有<script src="xxxx.js">標(biāo)簽,則會(huì)再次發(fā)起 HTTP 請(qǐng)求獲取對(duì)應(yīng)的 JS 內(nèi)容。而 HTTP/2 可以在返回 HTML 的同時(shí),將需要用到的 JS、CSS 等內(nèi)容一并返回給客戶(hù)端,當(dāng)瀏覽器解析到對(duì)應(yīng)標(biāo)簽時(shí),也就不需要再次發(fā)起請(qǐng)求了。
小結(jié):
通過(guò)二進(jìn)制幀流模式,打破之前的”請(qǐng)求 - 應(yīng)答“串行模式,單個(gè)TCP連接上支持并發(fā)請(qǐng)求、響應(yīng),多路復(fù)用大大提升了網(wǎng)絡(luò)吞吐量。
HTTP/2 作為升級(jí)版,為了與之前的版本保持兼容,對(duì)頭字段、狀態(tài)碼、請(qǐng)求方法等信息都保留不變,降低了學(xué)習(xí)成本,同時(shí)上層應(yīng)用也可以做到無(wú)縫兼容。
小提示:
做軟件架構(gòu)也是一樣,設(shè)計(jì)接口規(guī)范時(shí)一定要慎之又慎,盡量預(yù)留很長(zhǎng)一段時(shí)間的擴(kuò)展,后續(xù)更多是對(duì)里面的邏輯優(yōu)化重構(gòu),對(duì)外黑盒,無(wú)需感知。
為什么是 HTTP/2 ,而不是HTTP/2.0 ?
HTTP/2 工作組特別給出了解釋?zhuān)郧暗?.0、1.1 容易讓人誤解,實(shí)際使用中難以區(qū)分,所以,決定后續(xù)的版本不在使用小版本,一律采用大版本。
所以,接下來(lái),你只會(huì)看到 HTTP/2 、HTTP/3 ...
關(guān)于加密
為了滿(mǎn)足安全性,HTTP/2分別支持”加密“和”明文“,定義兩個(gè)字符串標(biāo)識(shí)符:“h2”表示加密的 HTTP/2,“h2c”表示明文的 HTTP/2,多出的那個(gè)字母“c”的意思是“clear text”。
五、 HTTP/3
HTTP/2 雖然使用“幀”、“流”“多路復(fù)用”,沒(méi)有了“隊(duì)頭阻塞”,但這些優(yōu)化技巧都是在應(yīng)用層里,而在底層,也就是 TCP 協(xié)議里,還是會(huì)發(fā)生“隊(duì)頭阻塞”。
HTTP/2 把多個(gè)請(qǐng)求 - 響應(yīng)分解成流,交給 TCP 后,TCP 會(huì)再拆成更小的段(segment)依次發(fā)送。如果網(wǎng)絡(luò)不好時(shí),會(huì)發(fā)生丟包。
TCP為了保證可靠性傳輸,會(huì)有丟包重傳機(jī)制。這樣,其他的包即使已經(jīng)收到了,也只能放在緩沖區(qū)里,這樣就又出現(xiàn)了隊(duì)頭阻塞,這是TCP協(xié)議固有的。
為了解決這個(gè)問(wèn)題,Google推出了QUIC協(xié)議,讓 HTTP 跑在 QUIC 上而不是 TCP 上,這個(gè)新版本,我們稱(chēng)之為 HTTP/3
HTTP/3 目前還處于草案階段,離正式發(fā)布還有段時(shí)間,我們拭目以待...
【編輯推薦】https://mp.weixin.qq.com/s/zn1aJMoNH9B741EoLBJcgA