客户端产生CLOSE WAIT状态的解决方案
現(xiàn)象
生產(chǎn)環(huán)境和測(cè)試環(huán)境都發(fā)現(xiàn)有個(gè)外圍應(yīng)用通過(guò)搜索服務(wù)調(diào)用搜索引擎時(shí),偶爾會(huì)出現(xiàn)大量的訪問(wèn)超時(shí)的問(wèn)題,通過(guò)如下方式進(jìn)行分析排查:
l?首先是拿到搜索服務(wù)的JavaCore,發(fā)現(xiàn)其堵在HttpClient的發(fā)送上面,被堵的連接有數(shù)百個(gè),原因是不能夠從連接池中獲取到連接;
l?首先想到的就是連接池沒(méi)有釋放,檢查代碼,也確實(shí)存在著一些調(diào)用沒(méi)有釋放連接,特別是在異常的情況下,針對(duì)這一部分代碼進(jìn)行修復(fù)后,可是一段時(shí)間之后還是出現(xiàn)了訪問(wèn)超時(shí)的問(wèn)題;
l?考慮到這個(gè)外圍應(yīng)用的訪問(wèn)現(xiàn)出問(wèn)題的時(shí)候,其它的外圍應(yīng)用調(diào)用搜索服務(wù)是沒(méi)有問(wèn)題的,因此確定當(dāng)前搜索服務(wù)還沒(méi)有掛;
l?不同的外圍應(yīng)用可能調(diào)用的后臺(tái)搜索引擎是不一樣的,難道是該外圍應(yīng)用對(duì)應(yīng)的搜索引擎出現(xiàn)了問(wèn)題?不過(guò)經(jīng)過(guò)對(duì)該搜索引擎進(jìn)行分析,該搜索引擎本身是正常的,但是有一個(gè)奇怪的現(xiàn)象,在外圍應(yīng)用調(diào)用搜索服務(wù)發(fā)生超時(shí)時(shí),搜索引擎本身沒(méi)有接受到任何請(qǐng)求;
l?也就是說(shuō)經(jīng)搜索服務(wù)的請(qǐng)求都沒(méi)有提交到該搜索引擎上,難道是搜索服務(wù)與該搜索引擎之間的連接有問(wèn)題?通過(guò)網(wǎng)絡(luò)排查,使用Ping和Telnet進(jìn)行正向和反向確定,從搜索服務(wù)和搜索引擎之間的網(wǎng)絡(luò)是正常的,且端口也可以正常訪問(wèn);
l?再回到搜索服務(wù)所在的服務(wù)器,通過(guò)netstat一看,發(fā)現(xiàn)有400個(gè)CLOSE_WAIT與該搜索引擎相關(guān)的連接,這個(gè)數(shù)字恰好是應(yīng)用中設(shè)置的單個(gè)Route所能夠連接的最大連接數(shù)。
?
分析到此,問(wèn)題就明朗了,HttpClient連接池的中創(chuàng)建連接數(shù)已經(jīng)達(dá)到了最大數(shù)字,不能夠創(chuàng)建新的連接了,已經(jīng)創(chuàng)建的連接都是在等待關(guān)閉(CLOSE_WAIT)的狀態(tài),沒(méi)有被放回到可用的連接池中,不能夠用于處理新的連接請(qǐng)求,因而所有的請(qǐng)求都是堵在了從連接池中獲取連接哪里。
要解決這個(gè)問(wèn)題,首先需要知道CLOSE_WAIT產(chǎn)生的原因,才能夠解決該問(wèn)題,或者減少該問(wèn)題的發(fā)生。
TCP連接關(guān)閉時(shí)需要四次握手才能夠完成,如下圖所示:
?
產(chǎn)生CLOSE_WAIT狀態(tài)的一方,是屬于被動(dòng)關(guān)閉的一方,用簡(jiǎn)單的話對(duì)解釋上圖(主動(dòng)關(guān)閉方為A,被動(dòng)關(guān)閉方為B):
| A發(fā)一條FIN(關(guān)閉)請(qǐng)求給B,說(shuō)我要關(guān)閉了; B回應(yīng)一條ACK(確認(rèn))請(qǐng)求給A,說(shuō)我知道了,你關(guān)吧,此時(shí)B就會(huì)進(jìn)行CLOSE_WAIT狀態(tài); B發(fā)送一條FIN(關(guān)閉)請(qǐng)給A,說(shuō)我要關(guān)閉了; A收到發(fā)送一條ACK(確認(rèn))消息說(shuō),你關(guān)閉吧。 ? |
上面四次握手完成后,雙方的連接就都關(guān)閉了,但是這里在客戶端產(chǎn)生了CLOSE_WAIT現(xiàn)象,首先可以確定的是服務(wù)端主動(dòng)關(guān)閉的連接,且客戶端沒(méi)有給服務(wù)端發(fā)送關(guān)閉的請(qǐng)求(第三次握手請(qǐng)求),就會(huì)一直處在CLOSE_WAIT的狀態(tài),可是客戶端為什么不向服務(wù)端發(fā)送關(guān)閉的請(qǐng)求,它當(dāng)時(shí)在忙什么呢,難道應(yīng)用在關(guān)閉前有哪么多事情要做?還有就是為什么服務(wù)會(huì)主動(dòng)關(guān)掉客戶端的這么多連接?
有人說(shuō)這可能是服務(wù)端在調(diào)用關(guān)閉時(shí),而客戶端正在執(zhí)行RECV(數(shù)據(jù)接收),這時(shí)候有可能服務(wù)端發(fā)送的FIN包客戶端接收出錯(cuò),就是由TCP代回了一個(gè)ACK包,所以客戶端就會(huì)處在CLOSE_WAIT的狀態(tài)中,因而建議判斷RECV時(shí)是否出錯(cuò),如果出錯(cuò)就主動(dòng)關(guān)閉連接,這樣就可以防止沒(méi)有接收到FIN包。
也有人說(shuō)這是由于客戶端請(qǐng)求服務(wù)端時(shí),超時(shí)就有可能出現(xiàn)這種情況,我對(duì)這種情況做了實(shí)驗(yàn),分別啟動(dòng)了客戶端和服務(wù)端,在服務(wù)端中暴露一個(gè)超時(shí)的服務(wù)接口,在客戶端中通過(guò)POST的方式調(diào)用,然后再通過(guò)第三方工具調(diào)用客戶端去調(diào)用服務(wù)端的超時(shí)接口,測(cè)試分別在Linux以及Windows平臺(tái)進(jìn)行了測(cè)試,可是經(jīng)過(guò)100萬(wàn)個(gè)連接超時(shí)的請(qǐng)求后,客戶端沒(méi)有出現(xiàn)CLOSE-WAIT的現(xiàn)象,只有服務(wù)端才出現(xiàn)了CLOSE-WAIT,并且都會(huì)正常的關(guān)閉。
我們嘗試過(guò)優(yōu)化Linux中TCP連接參數(shù),減少TCP的連接時(shí)間以及增加連接的可用性,如下:
| sysctl?-w?net.ipv4.tcp_timestamps=0? sysctl?-w?net.ipv4.tcp_tw_reuse=1? sysctl?-w?net.ipv4.tcp_tw_recycle=1? sysctl?-w?net.ipv4.tcp_fin_timeout=30? sysctl?-w?net.ipv4.tcp_keepalive_time=1800? sysctl?-w?net.ipv4.tcp_rmem="4096?87380?8388608"? sysctl?-w?net.ipv4.tcp_wmem="4096?87380?8388608"? sysctl?-w?net.ipv4.tcp_max_syn_backlog=4096? |
也優(yōu)化了HttpClient的參數(shù),可是客戶端還是會(huì)出現(xiàn)CLOSE_WAIT的情況,且搜索引擎是使用惠普的Autonomy,閉源的不好入手優(yōu)化,最后還是通過(guò)在客戶端實(shí)現(xiàn)定時(shí)任務(wù)定期檢查當(dāng)前連接中狀態(tài)為leased(拿走但沒(méi)有返回aviable可用隊(duì)列中的連接)的連接的數(shù)量,檢測(cè)到該這種連接的數(shù)量超過(guò)一定數(shù)量后,就關(guān)閉該連接池,釋放所有連接,然后重新初使化該連接池,就可以解決這種問(wèn)題了,經(jīng)過(guò)測(cè)試這種試是可行的。不過(guò)曾經(jīng)考慮到這種方式比較暴力,連可用的連接都給關(guān)閉了,本想只關(guān)閉那些長(zhǎng)久未釋放的連接,不過(guò)由于連接池沒(méi)有暴露操作方法,通過(guò)反射可以獲取到池中的連接,不過(guò)由于關(guān)聯(lián)資源較多,操作麻煩,最后沒(méi)有采用這種方式。
再分享一下我老師大神的人工智能教程吧。零基礎(chǔ)!通俗易懂!風(fēng)趣幽默!還帶黃段子!希望你也加入到我們?nèi)斯ぶ悄艿年?duì)伍中來(lái)!https://blog.csdn.net/jiangjunshow
轉(zhuǎn)載于:https://www.cnblogs.com/skiwdhwhssh/p/10295807.html
總結(jié)
以上是生活随笔為你收集整理的客户端产生CLOSE WAIT状态的解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 好货日报邀请码54321软件的操作逻辑
- 下一篇: 用户及用户组管理(week1_day4)