長連接和短連接區(qū)別詳細(xì)解析

一個完整的軟件系統(tǒng)大多數(shù)情況下是由多個進(jìn)程共同協(xié)作進(jìn)行的价脾,哪怕它們在同一臺服務(wù)器上贱纠。所以伞访,進(jìn)程之間如何進(jìn)行高效的通信至關(guān)重要蝶涩。

單個應(yīng)用程序 + 單個數(shù)據(jù)庫這套基礎(chǔ)開發(fā)套餐我相信每個人都經(jīng)歷過,甚至在初期它們還有可能部署在同一臺服務(wù)器上绩蜻。既然應(yīng)用程序和數(shù)據(jù)庫分屬于兩個不同的進(jìn)程铣墨,所以這個問題本質(zhì)上還是兩個進(jìn)程之間的通信問題。

兩個進(jìn)程之間如果要通信办绝,很顯然必須要建立一個連接伊约,通過它來相互傳輸數(shù)據(jù)。原則上孕蝉,如果兩個進(jìn)程在同一臺服務(wù)器上屡律,有很多種方式可以進(jìn)行相互通信。不過在分布式系統(tǒng)中降淮,不同的進(jìn)程很多時候被部署在不同的服務(wù)器上超埋。所以我們這次只聊基于 TCP/IP 的通信方式,因為對大家來說這是最普遍會用到的方式佳鳖,不管是應(yīng)用程序間的遠(yuǎn)程調(diào)用(RPC)還是應(yīng)用程序與數(shù)據(jù)庫間的調(diào)用(DAL)霍殴,皆是如此。

通過套接字(socket)建立連接

socket 與 TCP/IP 之間是唇齒相依般的關(guān)系系吩,聯(lián)系緊密来庭,先來看下維基百科對 socket 的定義。

socket 是計算機(jī)網(wǎng)絡(luò)中用于在節(jié)點內(nèi)發(fā)送或接收數(shù)據(jù)的內(nèi)部端點穿挨。具體來說月弛,它是網(wǎng)絡(luò)軟件 (協(xié)議棧) 中這個端點的一種表示,包含通信協(xié)議絮蒿、目標(biāo)地址尊搬、狀態(tài)等,是系統(tǒng)資源的一種形式土涝。

它在網(wǎng)絡(luò)中所處的位置大致就是下面的黑色部分,應(yīng)用層與傳輸層之間幌墓。

image.png

其中的傳輸層就是 TCP/IP 所在的地方但壮,而你平時通過代碼編寫的應(yīng)用程序大多屬于應(yīng)用層范疇冀泻,socket 在這里起到就是連接應(yīng)用層與傳輸層的作用。

socket 的誕生是為了應(yīng)用程序能夠更方便的將數(shù)據(jù)經(jīng)由傳輸層來傳輸蜡饵,所以它本質(zhì)上就是對 TCP/IP 的運用進(jìn)行了一層封裝弹渔,然后應(yīng)用程序直接調(diào)用 socket API 即可進(jìn)行通信。那么它是如何工作的呢溯祸?它分為 2 個部分肢专,服務(wù)端需要建立 socket 來監(jiān)聽指定的地址,然后等待客戶端來連接焦辅。而客戶端則需要建立 socket 并與服務(wù)端的 socket 地址進(jìn)行連接博杖。

image.png

這圖展示的就是建立 TCP/IP 連接的過程,經(jīng)典的叫法為“三次握手”的過程筷登。顧名思義剃根,這個過程中來回產(chǎn)生了三次網(wǎng)絡(luò)通信。

接下來的數(shù)據(jù)傳輸過程就簡單很多前方,發(fā)送數(shù)據(jù)就是客戶端往服務(wù)端通信狈醉,服務(wù)端處理完之后的數(shù)據(jù)返回則相反。

image.png

值得注意的是惠险,傳輸?shù)倪^程涉及到數(shù)據(jù) Copy苗傅,不過這些 Copy 是必不可少的。其中的發(fā)送緩沖區(qū)和接收緩沖區(qū)就是套接字緩存 (socket buffer)班巩。

image.png

連接使用完之后需要關(guān)閉金吗,不過 TCP/IP 連接關(guān)閉過程比創(chuàng)建更復(fù)雜一些,次數(shù)多了一次趣竣,這就是經(jīng)典的“四次握手”過程摇庙。

