HTTP(Hyper Text Transfer Protocol)<超文本傳輸協(xié)議>
在TCP/IP協(xié)議模型中顺呕, HTTP協(xié)議是在應(yīng)用層使用的協(xié)議,他的作用是將我們需要發(fā)送的數(shù)據(jù)進(jìn)行封裝必指,然后通過(guò)下一層的層層傳遞發(fā)送給目的主機(jī)囊咏,目的主機(jī)會(huì)給他一個(gè)響應(yīng)或者返回他查詢的數(shù)據(jù)。應(yīng)該是在我們開(kāi)發(fā)的過(guò)程中使用到最多的一個(gè)協(xié)議。本篇文章主要對(duì)HTTP協(xié)議做一個(gè)盡可能詳細(xì)的介紹匆笤,方便各位瀏覽也方便自己日后有問(wèn)題查閱研侣。
HTTP是基于客戶/服務(wù)器模式,且面向連接的炮捧。典型的HTTP事務(wù)處理有如下的過(guò)程:
- 瀏覽器向 DNS 服務(wù)器請(qǐng)求解析該 URL 中的域名所對(duì)應(yīng)的 IP 地址;
- 解析出 IP 地址后庶诡,根據(jù)該 IP 地址和默認(rèn)端口 80,和服務(wù)器建立TCP連接;
- 瀏覽器發(fā)出讀取文件(URL 中域名后面部分對(duì)應(yīng)的文件)的HTTP 請(qǐng)求咆课,該請(qǐng)求報(bào)文作為 TCP 三次握手的第三個(gè)報(bào)文的數(shù)據(jù)發(fā)送給服務(wù)器;
- 服務(wù)器對(duì)瀏覽器請(qǐng)求作出響應(yīng)末誓,并把對(duì)應(yīng)的 html 文本發(fā)送給瀏覽器;
- 釋放 TCP連接;
- 瀏覽器將該 html 文本并顯示內(nèi)容;
客戶與服務(wù)器之間的HTTP連接是一種一次性連接,它限制每次連接只處理一個(gè)請(qǐng)求书蚪,當(dāng)服務(wù)器返回本次請(qǐng)求的應(yīng)答后便立即關(guān)閉連接喇澡,下次請(qǐng)求再重新建立連接。這種一次性連接主要考慮到WWW服務(wù)器面向的是Internet中成干上萬(wàn)個(gè)用戶殊校,且只能提供有限個(gè)連接晴玖,故服務(wù)器不會(huì)讓一個(gè)連接處于等待狀態(tài),及時(shí)地釋放連接可以大大提高服務(wù)器的執(zhí)行效率
從技術(shù)上講是客戶在一個(gè)特定的TCP端口(端口號(hào)一般為80)上打開(kāi)一個(gè)套接字为流。如果服務(wù)器一直在這個(gè)周知的端口上傾聽(tīng)連接呕屎,則該連接便會(huì)建立起來(lái)。然后客戶通過(guò)該連接發(fā)送一個(gè)包含請(qǐng)求方法的請(qǐng)求塊敬察。
目前HTTP的版本有 0.9秀睛,1.0,1.1莲祸,2.0
使用最多的版本還是HTTP/1.1
HTTP協(xié)議有以下幾個(gè)特點(diǎn):
1.HTTP協(xié)議是基于TCP/IP協(xié)議模型的蹂安,所以我們前面文章介紹過(guò)的TCP的慢啟動(dòng)就自然而然的反應(yīng)在了每一個(gè)HTTP的數(shù)據(jù)交互里,當(dāng)一個(gè)頁(yè)面有很多小文件發(fā)起的請(qǐng)求的時(shí)候锐帜,這些請(qǐng)求都會(huì)經(jīng)歷慢啟動(dòng)田盈,花費(fèi)的時(shí)間就會(huì)比較多。
2.TCP的多條鏈接同時(shí)發(fā)起引起帶寬競(jìng)爭(zhēng)缴阎,帶寬固定缠黍,所以可能想快速下載的資源反而下載的慢。
3.一條HTTP建立的鏈接只有處理了一個(gè)請(qǐng)求才可以處理下一個(gè)TCP請(qǐng)求药蜻,回有頭部阻塞的情況出現(xiàn)。HTTP/2 進(jìn)一步解決線頭阻塞問(wèn)題替饿。通過(guò)獨(dú)立不同流语泽,讓各個(gè)流之間實(shí)現(xiàn)相互獨(dú)立傳輸,互不干擾.
4.無(wú)狀態(tài)保存:自身不對(duì)某次請(qǐng)求和響應(yīng)之間的通信狀態(tài)做保存视卢,不做持久化處理踱卵。這是為了更快地處理大量事務(wù),確保協(xié)議的可伸縮性,而特意把HTTP協(xié)議設(shè)計(jì)成 如此簡(jiǎn)單的。但是隨著WEB的發(fā)展,很多時(shí)候需要攜帶狀態(tài)惋砂,后來(lái)HTTP協(xié)議引入了cookie功能妒挎,后面會(huì)詳細(xì)介紹。
5.無(wú)連接:無(wú)連接的含義是限制每次連接只處理一個(gè)請(qǐng)求西饵。服務(wù)器處理完客戶的請(qǐng)求酝掩,并收到客戶的應(yīng)答后,即斷開(kāi)連接眷柔。采用這種方式可以節(jié)省傳輸時(shí)間期虾,并且可以提高并發(fā)性能,不能和每個(gè)用戶建立長(zhǎng)久的連接驯嘱,請(qǐng)求一次相應(yīng)一次镶苞,服務(wù)端和客戶端就中斷了。但是無(wú)連接有兩種方式鞠评,早期的http協(xié)議是一個(gè)請(qǐng)求一個(gè)響應(yīng)之后茂蚓,直接就斷開(kāi)了,但是現(xiàn)在的http協(xié)議1.1版本不是直接就斷開(kāi)了剃幌,而是等幾秒鐘聋涨,這幾秒鐘是等什么呢,等著用戶有后續(xù)的操作锥忿,如果用戶在這幾秒鐘之內(nèi)有新的請(qǐng)求牛郑,那么還是通過(guò)之前的連接通道來(lái)收發(fā)消息,如果過(guò)了這幾秒鐘用戶沒(méi)有發(fā)送新的請(qǐng)求敬鬓,那么就會(huì)斷開(kāi)連接淹朋,這樣可以提高效率,減少短時(shí)間內(nèi)建立連接的次數(shù)钉答,因?yàn)榻⑦B接也是耗時(shí)的础芍,默認(rèn)的好像是3秒種現(xiàn)在,但是這個(gè)時(shí)間是可以通過(guò)后端的代碼來(lái)調(diào)整的数尿,自己網(wǎng)站根據(jù)自己網(wǎng)站用戶的行為來(lái)分析統(tǒng)計(jì)出一個(gè)最優(yōu)的等待時(shí)間仑性。
HTTP請(qǐng)求報(bào)文解析
第一部分 請(qǐng)求行
由【請(qǐng)求方法 空格 URI 空格 HTTP版本 換行符】組成
比如:
GET 為請(qǐng)求方法
/slide_1_86523_474747.html 為URI
HTTP/1.1 為HTTP版本
第二部分 請(qǐng)求頭部,用來(lái)說(shuō)明服務(wù)器要使用的附加信息右蹦,有很多種參數(shù)可以選擇(后面會(huì)有詳細(xì)的參數(shù)表)
第三部分 是一個(gè)空行
第四部分是請(qǐng)求報(bào)文的主體
下面是一個(gè)請(qǐng)求的截圖诊杆,可以對(duì)比看下:
這是一個(gè)HTTP請(qǐng)求報(bào)文的截圖。把里面的數(shù)據(jù)拿出來(lái)整理一下就是下面的格式
GET /slide_1_86523_474747.html HTTP/1.1
Host: slide.news.sina.com.cn
Cookie: lxlrttp=1578733570; ULV=1597218435568:91:11:3:61.52.165.250_1597218193.555396:1597218193465;
U_TRS2=000000a0.14675b80.5f339e83.291ef996; Apache=61.52.165.250_1597218193.555396; _ga=GA1.3.1348710685.1578706684; _gid=GA1
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15\r\n
Referer: https://www.sina.com.cn/\r\n
Accept-Language: zh-cn\r\n
Accept-Encoding: gzip, deflate\r\n
HTTP響應(yīng)報(bào)文解析
第一行:【HTTP版本 空格 狀態(tài)碼 空格 狀態(tài)碼描述 換行符】組成
第二行:返回的各種參數(shù)何陆,后面會(huì)有表格對(duì)應(yīng)查詢
第三行:一個(gè)固定的換行符
第四行:返回的數(shù)據(jù)
知識(shí)點(diǎn)整理
HTTP協(xié)議看似簡(jiǎn)單晨汹,實(shí)際上也是比較復(fù)雜的,擴(kuò)展性比較強(qiáng)贷盲,下面整理了一些個(gè)人感覺(jué)比較重要的知識(shí)點(diǎn)淘这,很多來(lái)自參考的文章整理,自己對(duì)比寫(xiě)了一遍加深印象,也有很多感覺(jué)寫(xiě)的實(shí)在很好的直接拿過(guò)來(lái)用了铝穷,各位可以選擇性的瀏覽钠怯。
請(qǐng)求方法
請(qǐng)求體參數(shù)表
(由http://www.reibang.com/p/7c8b4576e4bb 整理,很詳細(xì)曙聂,直接拿過(guò)來(lái)了晦炊,方便以后查閱)
HTTP響應(yīng)的狀態(tài)碼
Content-Type 字段
關(guān)于字符的編碼,1.0版規(guī)定筹陵,頭信息必須是 ASCII 碼刽锤,后面的數(shù)據(jù)可以是任何格式。因此朦佩,服務(wù)器回應(yīng)的時(shí)候并思,必須告訴客戶端,數(shù)據(jù)是什么格式语稠,這就是Content-Type字段的作用宋彼。
下面是一些常見(jiàn)的Content-Type字段的值。
這些數(shù)據(jù)類(lèi)型總稱為MIME-TYPE仙畦,每個(gè)值包括一級(jí)類(lèi)型和二級(jí)類(lèi)型输涕,之間用斜杠分隔。
除了預(yù)定義的類(lèi)型慨畸,廠商也可以自定義類(lèi)型莱坎。
MIME type還可以在尾部使用分號(hào),添加參數(shù)寸士。
Content-Type: text/html; charset=utf-8
上面的類(lèi)型表明檐什,發(fā)送的是網(wǎng)頁(yè),而且編碼是UTF-8弱卡。
客戶端請(qǐng)求的時(shí)候乃正,可以使用Accept字段聲明自己可以接受哪些數(shù)據(jù)格式。
Accept: /
上面代碼中婶博,客戶端聲明自己可以接受任何格式的數(shù)據(jù)瓮具。
MIME type不僅用在HTTP協(xié)議,還可以用在其他地方凡人,比如HTML網(wǎng)頁(yè)名党。
內(nèi)容壓縮傳輸
HTTP壓縮是指: Web服務(wù)器和瀏覽器之間壓縮傳輸?shù)摹蔽谋緝?nèi)容“的方法。 HTTP采用通用的壓縮算法挠轴,比如gzip來(lái)壓縮html,javascript, CSS文件兑巾。 能大大減少網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量,提高了用戶顯示網(wǎng)頁(yè)的速度忠荞。當(dāng)然,同時(shí)會(huì)增加一點(diǎn)點(diǎn)服務(wù)器的開(kāi)銷(xiāo)。 首先委煤,瀏覽器發(fā)送一個(gè)請(qǐng)求(request)給web服務(wù)器堂油,支持一個(gè)壓縮格式如(gzip),服務(wù)端會(huì)將原來(lái)的源碼壓縮之后碧绞,通過(guò)http響應(yīng)(response)信息返回給web瀏覽器府框,瀏覽器接收之后,顯示出來(lái)讥邻。
內(nèi)容編碼:通過(guò)content-encoding來(lái)指定內(nèi)容的壓縮方式迫靖,通過(guò)content-length來(lái)指定文件大小,服務(wù)端會(huì)在緩沖指定大小的數(shù)據(jù)后才發(fā)送到瀏覽器兴使,瀏覽器收到指定大小的數(shù)據(jù)后認(rèn)為文件已接收完畢系宜,之后用相應(yīng)的壓縮方式對(duì)內(nèi)容進(jìn)行解壓。
傳輸編碼:上述方式中服務(wù)器等指定大小的資源緩沖好才發(fā)給瀏覽器发魄,造成瀏覽器等待時(shí)間長(zhǎng)盹牧,會(huì)影響用戶體驗(yàn)±祝可通過(guò)transfer-encoding:chunked來(lái)改變這一行為:服務(wù)器會(huì)將文件內(nèi)容分塊傳輸給瀏覽器而不用等所有緩沖完汰寓,最后一塊大小為0,指示瀏覽器只要收到數(shù)據(jù)就進(jìn)行處理展示而不用等所有收到苹粟。
content-encoding和transfer-encoding通常結(jié)合使用
http壓縮對(duì)純文本可以壓縮至原內(nèi)容的40%, 從而節(jié)省了60%的數(shù)據(jù)傳輸有滑。
在http協(xié)議中,可以對(duì)內(nèi)容(也就是body部分)進(jìn)行編碼嵌削, 可以采用gzip這樣的編碼毛好。 從而達(dá)到壓縮的目的。 也可以使用其他的編碼把內(nèi)容攪亂或加密掷贾,以此來(lái)防止未授權(quán)的第三方看到文檔的內(nèi)容睛榄。
壓縮過(guò)程:
1. 瀏覽器發(fā)送Http request 給Web服務(wù)器, request 中有Accept-Encoding: gzip, deflate。 (告訴服務(wù)器想帅, 瀏覽器支持gzip壓縮)
2. Web服務(wù)器接到request后场靴, 生成原始的Response, 其中有原始的Content-Type和Content-Length。
3. Web服務(wù)器通過(guò)Gzip港准,來(lái)對(duì)Response進(jìn)行編碼旨剥, 編碼后header中有Content-Type和Content-Length(壓縮后的大小), 并且增加了Content-Encoding:gzip. 然后把Response發(fā)送給瀏覽器浅缸。
上面截圖的服務(wù)器響應(yīng)也有對(duì)應(yīng)的壓縮字段轨帜,可以對(duì)比看下。
Content-Encoding 字段
HTTP可以對(duì)發(fā)送的數(shù)據(jù)進(jìn)行壓縮衩椒,這個(gè)字段就是說(shuō)明壓縮使用的方法
Content-Encoding: gzip
一種數(shù)據(jù)格式蚌父,默認(rèn)且目前僅使用deflate算法壓縮data部分哮兰。
缺點(diǎn):
JPEG這類(lèi)文件用gzip壓縮的不夠好。
簡(jiǎn)單來(lái)說(shuō)苟弛, Gzip壓縮是在一個(gè)文本文件中找出類(lèi)似的字符串喝滞, 并臨時(shí)替換他們,使整個(gè)文件變小膏秫。這種形式的壓縮對(duì)Web來(lái)說(shuō)非常適合右遭, 因?yàn)镠TML和CSS文件通常包含大量的重復(fù)的字符串,例如空格缤削,標(biāo)簽窘哈。
Content-Encoding: compress 表明實(shí)體采用Unix的文件壓縮程序
Content-Encoding: deflate deflate是一種壓縮算法,是huffman編碼的一種加強(qiáng)
Content-Encoding: identity 表明沒(méi)有對(duì)實(shí)體進(jìn)行編碼亭敢。當(dāng)沒(méi)有Content-Encoding header時(shí)滚婉, 就默認(rèn)為這種情況
客戶端在請(qǐng)求時(shí),用Accept-Encoding字段說(shuō)明自己可以接受哪些壓縮方法吨拗。比如:
Accept-Encoding: gzip, deflate
http壓縮對(duì)純文本可以壓縮至原內(nèi)容的40%, 從而節(jié)省了60%的數(shù)據(jù)傳輸满哪。
瀏覽器是不會(huì)對(duì)Request壓縮的。 但是 一些HTTP程序在發(fā)送Request時(shí)劝篷,會(huì)對(duì)其進(jìn)行編碼哨鸭。
持久連接
HTTP/1.0 版的主要缺點(diǎn)是,每個(gè)TCP連接只能發(fā)送一個(gè)請(qǐng)求娇妓。發(fā)送數(shù)據(jù)完畢像鸡,連接就關(guān)閉,如果還要請(qǐng)求其他資源哈恰,就必須再新建一個(gè)連接只估。
TCP連接的新建成本很高,因?yàn)樾枰蛻舳撕头?wù)器三次握手着绷,并且開(kāi)始時(shí)發(fā)送速率較慢(slow start)蛔钙。所以,HTTP 1.0版本的性能比較差荠医。隨著網(wǎng)頁(yè)加載的外部資源越來(lái)越多吁脱,這個(gè)問(wèn)題就愈發(fā)突出了。
為了解決這個(gè)問(wèn)題彬向,有些瀏覽器在請(qǐng)求時(shí)兼贡,用了一個(gè)非標(biāo)準(zhǔn)的Connection字段。
Connection: keep-alive
這個(gè)字段要求服務(wù)器不要關(guān)閉TCP連接娃胆,以便其他請(qǐng)求復(fù)用遍希,服務(wù)器同樣回應(yīng)這個(gè)字段
Connection: keep-alive
一個(gè)可以復(fù)用的TCP連接就建立了,直到客戶端或服務(wù)器主動(dòng)關(guān)閉連接里烦。但是凿蒜,這不是標(biāo)準(zhǔn)字段禁谦,不同實(shí)現(xiàn)的行為可能不一致,因此不是根本的解決辦法废封。
1.1 版的最大變化枷畏,就是引入了持久連接(persistent connection),即TCP連接默認(rèn)不關(guān)閉虱饿,可以被多個(gè)請(qǐng)求復(fù)用,不用聲明Connection: keep-alive触趴。
客戶端和服務(wù)器發(fā)現(xiàn)對(duì)方一段時(shí)間沒(méi)有活動(dòng)氮发,就可以主動(dòng)關(guān)閉連接。不過(guò)冗懦,規(guī)范的做法是爽冕,客戶端在最后一個(gè)請(qǐng)求時(shí),發(fā)送Connection: close披蕉,明確要求服務(wù)器關(guān)閉TCP連接颈畸。
Connection: close
目前,對(duì)于同一個(gè)域名没讲,大多數(shù)瀏覽器允許同時(shí)建立6個(gè)持久連接眯娱。
管道機(jī)制
1.1版本引入了管道機(jī)制,在同一個(gè)TCP連接里爬凑,客戶端可以同時(shí)發(fā)送多個(gè)請(qǐng)求徙缴,這樣就進(jìn)一步改善了HTTP協(xié)議的效率。
舉例來(lái)說(shuō)嘁信,客戶端需要請(qǐng)求兩個(gè)資源于样。以前的做法是,在同一個(gè)TCP連接里面潘靖,先發(fā)送A請(qǐng)求穿剖,然后等待服務(wù)器做出回應(yīng),收到后再發(fā)出B請(qǐng)求卦溢。管道機(jī)制則是允許瀏覽器同時(shí)發(fā)出A請(qǐng)求和B請(qǐng)求糊余,但是服務(wù)器還是按照順序,先回應(yīng)A請(qǐng)求既绕,完成后再回應(yīng)B請(qǐng)求啄刹。
Content-Length 字段
一個(gè)TCP連接現(xiàn)在可以傳送多個(gè)回應(yīng)刻盐,勢(shì)必就要有一種機(jī)制战虏,區(qū)分?jǐn)?shù)據(jù)包是屬于哪一個(gè)回應(yīng)的粉臊。這就是Content-length字段的作用寞忿,聲明本次回應(yīng)的數(shù)據(jù)長(zhǎng)度终吼。
Content-Length: 3495
上面代碼告訴瀏覽器,本次回應(yīng)的長(zhǎng)度是3495個(gè)字節(jié)尊搬,后面的字節(jié)就屬于下一個(gè)回應(yīng)了湾蔓。
分塊傳輸編碼
使用Content-Length 字段的前提是,服務(wù)器發(fā)送回應(yīng)之前壹甥,必須知道回應(yīng)的數(shù)據(jù)長(zhǎng)度救巷,
對(duì)于一些很耗時(shí)的動(dòng)態(tài)操作來(lái)說(shuō),這意味著句柠,服務(wù)器要等到所有操作完成浦译,才能發(fā)送數(shù)據(jù),顯然這樣的效率不高溯职。更好的處理方法是精盅,產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊谜酒,采用"流模式"(stream)取代"緩存模式"(buffer)叹俏。
因此,1.1版規(guī)定可以不使用Content-Length字段僻族,而使用"分塊傳輸編碼"(chunked transfer encoding)粘驰。只要請(qǐng)求或回應(yīng)的頭信息有Transfer-Encoding字段,就表明回應(yīng)將由數(shù)量未定的數(shù)據(jù)塊組成述么。
每個(gè)非空的數(shù)據(jù)塊之前蝌数,會(huì)有一個(gè)16進(jìn)制的數(shù)值,表示這個(gè)塊的長(zhǎng)度碉输。最后是一個(gè)大小為0的塊籽前,就表示本次回應(yīng)的數(shù)據(jù)發(fā)送完了。下面是一個(gè)例子敷钾。
隊(duì)頭阻塞
雖然1.1版允許復(fù)用TCP連接枝哄,但是同一個(gè)TCP連接里面,所有的數(shù)據(jù)通信是按次序進(jìn)行的阻荒。服務(wù)器只有處理完一個(gè)回應(yīng)挠锥,才會(huì)進(jìn)行下一個(gè)回應(yīng)。要是前面的回應(yīng)特別慢侨赡,后面就會(huì)有許多請(qǐng)求排隊(duì)等著蓖租。這稱為"隊(duì)頭堵塞"(Head-of-line blocking)。
為了避免這個(gè)問(wèn)題羊壹,只有兩種方法:一是減少請(qǐng)求數(shù)蓖宦,二是同時(shí)多開(kāi)持久連接。這導(dǎo)致了很多的網(wǎng)頁(yè)優(yōu)化技巧油猫,比如合并腳本和樣式表稠茂、將圖片嵌入CSS代碼、域名分片(domain sharding)等等。如果HTTP協(xié)議設(shè)計(jì)得更好一些睬关,這些額外的工作是可以避免的
數(shù)據(jù)的分塊傳輸
有一些文件可以使用gzip進(jìn)行壓縮诱担,但是視頻就不可以了,這個(gè)時(shí)候我們就需要進(jìn)行分塊傳輸
在報(bào)文中使用"Transer-Encoding:chunked"表示电爹,代表body部分?jǐn)?shù)據(jù)是分塊傳輸?shù)摹?/p>
在body中存在一個(gè)content-length字段表示body的長(zhǎng)度蔫仙,兩者不能共存,另外很多時(shí)候是流式數(shù)據(jù)丐箩,body中沒(méi)有指明content-length摇邦,這個(gè)時(shí)候一般就是chunked傳輸了。
分塊運(yùn)輸?shù)木幋a格式:
<1> 每一個(gè)分塊包含長(zhǎng)度和數(shù)據(jù)塊
<2> 長(zhǎng)度頭按照CRLF結(jié)束
<3> 數(shù)據(jù)塊在長(zhǎng)度快后屎勘,且最后CRLF結(jié)尾
<4> 使用長(zhǎng)度0表示結(jié)束涎嚼,"0\r\n\r\n"
如下圖
截?cái)喟l(fā)送
分塊解決了咋們一部分問(wèn)題,但是有的時(shí)候我們想截?cái)喟l(fā)送怎么辦呢挑秉。
在HTTP中提供了使用字段“Accept - Ranges: bytes”,明確告知客戶端:“我是支持范圍請(qǐng)求的”苔货,Range從0開(kāi)始計(jì)算犀概,比如Range:0-5則讀取前6個(gè)字節(jié),服務(wù)器收到了這個(gè)請(qǐng)求夜惭,將如何回應(yīng)呢
<1> 合法性檢查姻灶。比如一共只有20字節(jié),但是請(qǐng)求range:100-200诈茧。此時(shí)會(huì)返回416----"范圍請(qǐng)求有誤"
<2> 范圍正常产喉,則返回216,表示請(qǐng)求數(shù)據(jù)知識(shí)一部分
<3> 服務(wù)器端在相應(yīng)投資端增加Content-Range,格式"bytes x-y/length"敢会。
斷點(diǎn)續(xù)傳的實(shí)現(xiàn)思路:
<1> 查看服務(wù)器是否支持范圍請(qǐng)求并記錄文件大小
<2> 多個(gè)線程分別負(fù)責(zé)不同的range
<3> 下載同時(shí)記錄進(jìn)度曾沈,即使因?yàn)榫W(wǎng)絡(luò)等原因中斷也沒(méi)事,Range請(qǐng)求剩余即可
Cookie機(jī)制
HTTP是無(wú)狀態(tài)鸥昏、無(wú)記憶的塞俱,Cookie機(jī)制的出現(xiàn)讓其有記憶功能,簡(jiǎn)單流程如下:
Cookie是由瀏覽器負(fù)責(zé)存儲(chǔ)吏垮,換個(gè)瀏覽器打開(kāi)網(wǎng)頁(yè)的話之前溝通的Cookie就不會(huì)攜帶了障涯。
Cookie常見(jiàn)的應(yīng)用一個(gè)是身份識(shí)別,一個(gè)是廣告追蹤膳汪,比如我們?cè)谠L問(wèn)網(wǎng)頁(yè)視頻或者圖片的時(shí)候唯蝶,廣告商會(huì)悄悄給我們Cookie打上標(biāo)記,方便做關(guān)聯(lián)分析和行為分析遗嗽,從而給我推薦一些相關(guān)內(nèi)容粘我。
HTTP代理
之前說(shuō)的一一對(duì)一的問(wèn)答情景,但是很多情況下也存在多臺(tái)服務(wù)器進(jìn)行通信服務(wù)媳谁,比較常見(jiàn)的一個(gè)做法就是在請(qǐng)求方與問(wèn)答方中間增加一個(gè)中間代理涂滴。
代理作為中間位置友酱,相對(duì)青請(qǐng)求方為服務(wù)端,相對(duì)于后端為請(qǐng)求方柔纵。
代理常見(jiàn)的功能未負(fù)載均衡缔杉,在負(fù)載均衡中需要區(qū)分正向代理與反向代理,其中也就會(huì)涉及調(diào)度算法搁料,比如輪詢或详,一致性哈希等。
擴(kuò)展:
HTTP/2
HTTP/2 的前世是HTTP1.0和HTTP1.1郭计。雖然之前僅僅只有兩個(gè)版本霸琴,但這兩個(gè)版本所包含的協(xié)議規(guī)范之龐大,足以讓任何一個(gè)有經(jīng)驗(yàn)的工程師為之頭疼昭伸。網(wǎng)絡(luò)協(xié)議新版本并不會(huì)馬上取代舊版本梧乘。實(shí)際上,1.0和1.1在之后很長(zhǎng)的一段時(shí)間內(nèi)一直并存庐杨,這是由于網(wǎng)絡(luò)基礎(chǔ)設(shè)施更新緩慢所決定的选调。
2015年,HTTP/2 發(fā)布灵份。它不叫 HTTP/2.0仁堪,是因?yàn)闃?biāo)準(zhǔn)委員會(huì)不打算再發(fā)布子版本了,下一個(gè)新版本將是 HTTP/3填渠。
二進(jìn)制協(xié)議
HTTP/1.1 版的頭信息肯定是文本(ASCII編碼)弦聂,數(shù)據(jù)體可以是文本,也可以是二進(jìn)制氛什。HTTP/2 則是一個(gè)徹底的二進(jìn)制協(xié)議莺葫,頭信息和數(shù)據(jù)體都是二進(jìn)制,并且統(tǒng)稱為"幀"(frame):頭信息幀和數(shù)據(jù)幀枪眉。
二進(jìn)制協(xié)議的一個(gè)好處是徙融,可以定義額外的幀。HTTP/2 定義了近十種幀瑰谜,為將來(lái)的高級(jí)應(yīng)用打好了基礎(chǔ)欺冀。如果使用文本實(shí)現(xiàn)這種功能,解析數(shù)據(jù)將會(huì)變得非常麻煩萨脑,二進(jìn)制解析則方便得多隐轩。
多工
HTTP/2 復(fù)用TCP連接,在一個(gè)連接里渤早,客戶端和瀏覽器都可以同時(shí)發(fā)送多個(gè)請(qǐng)求或回應(yīng)职车,而且不用按照順序一一對(duì)應(yīng),這樣就避免了"隊(duì)頭堵塞"。
舉例來(lái)說(shuō)悴灵,在一個(gè)TCP連接里面扛芽,服務(wù)器同時(shí)收到了A請(qǐng)求和B請(qǐng)求,于是先回應(yīng)A請(qǐng)求积瞒,結(jié)果發(fā)現(xiàn)處理過(guò)程非常耗時(shí)川尖,于是就發(fā)送A請(qǐng)求已經(jīng)處理好的部分, 接著回應(yīng)B請(qǐng)求茫孔,完成后叮喳,再發(fā)送A請(qǐng)求剩下的部分。
這樣雙向的缰贝、實(shí)時(shí)的通信馍悟,就叫做多工(Multiplexing)。
數(shù)據(jù)流
因?yàn)?HTTP/2 的數(shù)據(jù)包是不按順序發(fā)送的剩晴,同一個(gè)連接里面連續(xù)的數(shù)據(jù)包锣咒,可能屬于不同的回應(yīng)。因此赞弥,必須要對(duì)數(shù)據(jù)包做標(biāo)記宠哄,指出它屬于哪個(gè)回應(yīng)。
HTTP/2 將每個(gè)請(qǐng)求或回應(yīng)的所有數(shù)據(jù)包嗤攻,稱為一個(gè)數(shù)據(jù)流(stream)。每個(gè)數(shù)據(jù)流都有一個(gè)獨(dú)一無(wú)二的編號(hào)诽俯。數(shù)據(jù)包發(fā)送的時(shí)候妇菱,都必須標(biāo)記數(shù)據(jù)流ID,用來(lái)區(qū)分它屬于哪個(gè)數(shù)據(jù)流暴区。另外還規(guī)定闯团,客戶端發(fā)出的數(shù)據(jù)流,ID一律為奇數(shù)仙粱,服務(wù)器發(fā)出的房交,ID為偶數(shù)。
數(shù)據(jù)流發(fā)送到一半的時(shí)候伐割,客戶端和服務(wù)器都可以發(fā)送信號(hào)(RST_STREAM幀)候味,取消這個(gè)數(shù)據(jù)流。1.1版取消數(shù)據(jù)流的唯一方法隔心,就是關(guān)閉TCP連接白群。這就是說(shuō),HTTP/2 可以取消某一次請(qǐng)求硬霍,同時(shí)保證TCP連接還打開(kāi)著帜慢,可以被其他請(qǐng)求使用。
客戶端還可以指定數(shù)據(jù)流的優(yōu)先級(jí)。優(yōu)先級(jí)越高粱玲,服務(wù)器就會(huì)越早回應(yīng)躬柬。
頭信息壓縮
HTTP 協(xié)議不帶有狀態(tài),每次請(qǐng)求都必須附上所有信息抽减。所以允青,請(qǐng)求的很多字段都是重復(fù)的,比如Cookie和User Agent胯甩,一模一樣的內(nèi)容昧廷,每次請(qǐng)求都必須附帶,這會(huì)浪費(fèi)很多帶寬偎箫,也影響速度木柬。
HTTP/2 對(duì)這一點(diǎn)做了優(yōu)化,引入了頭信息壓縮機(jī)制(header compression)淹办。一方面眉枕,頭信息使用gzip或compress壓縮后再發(fā)送;另一方面怜森,客戶端和服務(wù)器同時(shí)維護(hù)一張頭信息表速挑,所有字段都會(huì)存入這個(gè)表,生成一個(gè)索引號(hào)副硅,以后就不發(fā)送同樣字段了姥宝,只發(fā)送索引號(hào),這樣就提高速度了恐疲。
服務(wù)器推送
HTTP/2 允許服務(wù)器未經(jīng)請(qǐng)求腊满,主動(dòng)向客戶端發(fā)送資源,這叫做服務(wù)器推送(server push)培己。
常見(jiàn)場(chǎng)景是客戶端請(qǐng)求一個(gè)網(wǎng)頁(yè)碳蛋,這個(gè)網(wǎng)頁(yè)里面包含很多靜態(tài)資源。正常情況下省咨,客戶端必須收到網(wǎng)頁(yè)后肃弟,解析HTML源碼,發(fā)現(xiàn)有靜態(tài)資源零蓉,再發(fā)出靜態(tài)資源請(qǐng)求笤受。其實(shí),服務(wù)器可以預(yù)期到客戶端請(qǐng)求網(wǎng)頁(yè)后敌蜂,很可能會(huì)再請(qǐng)求靜態(tài)資源感论,所以就主動(dòng)把這些靜態(tài)資源隨著網(wǎng)頁(yè)一起發(fā)給客戶端了。
參考閱讀: