關(guān)于網(wǎng)絡(luò)連接CLOSE_WAIT狀態(tài)的問題

問題背景

在開發(fā)網(wǎng)絡(luò)服務(wù)器應(yīng)用系統(tǒng)的時(shí)候炸裆,有時(shí)會(huì)碰到服務(wù)器有大量的socket處于CLOSE_WAIT狀態(tài)娜搂,也無法關(guān)閉薛闪,導(dǎo)致服務(wù)器無法接受新的用戶請求辛馆,最終導(dǎo)致服務(wù)器奔潰,系統(tǒng)重啟才能解決豁延。

為什么會(huì)出現(xiàn)大量的CLOSE_WAIT狀態(tài)呢昙篙?

要解決這個(gè)問題,我們得先介紹一下socket斷開過程中的四次揮手术浪。

終止TCP連接的四次揮手

由于TCP連接是全雙工的瓢对,因此每個(gè)方向都必須單獨(dú)進(jìn)行關(guān)閉。
假設(shè)終止命令由client端發(fā)起胰苏。

image.png

當(dāng)clien端傳輸完成數(shù)據(jù)硕蛹,或者需要斷開連接時(shí):

  1. Client端發(fā)送一個(gè)FIN報(bào)文給Server端。(序號(hào)為M)
    1.1. 表示要終止Client到Server這個(gè)方向的連接硕并。
    1.1. 通過調(diào)用close(socket) API法焰。
    1.3 表示Client不再會(huì)發(fā)送數(shù)據(jù)到Server端。(但Server還能繼續(xù)發(fā)給Client端)
    1.4 Client狀態(tài)變?yōu)镕IN_WAIT_1
  2. Server端收到FIN后倔毙,發(fā)送一個(gè)ACK報(bào)文給Client端埃仪。(序號(hào)為M+1)
    2.1 Server狀態(tài)變?yōu)镃LOSE_WAIT
    2.2 Client收到序號(hào)為(M+1)的ACK后狀態(tài)變?yōu)镕IN_WAIT_2
    。陕赃。卵蛉。
  3. Server端也發(fā)送一個(gè)FIN報(bào)文給Client端。(序號(hào)為N)
    3.1 表示Server也要終止到Client端這個(gè)方向的連接么库。
    3.2. 通過調(diào)用close(socket) API傻丝。
    3.3 Server端狀態(tài)變?yōu)長AST_ACK
  4. Client端收到報(bào)文FIN后,也發(fā)送一個(gè)ACK報(bào)文給服務(wù)器诉儒。(序號(hào)N+1)
    4.1 Client狀態(tài)變?yōu)門IME_WAIT
  5. Server端收到序號(hào)為(N+1)的ACK
    5.1 Server的狀態(tài)變?yōu)镃LOSED.
  6. 等帶2MSL之后
    6.1 Client的狀態(tài)也變?yōu)镃LOSE.
  7. 至此葡缰,一個(gè)完整的TCP連接就關(guān)閉了。

兩個(gè)基本問題:

  1. Q: 我們看到CLOSE_WAIT出現(xiàn)在什么時(shí)候呢忱反?
    A: 在Sever端收到Client的FIN消息之后泛释。
  2. Q: 狀態(tài)CLOSE_WAIT在什么時(shí)候轉(zhuǎn)換成下一個(gè)狀態(tài)呢?
    A: 在Server端向Client發(fā)送FIN消息之后温算。

至此似乎明白了為什么會(huì)出現(xiàn)CLOSE_WAIT的狀態(tài):如果Server端一直沒有向client端發(fā)送FIN消息(調(diào)用close() API)怜校,那么這個(gè)CLOSE_WAIT會(huì)一直存在下去。

原因分析

從上面我們看到出現(xiàn)CLOSE_WAIT注竿,說明Server端沒有發(fā)起close()操作韭畸,這基本上是用戶server端程序的問題了宇智;通常情況下蔓搞,Server都是等待Client訪問胰丁,如果Client退出請求關(guān)閉連接,server端自覺close()對(duì)應(yīng)的連接喂分。

當(dāng)然這也可能是業(yè)務(wù)實(shí)現(xiàn)上的需要锦庸,暫時(shí)不發(fā)送FIN,因?yàn)榉?wù)器可能還有數(shù)據(jù)要發(fā)往客戶端蒲祈,等發(fā)送完所有應(yīng)用數(shù)據(jù)最后再發(fā)送FIN消息了甘萧;這個(gè)場景并不是這里我們討論的大量COLSE_WAIT的問題了,因?yàn)檫@個(gè)還是可控的梆掸。

