HTTP 的特點(diǎn)
所以接下來先是聊聊 HTTP 協(xié)議的特點(diǎn)、優(yōu)點(diǎn)和缺點(diǎn)传透。既要看到它好的一面,也要正視它不好的一面,只有全方位、多角度了解 HTTP塌西,才能實(shí)現(xiàn)“揚(yáng)長避短”歌焦,更好地利用 HTTP。
靈活可擴(kuò)展
首先郁油, HTTP 協(xié)議是一個(gè)“靈活可擴(kuò)展”的傳輸協(xié)議。
HTTP 協(xié)議最初誕生的時(shí)候就比較簡(jiǎn)單攀痊,本著開放的精神只規(guī)定了報(bào)文的基本格式桐腌,比如用空格分隔單詞,用換行分隔字段苟径,“header+body”等案站,報(bào)文里的各個(gè)組成部分都沒有做嚴(yán)格的語法語義限制,可以由開發(fā)者任意定制棘街。
所以蟆盐,HTTP 協(xié)議就隨著互聯(lián)網(wǎng)的發(fā)展一同成長起來了。在這個(gè)過程中遭殉,HTTP 協(xié)議逐漸增加了請(qǐng)求方法石挂、版本號(hào)、狀態(tài)碼险污、頭字段等特性痹愚。而 body 也不再限于文本形式的 TXT 或 HTML,而是能夠傳輸圖片蛔糯、音頻視頻等任意數(shù)據(jù)拯腮,這些都是源于它的“靈活可擴(kuò)展”的特點(diǎn)。
而那些 RFC 文檔蚁飒,實(shí)際上也可以理解為是對(duì)已有擴(kuò)展的“承認(rèn)和標(biāo)準(zhǔn)化”动壤,實(shí)現(xiàn)了“從實(shí)踐中來,到實(shí)踐中去”的良性循環(huán)淮逻。
也正是因?yàn)檫@個(gè)特點(diǎn)琼懊,HTTP 才能在三十年的歷史長河中“屹立不倒”,從最初的低速實(shí)驗(yàn)網(wǎng)絡(luò)發(fā)展到現(xiàn)在的遍布全球的高速互聯(lián)網(wǎng)爬早,始終保持著旺盛的生命力肩碟。
可靠傳輸
第二個(gè)特點(diǎn), HTTP 協(xié)議是一個(gè)“可靠”的傳輸協(xié)議凸椿。
這個(gè)特點(diǎn)顯而易見,因?yàn)?HTTP 協(xié)議是基于 TCP/IP 的翅溺,而 TCP 本身是一個(gè)“可靠”的傳輸協(xié)議脑漫,所以 HTTP 自然也就繼承了這個(gè)特性髓抑,能夠在請(qǐng)求方和應(yīng)答方之間“可靠”地傳輸數(shù)據(jù)。
它的具體做法與 TCP/UDP 差不多优幸,都是對(duì)實(shí)際傳輸?shù)臄?shù)據(jù)(entity)做了一層包裝吨拍,加上一個(gè)頭,然后調(diào)用 Socket API网杆,通過 TCP/IP 協(xié)議棧發(fā)送或者接收羹饰。
不過我們必須正確地理解“可靠”的含義,HTTP 并不能 100% 保證數(shù)據(jù)一定能夠發(fā)送到另一端碳却,在網(wǎng)絡(luò)繁忙队秩、連接質(zhì)量差等惡劣的環(huán)境下,也有可能收發(fā)失敗昼浦♀勺剩“可靠”只是向使用者提供了一個(gè)“承諾”,會(huì)在下層用多種手段“盡量”保證數(shù)據(jù)的完整送達(dá)关噪。
當(dāng)然鸟蟹,如果遇到光纖被意外挖斷這樣的極端情況,即使是神仙也不能發(fā)送成功使兔。所以建钥,“可靠”傳輸是指在網(wǎng)絡(luò)基本正常的情況下數(shù)據(jù)收發(fā)必定成功,借用運(yùn)維里的術(shù)語虐沥,大概就是“3 個(gè) 9”或者“4 個(gè) 9”的程度吧熊经。
應(yīng)用層協(xié)議
第三個(gè)特點(diǎn),HTTP 協(xié)議是一個(gè)應(yīng)用層的協(xié)議置蜀。
這個(gè)特點(diǎn)也是不言自明的奈搜,但卻很重要。
在 TCP/IP 誕生后的幾十年里盯荤,雖然出現(xiàn)了許多的應(yīng)用層協(xié)議馋吗,但它們都僅關(guān)注很小的應(yīng)用領(lǐng)域,局限在很少的應(yīng)用場(chǎng)景秋秤。例如 FTP 只能傳輸文件宏粤、SMTP 只能發(fā)送郵件、SSH 只能遠(yuǎn)程登錄等灼卢,在通用的數(shù)據(jù)傳輸方面“完全不能打”绍哎。
所以 HTTP 憑借著可攜帶任意頭字段和實(shí)體數(shù)據(jù)的報(bào)文結(jié)構(gòu),以及連接控制鞋真、緩存代理等方便易用的特性崇堰,一出現(xiàn)就“技?jí)喝盒邸保杆俪蔀榱藨?yīng)用層里的“明星”協(xié)議。只要不太苛求性能海诲,HTTP 幾乎可以傳遞一切東西繁莹,滿足各種需求,稱得上是一個(gè)“萬能”的協(xié)議特幔。
套用一個(gè)網(wǎng)上流行的段子咨演,HTTP 完全可以用開玩笑的口吻說:“不要誤會(huì),我不是針對(duì) FTP蚯斯,我是說在座的應(yīng)用層各位薄风,都是垃圾∨那叮”
請(qǐng)求 - 應(yīng)答
第四個(gè)特點(diǎn)遭赂,HTTP 協(xié)議使用的是請(qǐng)求 - 應(yīng)答通信模式。
這個(gè)請(qǐng)求 - 應(yīng)答模式是 HTTP 協(xié)議最根本的通信模型撰茎,通俗來講就是“一發(fā)一收”“有來有去”嵌牺,就像是寫代碼時(shí)的函數(shù)調(diào)用,只要填好請(qǐng)求頭里的字段龄糊,“調(diào)用”后就會(huì)收到答復(fù)逆粹。
請(qǐng)求 - 應(yīng)答模式也明確了 HTTP 協(xié)議里通信雙方的定位,永遠(yuǎn)是請(qǐng)求方先發(fā)起連接和請(qǐng)求炫惩,是主動(dòng)的僻弹,而應(yīng)答方只有在收到請(qǐng)求后才能答復(fù),是被動(dòng)的他嚷,如果沒有請(qǐng)求時(shí)不會(huì)有任何動(dòng)作蹋绽。
當(dāng)然,請(qǐng)求方和應(yīng)答方的角色也不是絕對(duì)的筋蓖,在瀏覽器 - 服務(wù)器的場(chǎng)景里卸耘,通常服務(wù)器都是應(yīng)答方,但如果將它用作代理連接后端服務(wù)器粘咖,那么它就可能同時(shí)扮演請(qǐng)求方和應(yīng)答方的角色蚣抗。
HTTP 的請(qǐng)求 - 應(yīng)答模式也恰好契合了傳統(tǒng)的 C/S(Client/Server)系統(tǒng)架構(gòu),請(qǐng)求方作為客戶端瓮下、應(yīng)答方作為服務(wù)器翰铡。所以,隨著互聯(lián)網(wǎng)的發(fā)展就出現(xiàn)了 B/S(Browser/Server)架構(gòu)讽坏,用輕量級(jí)的瀏覽器代替笨重的客戶端應(yīng)用锭魔,實(shí)現(xiàn)零維護(hù)的“瘦”客戶端,而服務(wù)器則擯棄私有通信協(xié)議轉(zhuǎn)而使用 HTTP 協(xié)議路呜。
此外迷捧,請(qǐng)求 - 應(yīng)答模式也完全符合 RPC(Remote Procedure Call)的工作模式织咧,可以把 HTTP 請(qǐng)求處理封裝成遠(yuǎn)程函數(shù)調(diào)用,導(dǎo)致了 WebService漠秋、RESTful 和 gPRC 等的出現(xiàn)烦感。
無狀態(tài)
第五個(gè)特點(diǎn),HTTP 協(xié)議是無狀態(tài)的膛堤。
這個(gè)所謂的“狀態(tài)”應(yīng)該怎么理解呢?
“狀態(tài)”其實(shí)就是客戶端或者服務(wù)器里保存的一些數(shù)據(jù)或者標(biāo)志晌该,記錄了通信過程中的一些變化信息肥荔。
你一定知道,TCP 協(xié)議是有狀態(tài)的朝群,一開始處于 CLOSED 狀態(tài)燕耿,連接成功后是 ESTABLISHED 狀態(tài),斷開連接后是 FIN-WAIT 狀態(tài)姜胖,最后又是 CLOSED 狀態(tài)誉帅。
這些“狀態(tài)”就需要 TCP 在內(nèi)部用一些數(shù)據(jù)結(jié)構(gòu)去維護(hù),可以簡(jiǎn)單地想象成是個(gè)標(biāo)志量右莱,標(biāo)記當(dāng)前所處的狀態(tài)蚜锨,例如 0 是 CLOSED,2 是 ESTABLISHED 等等慢蜓。
再來看 HTTP亚再,那么對(duì)比一下 TCP 就看出來了,在整個(gè)協(xié)議里沒有規(guī)定任何的“狀態(tài)”晨抡,客戶端和服務(wù)器永遠(yuǎn)是處在一種“無知”的狀態(tài)氛悬。建立連接前兩者互不知情,每次收發(fā)的報(bào)文也都是互相獨(dú)立的耘柱,沒有任何的聯(lián)系如捅。收發(fā)報(bào)文也不會(huì)對(duì)客戶端或服務(wù)器產(chǎn)生任何影響,連接后也不會(huì)要求保存任何信息调煎。
“無狀態(tài)”形象地來說就是“沒有記憶能力”镜遣。比如,瀏覽器發(fā)了一個(gè)請(qǐng)求汛蝙,說“我是小明烈涮,請(qǐng)給我 A 文件〗呀#”坚洽,服務(wù)器收到報(bào)文后就會(huì)檢查一下權(quán)限,看小明確實(shí)可以訪問 A 文件西土,于是把文件發(fā)回給瀏覽器讶舰。接著瀏覽器還想要 B 文件,但服務(wù)器不會(huì)記錄剛才的請(qǐng)求狀態(tài),不知道第二個(gè)請(qǐng)求和第一個(gè)請(qǐng)求是同一個(gè)瀏覽器發(fā)來的跳昼,所以瀏覽器必須還得重復(fù)一次自己的身份才行:“我是剛才的小明般甲,請(qǐng)?jiān)俳o我 B 文件《旒眨”
我們可以再對(duì)比一下 UDP 協(xié)議敷存,不過它是無連接也無狀態(tài)的,順序發(fā)包亂序收包堪伍,數(shù)據(jù)包發(fā)出去后就不管了锚烦,收到后也不會(huì)順序整理。而 HTTP 是有連接無狀態(tài)帝雇,順序發(fā)包順序收包涮俄,按照收發(fā)的順序管理報(bào)文归苍。
但不要忘了 HTTP 是“靈活可擴(kuò)展”的球昨,雖然標(biāo)準(zhǔn)里沒有規(guī)定“狀態(tài)”,但完全能夠在協(xié)議的框架里給它“打個(gè)補(bǔ)丁”翻斟,增加這個(gè)特性吮廉。
其他特點(diǎn)
除了以上的五大特點(diǎn)苞尝,其實(shí) HTTP 協(xié)議還可以列出非常多的特點(diǎn),例如傳輸?shù)膶?shí)體數(shù)據(jù)可緩存可壓縮茧痕、可分段獲取數(shù)據(jù)野来、支持身份認(rèn)證、支持國際化語言等踪旷。但這些并不能算是 HTTP 的基本特點(diǎn)曼氛,因?yàn)檫@都是由第一個(gè)“靈活可擴(kuò)展”的特點(diǎn)所衍生出來的。
小結(jié)
HTTP 是靈活可擴(kuò)展的令野,可以任意添加頭字段實(shí)現(xiàn)任意功能舀患;
HTTP 是可靠傳輸協(xié)議,基于 TCP/IP 協(xié)議“盡量”保證數(shù)據(jù)的送達(dá)气破;
HTTP 是應(yīng)用層協(xié)議聊浅,比 FTP、SSH 等更通用功能更多现使,能夠傳輸任意數(shù)據(jù)低匙;
HTTP 使用了請(qǐng)求 - 應(yīng)答模式,客戶端主動(dòng)發(fā)起請(qǐng)求碳锈,服務(wù)器被動(dòng)回復(fù)請(qǐng)求顽冶;
HTTP 本質(zhì)上是無狀態(tài)的,每個(gè)請(qǐng)求都是互相獨(dú)立售碳、毫無關(guān)聯(lián)的强重,協(xié)議不要求客戶端或服務(wù)器記錄請(qǐng)求相關(guān)的信息绞呈。
HTTP的連接管理
HTTP 的連接管理也算得上是個(gè)“老生常談”的話題了,你一定曾經(jīng)聽說過“短連接”“長連接”之類的名詞间景,今天讓我們一起來把它們弄清楚佃声。
短連接
HTTP 協(xié)議最初(0.9/1.0)是個(gè)非常簡(jiǎn)單的協(xié)議,通信過程也采用了簡(jiǎn)單的“請(qǐng)求 - 應(yīng)答”方式倘要。
它底層的數(shù)據(jù)傳輸基于 TCP/IP圾亏,每次發(fā)送請(qǐng)求前需要先與服務(wù)器建立連接,收到響應(yīng)報(bào)文后會(huì)立即關(guān)閉連接封拧。
因?yàn)榭蛻舳伺c服務(wù)器的整個(gè)連接過程很短暫召嘶,不會(huì)與服務(wù)器保持長時(shí)間的連接狀態(tài),所以就被稱為“短連接”(short-lived connections)哮缺。早期的 HTTP 協(xié)議也被稱為是“無連接”的協(xié)議。
短連接的缺點(diǎn)相當(dāng)嚴(yán)重甲喝,因?yàn)樵?TCP 協(xié)議里尝苇,建立連接和關(guān)閉連接都是非常“昂貴”的操作埠胖。TCP 建立連接要有“三次握手”糠溜,發(fā)送 3 個(gè)數(shù)據(jù)包,需要 1 個(gè) RTT直撤;關(guān)閉連接是“四次揮手”非竿,4 個(gè)數(shù)據(jù)包需要 2 個(gè) RTT。
而 HTTP 的一次簡(jiǎn)單“請(qǐng)求 - 響應(yīng)”通常只需要 4 個(gè)包谋竖,如果不算服務(wù)器內(nèi)部的處理時(shí)間红柱,最多是 2 個(gè) RTT。這么算下來蓖乘,浪費(fèi)的時(shí)間就是“3÷5=60%”锤悄,有三分之二的時(shí)間被浪費(fèi)掉了,傳輸效率低得驚人嘉抒。
單純地從理論上講零聚,TCP 協(xié)議你可能還不太好理解,我就拿打卡考勤機(jī)來做個(gè)形象的比喻吧些侍。
假設(shè)你的公司買了一臺(tái)打卡機(jī)隶症,放在前臺(tái),因?yàn)檫@臺(tái)機(jī)器比較貴岗宣,所以專門做了一個(gè)保護(hù)罩蓋著它蚂会,公司要求每次上下班打卡時(shí)都要先打開蓋子,打卡后再蓋上蓋子狈定。
可是偏偏這個(gè)蓋子非常牢固颂龙,打開關(guān)閉要費(fèi)很大力氣习蓬,打卡可能只要 1 秒鐘,而開關(guān)蓋子卻需要四五秒鐘措嵌,大部分時(shí)間都浪費(fèi)在了毫無意義的開關(guān)蓋子操作上了躲叼。
可想而知,平常還好說企巢,一到上下班的點(diǎn)在打卡機(jī)前就會(huì)排起長隊(duì)枫慷,每個(gè)人都要重復(fù)“開蓋 - 打卡 - 關(guān)蓋”的三個(gè)步驟,你說著急不著急浪规。
在這個(gè)比喻里或听,打卡機(jī)就相當(dāng)于服務(wù)器,蓋子的開關(guān)就是 TCP 的連接與關(guān)閉笋婿,而每個(gè)打卡的人就是 HTTP 請(qǐng)求誉裆,很顯然,短連接的缺點(diǎn)嚴(yán)重制約了服務(wù)器的服務(wù)能力缸濒,導(dǎo)致它無法處理更多的請(qǐng)求足丢。
長連接
針對(duì)短連接暴露出的缺點(diǎn),HTTP 協(xié)議就提出了“長連接”的通信方式庇配,也叫“持久連接”(persistent connections)斩跌、“連接保活”(keep alive)捞慌、“連接復(fù)用”(connection reuse)耀鸦。
其實(shí)解決辦法也很簡(jiǎn)單,用的就是“成本均攤”的思路啸澡,既然 TCP 的連接和關(guān)閉非常耗時(shí)間袖订,那么就把這個(gè)時(shí)間成本由原來的一個(gè)“請(qǐng)求 - 應(yīng)答”均攤到多個(gè)“請(qǐng)求 - 應(yīng)答”上。
這樣雖然不能改善 TCP 的連接效率嗅虏,但基于“分母效應(yīng)”著角,每個(gè)“請(qǐng)求 - 應(yīng)答”的無效時(shí)間就會(huì)降低不少,整體傳輸效率也就提高了旋恼。
這里我畫了一個(gè)短連接與長連接的對(duì)比示意圖吏口。
在短連接里發(fā)送了三次 HTTP“請(qǐng)求 - 應(yīng)答”,每次都會(huì)浪費(fèi) 60% 的 RTT 時(shí)間冰更。而在長連接的情況下产徊,同樣發(fā)送三次請(qǐng)求,因?yàn)橹辉诘谝淮螘r(shí)建立連接蜀细,在最后一次時(shí)關(guān)閉連接舟铜,所以浪費(fèi)率就是“3÷9≈33%”,降低了差不多一半的時(shí)間損耗奠衔。顯然谆刨,如果在這個(gè)長連接上發(fā)送的請(qǐng)求越多塘娶,分母就越大,利用率也就越高痊夭。
繼續(xù)用剛才的打卡機(jī)的比喻刁岸,公司也覺得這種反復(fù)“開蓋 - 打卡 - 關(guān)蓋”的操作太“反人類”了,于是頒布了新規(guī)定她我,早上打開蓋子后就不用關(guān)上了虹曙,可以自由打卡,到下班后再關(guān)上蓋子番舆。
這樣打卡的效率(即服務(wù)能力)就大幅度提升了酝碳,原來一次打卡需要五六秒鐘,現(xiàn)在只要一秒就可以了恨狈,上下班時(shí)排長隊(duì)的景象一去不返疏哗,大家都開心。
連接相關(guān)的頭字段
由于長連接對(duì)性能的改善效果非常顯著禾怠,所以在 HTTP/1.1 中的連接都會(huì)默認(rèn)啟用長連接沃斤。不需要用什么特殊的頭字段指定,只要向服務(wù)器發(fā)送了第一次請(qǐng)求刃宵,后續(xù)的請(qǐng)求都會(huì)重復(fù)利用第一次打開的 TCP 連接,也就是長連接徘公,在這個(gè)連接上收發(fā)數(shù)據(jù)牲证。
當(dāng)然,我們也可以在請(qǐng)求頭里明確地要求使用長連接機(jī)制关面,使用的字段是 Connection坦袍,值是 “keep-alive”。
不過不管客戶端是否顯式要求長連接等太,如果服務(wù)器支持長連接捂齐,它總會(huì)在響應(yīng)報(bào)文里放一個(gè) “Connection: keep-alive” 字段,告訴客戶端:“我是支持長連接的缩抡,接下來就用這個(gè) TCP 一直收發(fā)數(shù)據(jù)吧”奠宜。
不過長連接也有一些小缺點(diǎn),問題就出在它的“長”字上瞻想。
因?yàn)?TCP 連接長時(shí)間不關(guān)閉压真,服務(wù)器必須在內(nèi)存里保存它的狀態(tài),這就占用了服務(wù)器的資源蘑险。如果有大量的空閑長連接只連不發(fā)滴肿,就會(huì)很快耗盡服務(wù)器的資源,導(dǎo)致服務(wù)器無法為真正有需要的用戶提供服務(wù)佃迄。
所以泼差,長連接也需要在恰當(dāng)?shù)臅r(shí)間關(guān)閉贵少,不能永遠(yuǎn)保持與服務(wù)器的連接,這在客戶端或者服務(wù)器都可以做到堆缘。
在客戶端滔灶,可以在請(qǐng)求頭里加上“Connection: close”字段,告訴服務(wù)器:“這次通信后就關(guān)閉連接”套啤。服務(wù)器看到這個(gè)字段宽气,就知道客戶端要主動(dòng)關(guān)閉連接,于是在響應(yīng)報(bào)文里也加上這個(gè)字段潜沦,發(fā)送之后就調(diào)用 Socket API 關(guān)閉 TCP 連接萄涯。
服務(wù)器端通常不會(huì)主動(dòng)關(guān)閉連接,但也可以使用一些策略唆鸡。拿 Nginx 來舉例涝影,它有兩種方式:
使用“keepalive_timeout”指令,設(shè)置長連接的超時(shí)時(shí)間争占,如果在一段時(shí)間內(nèi)連接上沒有任何數(shù)據(jù)收發(fā)就主動(dòng)斷開連接燃逻,避免空閑連接占用系統(tǒng)資源。
使用“keepalive_requests”指令臂痕,設(shè)置長連接上可發(fā)送的最大請(qǐng)求次數(shù)伯襟。比如設(shè)置成 1000,那么當(dāng) Nginx 在這個(gè)連接上處理了 1000 個(gè)請(qǐng)求后握童,也會(huì)主動(dòng)斷開連接姆怪。
另外,客戶端和服務(wù)器都可以在報(bào)文里附加通用頭字段“Keep-Alive: timeout=value”澡绩,限定長連接的超時(shí)時(shí)間稽揭。但這個(gè)字段的約束力并不強(qiáng),通信的雙方可能并不會(huì)遵守肥卡,所以不太常見溪掀。
隊(duì)頭阻塞
看完了短連接和長連接,接下來就要說到著名的“隊(duì)頭阻塞”(Head-of-line blocking步鉴,也叫“隊(duì)首阻塞”)了揪胃。
“隊(duì)頭阻塞”與短連接和長連接無關(guān),而是由 HTTP 基本的“請(qǐng)求 - 應(yīng)答”模型所導(dǎo)致的氛琢。
因?yàn)?HTTP 規(guī)定報(bào)文必須是“一發(fā)一收”只嚣,這就形成了一個(gè)先進(jìn)先出的“串行”隊(duì)列。隊(duì)列里的請(qǐng)求沒有輕重緩急的優(yōu)先級(jí)艺沼,只有入隊(duì)的先后順序册舞,排在最前面的請(qǐng)求被最優(yōu)先處理。
如果隊(duì)首的請(qǐng)求因?yàn)樘幚淼奶⒄`了時(shí)間障般,那么隊(duì)列里后面的所有請(qǐng)求也不得不跟著一起等待调鲸,結(jié)果就是其他的請(qǐng)求承擔(dān)了不應(yīng)有的時(shí)間成本盛杰。
還是用打卡機(jī)做個(gè)比喻。
上班的時(shí)間點(diǎn)上藐石,大家都在排隊(duì)打卡即供,可這個(gè)時(shí)候偏偏最前面的那個(gè)人遇到了打卡機(jī)故障,怎么也不能打卡成功于微,急得滿頭大汗逗嫡。等找人把打卡機(jī)修好,后面排隊(duì)的所有人全遲到了株依。
性能優(yōu)化
因?yàn)椤罢?qǐng)求 - 應(yīng)答”模型不能變驱证,所以“隊(duì)頭阻塞”問題在 HTTP/1.1 里無法解決,只能緩解恋腕,有什么辦法呢抹锄?
公司里可以再多買幾臺(tái)打卡機(jī)放在前臺(tái),這樣大家可以不用擠在一個(gè)隊(duì)伍里荠藤,分散打卡伙单,一個(gè)隊(duì)伍偶爾阻塞也不要緊,可以改換到其他不阻塞的隊(duì)伍哈肖。
這在 HTTP 里就是“并發(fā)連接”(concurrent connections)吻育,也就是同時(shí)對(duì)一個(gè)域名發(fā)起多個(gè)長連接,用數(shù)量來解決質(zhì)量的問題淤井。
但這種方式也存在缺陷布疼。如果每個(gè)客戶端都想自己快,建立很多個(gè)連接庄吼,用戶數(shù)×并發(fā)數(shù)就會(huì)是個(gè)天文數(shù)字。服務(wù)器的資源根本就扛不住严就,或者被服務(wù)器認(rèn)為是惡意攻擊总寻,反而會(huì)造成“拒絕服務(wù)”。
所以梢为,HTTP 協(xié)議建議客戶端使用并發(fā)渐行,但不能“濫用”并發(fā)。RFC2616 里明確限制每個(gè)客戶端最多并發(fā) 2 個(gè)連接铸董。不過實(shí)踐證明這個(gè)數(shù)字實(shí)在是太小了祟印,眾多瀏覽器都“無視”標(biāo)準(zhǔn),把這個(gè)上限提高到了 6~8粟害。后來修訂的 RFC7230 也就“順?biāo)浦邸痹桃洌∠诉@個(gè)“2”的限制。
但“并發(fā)連接”所壓榨出的性能也跟不上高速發(fā)展的互聯(lián)網(wǎng)無止境的需求悲幅,還有什么別的辦法嗎套鹅?
公司發(fā)展的太快了站蝠,員工越來越多,上下班打卡成了迫在眉睫的大問題卓鹿。前臺(tái)空間有限菱魔,放不下更多的打卡機(jī)了,怎么辦吟孙?那就多開幾個(gè)打卡的地方澜倦,每個(gè)樓層、辦公區(qū)的入口也放上三四臺(tái)打卡機(jī)杰妓,把人進(jìn)一步分流藻治,不要都往前臺(tái)擠。
這個(gè)就是“域名分片”(domain sharding)技術(shù)稚失,還是用數(shù)量來解決質(zhì)量的思路栋艳。
HTTP 協(xié)議和瀏覽器不是限制并發(fā)連接數(shù)量嗎?好句各,那我就多開幾個(gè)域名吸占,比如shard1.chrono.com、shard2.chrono.com凿宾,而這些域名都指向同一臺(tái)服務(wù)器www.chrono.com矾屯,這樣實(shí)際長連接的數(shù)量就又上去了,真是“美滋滋”初厚。不過實(shí)在是有點(diǎn)“上有政策件蚕,下有對(duì)策”的味道。
小結(jié)
這一講中我們學(xué)習(xí)了 HTTP 協(xié)議里的短連接和長連接产禾,簡(jiǎn)單小結(jié)一下今天的內(nèi)容:
早期的 HTTP 協(xié)議使用短連接排作,收到響應(yīng)后就立即關(guān)閉連接,效率很低亚情;
HTTP/1.1 默認(rèn)啟用長連接妄痪,在一個(gè)連接上收發(fā)多個(gè)請(qǐng)求響應(yīng),提高了傳輸效率楞件;
服務(wù)器會(huì)發(fā)送“Connection: keep-alive”字段表示啟用了長連接衫生;
報(bào)文頭里如果有“Connection: close”就意味著長連接即將關(guān)閉;
過多的長連接會(huì)占用服務(wù)器資源土浸,所以服務(wù)器會(huì)用一些策略有選擇地關(guān)閉長連接罪针;
“隊(duì)頭阻塞”問題會(huì)導(dǎo)致性能下降,可以用“并發(fā)連接”和“域名分片”技術(shù)緩解黄伊。
作者:易道云控
鏈接:http://www.reibang.com/p/58ac01ffda82
來源:簡(jiǎn)書
著作權(quán)歸作者所有泪酱。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。