簡單總結(jié)一下 socket。socket 是進(jìn)程間數(shù)據(jù)傳輸?shù)拿浇橐B疲瑸榱吮WC連接的可靠卫袒,你需要特別注意建立連接和關(guān)閉連接的過程。為了確保準(zhǔn)確单匣、完整的數(shù)據(jù)傳輸夕凝,客戶端和服務(wù)端來回進(jìn)行了多次網(wǎng)絡(luò)通信才得以完成連接的創(chuàng)建和關(guān)閉,這同時也是你在運用一個連接時所花費的額外成本户秤。

基于 socket 我們可以選擇建立長連接或者短連接码秉,在實際運用中兩者都有可能被用到。

長連接和短連接的區(qū)別

先帶你來認(rèn)識一下它倆的區(qū)別鸡号。

長連接意味著進(jìn)行一次數(shù)據(jù)傳輸后转砖,不關(guān)閉連接,長期保持連通狀態(tài)。如果兩個應(yīng)用程序之間有新的數(shù)據(jù)需要傳輸府蔗,則直接復(fù)用這個連接晋控,無需再建立一個新的連接。就像下圖這樣姓赤。

image.png

它的優(yōu)勢是在多次通信中可以省去連接建立和關(guān)閉連接的開銷赡译,并且從總體上來看,進(jìn)行多次數(shù)據(jù)傳輸?shù)目偤臅r更少不铆。缺點是需要花費額外的精力來保持這個連接一直是可用的蝌焚,因為網(wǎng)絡(luò)抖動、服務(wù)器故障等都會導(dǎo)致這個連接不可用誓斥,甚至是由于防火墻的原因只洒。所以,一般我們會通過下面這幾種方式來做“贬常活”工作红碑,確保連接在被使用的時候是可用狀態(tài):

  1. 利用 TCP 自身的保活(Keepalive)機(jī)制來實現(xiàn)泡垃,蔽錾海活機(jī)制會定時發(fā)送探測報文來識別對方是否可達(dá)。一般的默認(rèn)定時間隔是 2 小時蔑穴,你可以根據(jù)自己的需要在操作系統(tǒng)層面去調(diào)整這個間隔忠寻,不管是 Linux 還是 Windows 系統(tǒng)。
  2. 上層應(yīng)用主動的定時發(fā)送一個小數(shù)據(jù)包作為“心跳”存和,探測是否能成功送達(dá)到另外一端奕剃。 保活功能大多數(shù)情況下用于服務(wù)端探測客戶端的場景捐腿,一旦識別客戶端不可達(dá)纵朋,則斷開連接,緩解服務(wù)端壓力茄袖。

提前多說一句操软,如果在做了高可用的分布式系統(tǒng)場景中運用長連接會更麻煩一些。因為高可用必然包含自動故障轉(zhuǎn)移宪祥、故障隔離等機(jī)制聂薪。這恰恰導(dǎo)致了一旦發(fā)生故障,客戶端需要及時發(fā)現(xiàn)哪些連接已處于不可用狀態(tài)蝗羊,并進(jìn)行相應(yīng)的重連藏澳,包括重新做負(fù)載均衡等工作。

了解完了長連接耀找,那么短連接就很容易理解了翔悠。短連接意味著每一次的數(shù)據(jù)傳輸都需要建立一個新的連接,用完再馬上關(guān)閉它。下次再用的時候重新建立一個新的連接凉驻,如此反復(fù)腻要。

image.png

它的優(yōu)勢是由于每次使用的連接都是新建的复罐,所以基本上只要能夠建立連接涝登,數(shù)據(jù)就大概率能送達(dá)到對方。并且哪怕這次傳輸出現(xiàn)異常也不用擔(dān)心影響后續(xù)新的數(shù)據(jù)傳輸效诅,因為屆時又是一個新的連接胀滚。缺點是每個連接都需要經(jīng)過三次握手和四次握手的過程,耗時大大增加乱投。