我們要討論的場景是什么扬卷?我們先介紹兩個(gè)系統(tǒng)調(diào)用,前面也提到并且用到的close(socket)和shutdown(socket,HOW)接著往下分析酸钦。

我們知道一個(gè)進(jìn)程打開一個(gè)socket怪得,然后此進(jìn)程fork出子進(jìn)程的時(shí)候,父進(jìn)程已打開的socket是會(huì)被繼承的卑硫,即子進(jìn)程能夠繼續(xù)訪問這個(gè)socket徒恋。其結(jié)果就是,一個(gè)socket被兩個(gè)進(jìn)程打開欢伏,一個(gè)父進(jìn)程和一個(gè)子進(jìn)程入挣,此時(shí)socket的引用計(jì)數(shù)會(huì)變成2。

  • 調(diào)用close(socket)時(shí)硝拧,內(nèi)核先檢查socket上的引用計(jì)數(shù)器:如果引用計(jì)數(shù)大于1径筏,那么將這個(gè)引用計(jì)數(shù)減1,然后直接返回障陶。如果引用計(jì)數(shù)等于1滋恬,那么內(nèi)核才會(huì)真正關(guān)閉此socket。(通過發(fā)送FIN到對(duì)端來關(guān)閉TCP連接)
  • 調(diào)用shutdown(socket咸这,HOW)時(shí)夷恍,內(nèi)核不會(huì)檢查此socket對(duì)應(yīng)的引用計(jì)數(shù)器,直接向?qū)Χ税l(fā)送FIN來關(guān)閉TCP連接媳维。

據(jù)此分析酿雪,很大可能性是用戶服務(wù)器的程序?qū)崿F(xiàn)有問題導(dǎo)致的大量CLOSE_WAIT的socket,比如父進(jìn)程打開了socket侄刽,然后通過fork出子進(jìn)程來處理業(yè)務(wù)指黎,父進(jìn)程繼續(xù)對(duì)網(wǎng)絡(luò)請求進(jìn)行監(jiān)聽,永遠(yuǎn)不會(huì)終止州丹;當(dāng)客戶端發(fā)FIN過來的時(shí)候醋安,處理業(yè)務(wù)的子進(jìn)程處理此FIN消息杂彭,調(diào)用close()對(duì)本端進(jìn)行關(guān)閉,然而這個(gè)close()調(diào)用只是把socket的引用計(jì)數(shù)器減1吓揪,因?yàn)楦高M(jìn)程還在運(yùn)行亲怠,socket并沒關(guān)閉,這樣就導(dǎo)致系統(tǒng)中又多了一個(gè)CLOSE_WAIT的socket柠辞,長此以往团秽,就這樣了。

關(guān)于TIME_WAIT狀態(tài)

多說兩句關(guān)于TIME_WAIT的狀態(tài)叭首,這個(gè)發(fā)生在client端习勤,而且是不可避免的,其時(shí)間長度是固定的2MSL焙格,到期自動(dòng)轉(zhuǎn)為CLOSED图毕,不會(huì)導(dǎo)致系統(tǒng)資源耗盡的問題。

MSL是一個(gè)系統(tǒng)級(jí)參數(shù)眷唉,可調(diào)予颤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市厢破,隨后出現(xiàn)的幾起案子荣瑟,更是在濱河造成了極大的恐慌,老刑警劉巖摩泪,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笆焰,死亡現(xiàn)場離奇詭異,居然都是意外死亡见坑,警方通過查閱死者的電腦和手機(jī)嚷掠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荞驴,“玉大人不皆,你說我怎么就攤上這事⌒苈ィ” “怎么了霹娄?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鲫骗。 經(jīng)常有香客問我犬耻,道長,這世上最難降的妖魔是什么执泰? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任枕磁,我火速辦了婚禮,結(jié)果婚禮上术吝,老公的妹妹穿的比我還像新娘计济。我一直安慰自己茸苇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布沦寂。 她就那樣靜靜地躺著学密,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凑队。 梳的紋絲不亂的頭發(fā)上则果,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音漩氨,去河邊找鬼。 笑死遗增,一個(gè)胖子當(dāng)著我的面吹牛叫惊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播做修,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼霍狰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饰及?” 一聲冷哼從身側(cè)響起蔗坯,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎燎含,沒想到半個(gè)月后宾濒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屏箍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年绘梦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赴魁。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卸奉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颖御,到底是詐尸還是另有隱情榄棵,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布潘拱,位于F島的核電站疹鳄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏泽铛。R本人自食惡果不足惜尚辑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盔腔。 院中可真熱鬧杠茬,春花似錦月褥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栓票,卻和暖如春决左,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背走贪。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工佛猛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坠狡。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓继找,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逃沿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子婴渡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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