*轉(zhuǎn)載,本人學(xué)習(xí)用理朋,侵刪
1.以前的誤解
很久之前就聽說過長連接的說法絮识,而且還知道HTTP1.0協(xié)議不支持長連接,從HTTP1.1協(xié)議以后嗽上,連接默認(rèn)都是長連接次舌。但終究覺得對于長連接一直懵懵懂懂的,有種抓不到關(guān)鍵點的感覺兽愤。
今天通過一番研究彼念,終于明白了這其中的奧秘。而之前浅萧,也看過長連接相關(guān)的內(nèi)容逐沙,但一直都是云里霧里的。這次之所以能在這么短的時間里搞清楚洼畅,和自己技術(shù)的沉淀密不可分吩案。因此,這里借著這個機會帝簇,再次強調(diào)一下徘郭,千萬不要試圖去研究你研究了很久都整不明白的東西,或許是你的層次不到丧肴,也或許是你從未在實際的應(yīng)用場景接觸過残揉,這種情況下你去研究,只會事倍功半芋浮,徒勞一番罷了抱环。
回到正題,既然說是誤解,那么的誤解到底是什么镇草?
那就是一直認(rèn)為眶痰,HTTP連接分為長連接和短連接,而我們現(xiàn)在常用的都是HTTP1.1陶夜,因此我們用的都是長連接凛驮。
這句話其實只對了一半,我們現(xiàn)如今的HTTP協(xié)議条辟,大部分都是1.1的黔夭,因此我們平時用的基本上都是長連接。但是前半句是不對的羽嫡,HTTP協(xié)議根本沒有長短連接這一說本姥,也正因為誤解了這個,導(dǎo)致對于長連接一直不明不白杭棵,始終不得其要領(lǐng)婚惫,具體下面一段會說到。
網(wǎng)絡(luò)上很多文章都是誤人子弟魂爪,根本沒有說明白這個概念先舷。這里要強調(diào)一下,HTTP協(xié)議是基于請求/響應(yīng)模式的滓侍,因此只要服務(wù)端給了響應(yīng)蒋川,本次HTTP連接就結(jié)束了,或者更準(zhǔn)確的說撩笆,是本次HTTP請求就結(jié)束了捺球,根本沒有長連接這一說。那么自然也就沒有短連接這一說了夕冲。
之所以網(wǎng)絡(luò)上說HTTP分為長連接和短連接氮兵,其實本質(zhì)上是說的TCP連接。TCP連接是一個雙向的通道歹鱼,它是可以保持一段時間不關(guān)閉的泣栈,因此TCP連接才有真正的長連接和短連接這一說。
其實知道了以后醉冤,會覺得這很好理解秩霍。HTTP協(xié)議說到底是應(yīng)用層的協(xié)議,而TCP才是真正的傳輸層協(xié)議蚁阳,只有負(fù)責(zé)傳輸?shù)倪@一層才需要建立連接。
一個形象的例子就是鸽照,拿你在網(wǎng)上購物來說螺捐,HTTP協(xié)議是指的那個快遞單,你寄件的時候填的單子就像是發(fā)了一個HTTP請求,等貨物運到地方了定血,快遞員會根據(jù)你發(fā)的請求把貨物送給相應(yīng)的收貨人赔癌。而TCP協(xié)議就是中間運貨的那個大貨車,也可能是火車或者飛機澜沟,但不管是什么灾票,它是負(fù)責(zé)運輸?shù)模虼吮仨氁新访K洌还苁堑厣线€是天上刊苍。那么這個路就是所謂的TCP連接,也就是一個雙向的數(shù)據(jù)通道濒析。
因此正什,LZ現(xiàn)在甚至覺得,“HTTP連接”這個詞就不應(yīng)該出現(xiàn)号杏,它只是一個應(yīng)用層的協(xié)議婴氮,根本就沒有所謂的連接這一說,就像FTP也是應(yīng)用層的協(xié)議盾致,但是你有聽說過FTP連接嗎主经?(恩,好像是聽過庭惜,-_-罩驻,但你現(xiàn)在知道了,其實所謂的FTP連接蜈块,嚴(yán)格來說鉴腻,依舊是TCP連接)
實際上,說HTTP請求和HTTP響應(yīng)會更準(zhǔn)確一些百揭,而HTTP請求和HTTP響應(yīng)爽哎,都是通過TCP連接這個通道來回傳輸?shù)摹?/p>
不管怎么說,一定要務(wù)必記住器一,長連接是指的TCP連接课锌,而不是HTTP連接。
一個疑問
之前LZ一直對一件事有些模糊不清祈秕,首先是怎么樣就算是把HTTP變成長連接了渺贤,是不是只要設(shè)置Connection為keep-alive就算是了?
如果是的話请毛,那都說HTTP1.1默認(rèn)是長連接志鞍,而觀察我們平時開發(fā)的Web應(yīng)用的HTTP頭部,Connection也確實是keep-alive方仿,那就是說我們大部分都是用的長連接固棚,但是長連接不是一般用于交互比較頻繁的應(yīng)用嗎统翩?像我們這種普通的Web應(yīng)用,比如博客園這種此洲,或者我的個人博客這種厂汗,長連接有什么用?
如果有用那用處到底是什么呜师,我們又不是客戶端與服務(wù)器交互頻繁的那種應(yīng)用(畢竟你打開網(wǎng)頁肯定要半天才打開另外一個吧)娶桦,如果沒用的話,那到底應(yīng)不應(yīng)該把Connection為keep-alive這個header值給改掉汁汗,從而改成短連接衷畦?
這個疑問,在LZ明白了長連接其實是指的TCP連接之后碰酝,基本上就明白了霎匈。而這個疑問,也正是LZ在“以前的誤解”那一段所提到的送爸,那個因為誤解導(dǎo)致LZ一直搞不明白的問題铛嘱。
為什么解決了上面那個誤解之后,前面所說的這些疑問LZ都明白了袭厂?
因為長連接意味著連接會被復(fù)用墨吓,畢竟一直保持著連接不就是為了重復(fù)使用嘛。但如果長連接是指的HTTP的話纹磺,那就是說HTTP連接可以被重復(fù)利用帖烘,這個話聽起來就感覺很別扭。之所以覺得別扭橄杨,其實就是LZ的一種直覺秘症,沒什么理論依據(jù)。而這種別扭的根源就在于式矫,之前一直沒有融會貫通的感覺乡摹,所以總感覺缺少點什么。不過這點疑惑采转,并沒有影響LZ的工作聪廉,因此也就沒深究過。
但現(xiàn)在好了故慈,明白了長連接實際上是指的TCP連接板熊,LZ瞬間自己就想明白了上面的那些問題。
第一個問題是察绷,是不是只要設(shè)置Connection為keep-alive就算是長連接了干签?
當(dāng)然是的,但要服務(wù)器和客戶端都設(shè)置拆撼。
第二個問題是筒严,我們平時用的是不是長連接丹泉?
這個也毫無疑問情萤,當(dāng)然是的鸭蛙。(現(xiàn)在用的基本上都是HTTP1.1協(xié)議,你觀察一下就會發(fā)現(xiàn)筋岛,基本上Connection都是keep-alive娶视。而且HTTP協(xié)議文檔上也提到了,HTTP1.1默認(rèn)是長連接睁宰,也就是默認(rèn)Connection的值就是keep-alive)
第三個問題肪获,也是LZ之前最想不明白的問題,那就是我們這種普通的Web應(yīng)用(比如博客園柒傻,我的個人博客這種)用長連接有啥好處孝赫?需不需要關(guān)掉長連接而使用短連接?
這個問題LZ現(xiàn)在終于明白了红符,問題的答案是好處還是有的青柄。
好處是什么?
首先预侯,剛才已經(jīng)說了致开,長連接是為了復(fù)用,這個在之前LZ就明白萎馅。那既然長連接是指的TCP連接双戳,也就是說復(fù)用的是TCP連接。那這就很好解釋了糜芳,也就是說飒货,長連接情況下,多個HTTP請求可以復(fù)用同一個TCP連接峭竣,這就節(jié)省了很多TCP連接建立和斷開的消耗塘辅。
比如你請求了博客園的一個網(wǎng)頁,這個網(wǎng)頁里肯定還包含了CSS邪驮、JS等等一系列資源莫辨,如果你是短連接(也就是每次都要重新建立TCP連接)的話,那你每打開一個網(wǎng)頁毅访,基本要建立幾個甚至幾十個TCP連接沮榜,這浪費了多少資源就不用LZ去說了吧。
但如果是長連接的話喻粹,那么這么多次HTTP請求(這些請求包括請求網(wǎng)頁內(nèi)容蟆融,CSS文件,JS文件守呜,圖片等等),其實使用的都是一個TCP連接椎例,很顯然是可以節(jié)省很多消耗的拾给。
這樣一解釋,就很明白了郁竟,不知道大家看了這些解釋感覺如何,反正LZ在自己想明白以后由境,有種豁然開朗的感覺棚亩。
另外,最后關(guān)于長連接還要多提一句虏杰,那就是讥蟆,長連接并不是永久連接的。如果一段時間內(nèi)(具體的時間長短纺阔,是可以在header當(dāng)中進行設(shè)置的瘸彤,也就是所謂的超時時間),這個連接沒有HTTP請求發(fā)出的話笛钝,那么這個長連接就會被斷掉质况。
這一點其實很容易理解,否則的話婆翔,TCP連接將會越來越多拯杠,直到把服務(wù)器的TCP連接數(shù)量撐爆到上限為止。現(xiàn)在想想啃奴,對于服務(wù)器來說潭陪,服務(wù)器里的這些個長連接其實很有數(shù)據(jù)庫連接池的味道,大家都是為了節(jié)省連接重復(fù)利用嘛最蕾,對不對依溯?
長輪詢和短輪詢
前面基本上LZ已經(jīng)把長短連接說的差不多了,接下來說說長短輪詢瘟则,今天也正是為了研究長短輪詢黎炉,LZ才順便研究了下長短連接這回事。
短輪詢相信大家都不難理解醋拧,比如你現(xiàn)在要做一個電商中商品詳情的頁面慷嗜,這個詳情界面中有一個字段是庫存量(相信這個大家都不陌生,隨便打開淘寶或者京東都能找到這種頁面)丹壕。而這個庫存量需要實時的變化庆械,保持和服務(wù)器里實際的庫存一致。
這個時候菌赖,你會怎么做缭乘?
最簡單的一種方式,就是你用JS寫個死循環(huán)琉用,不停的去請求服務(wù)器中的庫存量是多少堕绩,然后刷新到這個頁面當(dāng)中策幼,這其實就是所謂的短輪詢。
這種方式有明顯的壞處奴紧,那就是你很浪費服務(wù)器和客戶端的資源特姐。客戶端還好點绰寞,現(xiàn)在PC機配置高了到逊,你不停的請求還不至于把用戶的電腦整死,但是服務(wù)器就很蛋疼了滤钱。如果有1000個人停留在某個商品詳情頁面,那就是說會有1000個客戶端不停的去請求服務(wù)器獲取庫存量脑题,這顯然是不合理的件缸。
那怎么辦呢?
長輪詢這個時候就出現(xiàn)了叔遂,其實長輪詢和短輪詢最大的區(qū)別是他炊,短輪詢?nèi)シ?wù)端查詢的時候,不管庫存量有沒有變化已艰,服務(wù)器就立即返回結(jié)果了痊末。而長輪詢則不是,在長輪詢中哩掺,服務(wù)器如果檢測到庫存量沒有變化的話凿叠,將會把當(dāng)前請求掛起一段時間(這個時間也叫作超時時間,一般是幾十秒)嚼吞。在這個時間里盒件,服務(wù)器會去檢測庫存量有沒有變化,檢測到變化就立即返回舱禽,否則就一直等到超時為止炒刁。
而對于客戶端來說,不管是長輪詢還是短輪詢誊稚,客戶端的動作都是一樣的翔始,就是不停的去請求,不同的是服務(wù)端里伯,短輪詢情況下服務(wù)端每次請求不管有沒有變化都會立即返回結(jié)果城瞎,而長輪詢情況下,如果有變化才會立即返回結(jié)果俏脊,而沒有變化的話全谤,則不會再立即給客戶端返回結(jié)果,直到超時為止爷贫。
這樣一來认然,客戶端的請求次數(shù)將會大量減少(這也就意味著節(jié)省了網(wǎng)絡(luò)流量补憾,畢竟每次發(fā)請求,都會占用客戶端的上傳流量和服務(wù)端的下載流量)卷员,而且也解決了服務(wù)端一直疲于接受請求的窘境盈匾。
但是長輪詢也是有壞處的,因為把請求掛起同樣會導(dǎo)致資源的浪費毕骡,假設(shè)還是1000個人停留在某個商品詳情頁面削饵,那就很有可能服務(wù)器這邊掛著1000個線程,在不停檢測庫存量未巫,這依然是有問題的窿撬。
因此,從這里可以看出叙凡,不管是長輪詢還是短輪詢劈伴,都不太適用于客戶端數(shù)量太多的情況,因為每個服務(wù)器所能承載的TCP連接數(shù)是有上限的握爷,這種輪詢很容易把連接數(shù)頂滿跛璧。之所以舉這個例子,只是因為大家肯定都會網(wǎng)購新啼,所以這個例子比較通俗一點追城。
哪怕輪詢解決不了獲取庫存這個問題,但只要大家明白了長短輪詢的區(qū)別燥撞,這就足夠了座柱。實際上,據(jù)LZ自己平日里購物的觀察叨吮,那個庫存量應(yīng)該是不會變的辆布,這個例子純屬LZ個人的意淫,-_-茶鉴。
長短輪詢和長短連接的區(qū)別
這里簡單說一下它們的區(qū)別锋玲,LZ這里只說最根本的區(qū)別。
第一個區(qū)別是決定的方式涵叮,一個TCP連接是否為長連接惭蹂,是通過設(shè)置HTTP的Connection Header來決定的,而且是需要兩邊都設(shè)置才有效割粮。而一種輪詢方式是否為長輪詢盾碗,是根據(jù)服務(wù)端的處理方式來決定的,與客戶端沒有關(guān)系舀瓢。
第二個區(qū)別就是實現(xiàn)的方式廷雅,連接的長短是通過協(xié)議來規(guī)定和實現(xiàn)的。而輪詢的長短,是服務(wù)器通過編程的方式手動掛起請求來實現(xiàn)的航缀。
作者:熊師傅
鏈接:http://www.reibang.com/p/3fc3646fad80
來源:簡書
簡書著作權(quán)歸作者所有商架,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。