另外咽笼,短連接還有一個致命的缺點。我們回到前面提到的維基百科對 socket 的定義戚炫,其中說到socket 包含通信協(xié)議剑刑、目標(biāo)地址、狀態(tài)等双肤。實際當(dāng)你在基于 socket 進(jìn)行開發(fā)的時候施掏,這些包含的具體資源主要就是這 5 個:源 IP、源端口茅糜、目的 IP七芭、目的端口、協(xié)議蔑赘,有個專業(yè)的叫法稱之為“五元組”狸驳。在一臺計算機(jī)上只要這五元組的值不重復(fù),那么連接就可以被建立缩赛。然而一臺計算機(jī)最多只能開啟 65535 個端口耙箍,如果現(xiàn)在兩個進(jìn)程之間需要通信,作為服務(wù)端的 IP 和端口必然是固定的酥馍,因此單個客戶端理論上最多只能與服務(wù)端同時建立 65535 個 socket 連接辩昆。如果除去操作系統(tǒng)和其它進(jìn)程所占用的端口,實際還會更少物喷。所以卤材,一旦使用不當(dāng),在很短的時間內(nèi)建立了大量連接峦失,端口很容易被占用完扇丛。這不但會導(dǎo)致自身無法正常工作,還會影響到同一臺計算機(jī)上的其它進(jìn)程尉辑。

我猜你在項目中大多數(shù)情況使用的是短連接的方式帆精,因為這對我們編程來說可以少考慮很多問題,潛在的這些缺點可能是你沒有遇到或者意識到而已。存在必有其價值卓练,接下去我們根據(jù)實際的案例讓你清楚知道如何來選擇它們。

長連接和短連接的選擇

我想你肯定見過一些監(jiān)控或者實時報價類系統(tǒng)襟企,比如股票軟件嘱么,它需要在幾秒之內(nèi)刷新最新的價格。像這種場景中同時包含了需要運用長連接的三個主要因素:高頻曼振、服務(wù)端主動推送和有狀態(tài)。

  • 高頻的原因我想你根據(jù)前面的內(nèi)容也明白了甲雅,因為頻次越高的話抛人,使用短連接帶來的建立連接和關(guān)閉連接的總開銷越大函匕。
  • 而服務(wù)端主動推送也需要長連接的原因是,由于服務(wù)端往往是“中心化”的掠剑,一般都是 1 個服務(wù)端為多個客戶端提供服務(wù)。所以例嘱,如果使用短連接的方式拼卵,那么在客戶端未主動連接到服務(wù)端的情況下腋腮,服務(wù)端并不知道需要往哪些客戶端去推送數(shù)據(jù)低葫,這是原因之一水泉。所以此時蟹漓,長連接成為了一個很好的選擇。另外一個原因是拾枣,哪怕客戶端通過定時的短連接輪詢方式進(jìn)行主動連接梅肤,除了增加了額外的建立連接和關(guān)閉連接的開銷外,還可能遇到通信完成后結(jié)果數(shù)據(jù)并未發(fā)生變化邑茄,做了無用功姨蝴。
  • 成熟股票軟件的服務(wù)端,為了支撐更多的用戶以及做高可用撩扒,必然部署了多臺似扔。但是這個業(yè)務(wù)場景吨些,用戶無法容忍由于多個服務(wù)端之間數(shù)據(jù)同步的誤差導(dǎo)致他在客戶端看到的價格刷新產(chǎn)生“回退”現(xiàn)象。所以炒辉,只能盡量保持一直連接在同一臺服務(wù)器上豪墅,才能避免這個情況。這種場景被稱之為“有狀態(tài)”黔寇,也可以理解為是“串行”的偶器,因為多次請求的前后需要保持“連續(xù)性”。

短連接則更適用于諸如閱讀類軟件的場景中缝裤,例如屏轰,很多時候用戶點開一篇文章后需要花一些時間進(jìn)行閱讀,這個時間有長有短憋飞,并且直到用戶下一次操作之前都沒有數(shù)據(jù)傳輸發(fā)生霎苗。這個場景中包含了運用短連接的兩個主要因素:低頻、無狀態(tài)榛做。

  • 因為低頻唁盏,所以更能容忍建立連接和關(guān)閉連接的開銷。
  • 用戶的下一次點擊往往跳轉(zhuǎn)到了其它文章检眯,并且新打開的與當(dāng)前文章并不需要具有“連續(xù)性”厘擂,所以這種場景我們稱之為“無狀態(tài)”的。另外锰瘸,理論上同一時刻打開幾篇文章也不會存在什么不妥刽严。

通過這兩個案例我們可以總結(jié)出一個決定何時運用長連接和短連接的最佳實踐。

長連接適用于:兩個進(jìn)程之間需要高頻通信并且具備服務(wù)端主動推送或者有狀態(tài)(需串行)兩者之一的場景避凝,否則并不是必選項舞萄。

短連接適用于:兩個進(jìn)程之間通信頻率較低,或者屬于無狀態(tài)(可并行)的場景恕曲,否則并不是必選項鹏氧。

其它情況就根據(jù)所需的側(cè)重點來,比如側(cè)重性能就長連接佩谣,側(cè)重編碼的便捷性就選擇短連接把还。

總結(jié)

至此,相信你應(yīng)該清楚了長連接和短連接在跨進(jìn)程通信中該如何選擇茸俭,而且還對通過 socket 建立 TCP 連接有了一定的認(rèn)識吊履。你在實際的工作中可能遇到的場景千奇百怪,只需要保持先識別所處場景的特點调鬓,再基于這些特點來作出選擇的習(xí)慣艇炎,必然至少是個不錯的決策。

不過有時候我們可能需要一個中庸的方案來作為默認(rèn)選擇腾窝,因為很多場景中的請求并不是平穩(wěn)的缀踪,甚至波動會較大居砖,而且可能同時存在有狀態(tài)和無狀態(tài)的場景,此時如果單方面的選擇長連接或者短連接都會產(chǎn)生較多的資源浪費驴娃。那么我們可以通過增加一些復(fù)雜度來實現(xiàn)一個能夠綜合長連接和短連接各自優(yōu)點的方案:建立多個長連接奏候,每次數(shù)據(jù)傳輸?shù)臅r候獨占使用,用完之后放回唇敞,再給后續(xù)使用蔗草。這種方案被稱之為“連接池”。例如, 很多的數(shù)據(jù)庫訪問框架都內(nèi)置了連接池機(jī)制疆柔,因為作為底層框架的它不知道會被使用到何種場景的系統(tǒng)中咒精,所以提供了這個選項。

連接池的運作流程大致如下圖旷档。除了上面所說的模叙,獨占使用,用完放回之外彬犯,一般都會在應(yīng)用程序啟動時預(yù)先建立好指定數(shù)據(jù)量的連接向楼,以更好應(yīng)對冷啟動后請求數(shù)快速上升帶來的資源競爭問題,這個數(shù)量一般稱之為最小連接數(shù)谐区。另外,如果新的請求進(jìn)來時逻卖,所有已建立的連接都在使用中宋列,但是連接數(shù)的上限未達(dá)到指定數(shù)量,可以再建立新的長連接來使用评也,用完依舊放回到空閑池炼杖,相當(dāng)于把連接池擴(kuò)大了,這個上限數(shù)量一般稱之為最大連接數(shù)盗迟。

image.png

轉(zhuǎn)載地址:https://cloud.tencent.com/developer/article/1470024

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坤邪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子罚缕,更是在濱河造成了極大的恐慌艇纺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邮弹,死亡現(xiàn)場離奇詭異黔衡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)腌乡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門盟劫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人与纽,你說我怎么就攤上這事侣签√磷埃” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵影所,是天一觀的道長氢哮。 經(jīng)常有香客問我,道長型檀,這世上最難降的妖魔是什么冗尤? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮胀溺,結(jié)果婚禮上裂七,老公的妹妹穿的比我還像新娘。我一直安慰自己仓坞,他們只是感情好背零,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著无埃,像睡著了一般徙瓶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嫉称,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天侦镇,我揣著相機(jī)與錄音,去河邊找鬼织阅。 笑死壳繁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荔棉。 我是一名探鬼主播闹炉,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼润樱!你這毒婦竟也來了渣触?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤壹若,失蹤者是張志新(化名)和其女友劉穎嗅钻,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舌稀,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡啊犬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了壁查。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片觉至。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖睡腿,靈堂內(nèi)的尸體忽然破棺而出语御,到底是詐尸還是另有隱情峻贮,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布应闯,位于F島的核電站纤控,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碉纺。R本人自食惡果不足惜船万,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骨田。 院中可真熱鬧耿导,春花似錦、人聲如沸态贤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悠汽。三九已至箱吕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柿冲,已是汗流浹背茬高。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留姻采,地道東北人雅采。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像慨亲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宝鼓,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容