你遇到過TIME_WAIT的問題嗎?
我相信很多都遇到過這個問題麻汰。一旦有用戶在喊:網(wǎng)絡(luò)變慢了狞膘。第一件事情就是,netstat -a | grep TIME_WAIT | wc -l一下什乙。哎呀媽呀挽封,幾千個TIME_WAIT.
然后,做的第一件事情就是:打開Google或者Bing臣镣,輸入關(guān)鍵詞:too many time wait辅愿。一定能找到解決方案,而排在最前面或者被很多人到處轉(zhuǎn)載的解決方案一定是:
打開sysctl.conf文件忆某,修改以下幾個參數(shù):
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
你也會被告知点待,開啟tw_recylce和tw_reuse一定需要timestamps的支持,而且這些配置一般不建議開啟弃舒,但是對解決TIME_WAIT很多的問題癞埠,有很好的用處状原。
接下來,你就直接修改了這幾個參數(shù)苗踪,reload一下颠区,發(fā)現(xiàn),咦通铲,沒幾分鐘毕莱,TIME_WAIT的數(shù)量真的降低了,也沒發(fā)現(xiàn)哪個用戶說有問題颅夺,然后就沒有然后了朋截。
做到這一步,相信50%或者更高比例的開發(fā)就已經(jīng)止步了吧黄。問題好像解決了部服,但是,要徹底理解并解決這個問題拗慨,可能就沒這么簡單廓八,或者說,還有很長的路要走胆描!
什么是TIME-WAIT和CLOSE-WAIT?
所謂,要解決問題仗阅,就要先理解問題昌讲。隨便改兩行代碼,發(fā)現(xiàn)bug”沒有了“减噪,也不是bug真的沒有了短绸,只是隱藏在更深的地方,你沒有發(fā)現(xiàn)筹裕,或者以你的知識水平醋闭,你無法發(fā)現(xiàn)而已。
大家知道朝卒,由于socket是全雙工的工作模式证逻,一個socket的關(guān)閉,是需要四次握手來完成的抗斤。
主動關(guān)閉連接的一方囚企,調(diào)用close();協(xié)議層發(fā)送FIN包
被動關(guān)閉的一方收到FIN包后,協(xié)議層回復(fù)ACK;然后被動關(guān)閉的一方厘肮,進入CLOSE_WAIT狀態(tài)前硫,主動關(guān)閉的一方等待對方關(guān)閉,則進入FIN_WAIT_2狀態(tài)典阵;此時疾宏,主動關(guān)閉的一方
等待
被動關(guān)閉一方的應(yīng)用程序后添,調(diào)用close操作
被動關(guān)閉的一方在完成所有數(shù)據(jù)發(fā)送后黍特,調(diào)用close()操作蛙讥;此時,協(xié)議層發(fā)送FIN包給主動關(guān)閉的一方衅澈,等待對方的ACK键菱,被動關(guān)閉的一方進入LAST_ACK狀態(tài);
主動關(guān)閉的一方收到FIN包今布,協(xié)議層回復(fù)ACK经备;此時,主動關(guān)閉連接的一方部默,進入TIME_WAIT狀態(tài)侵蒙;而被動關(guān)閉的一方,進入CLOSED狀態(tài)
等待2MSL時間傅蹂,主動關(guān)閉的一方纷闺,結(jié)束TIME_WAIT,進入CLOSED狀態(tài)
通過上面的一次socket關(guān)閉操作份蝴,你可以得出以下幾點:
主動關(guān)閉連接的一方–也就是主動調(diào)用socket的close操作的一方犁功,最終會進入TIME_WAIT狀態(tài)
被動關(guān)閉連接的一方,有一個中間狀態(tài)婚夫,即CLOSE_WAIT浸卦,因為協(xié)議層在等待上層的應(yīng)用程序,主動調(diào)用close操作后才主動關(guān)閉這條連接
TIME_WAIT會默認等待2MSL時間后案糙,才最終進入CLOSED狀態(tài)限嫌;
在一個連接沒有進入CLOSED狀態(tài)之前,這個連接是不能被重用的时捌!
所以怒医,這里憑你的直覺,TIME_WAIT并不可怕(not really奢讨,后面講)稚叹,CLOSE_WAIT才可怕,因為CLOSE_WAIT很多拿诸,表示說要么是你的應(yīng)用程序?qū)懙挠袉栴}入录,沒有合適的關(guān)閉socket;要么是說佳镜,你的服務(wù)器CPU處理不過來(CPU太忙)或者你的應(yīng)用程序一直睡眠到其它地方(鎖僚稿,或者文件I/O等等),你的應(yīng)用程序獲得不到合適的調(diào)度時間蟀伸,造成你的程序沒法真正的執(zhí)行close操作蚀同。
這里又出現(xiàn)兩個問題:
上文提到的連接重用缅刽,那連接到底是個什么概念?
協(xié)議層為什么要設(shè)計一個TIME_WAIT狀態(tài)蠢络?這個狀態(tài)為什么默認等待2MSL時間才會進入CLOSED
先解釋清楚這兩個問題衰猛,我們再來看,開頭提到的幾個網(wǎng)絡(luò)配置究竟有什么用刹孔,以及TIME_WAIT的后遺癥問題啡省。
Socket連接到底是個什么概念?
大家經(jīng)常提socket髓霞,那么卦睹,到底什么是一個socket?其實方库,socket就是一個
五元組结序,包括:
源IP
源端口
目的IP
目的端口
類型:TCP or UDP
這個五元組,即標識了一條可用的連接纵潦。注意徐鹤,有很多人把一個socket定義成四元組,也就是
源IP:源端口+目的IP:目的端口邀层,這個定義是不正確的返敬。
例如,如果你的本地出口IP是180.172.35.150寥院,那么你的瀏覽器在連接某一個Web服務(wù)器劲赠,例如百度的時候,這條socket連接的四元組可能就是:
[180.172.35.150:45678, tcp, 180.97.33.108:80]
源IP為你的出口IP地址180.172.35.150只磷,源端口為隨機端口45678经磅,目的IP為百度的某一個負載均衡服務(wù)器IP?180.97.33.108泌绣,端口為HTTP標準的80端口钮追。
如果這個時候,你再開一個瀏覽器阿迈,訪問百度元媚,將會產(chǎn)生一條新的連接:
[180.172.35.150:43678, tcp, 180.97.33.108:80]
這條新的連接的源端口為一個新的隨機端口43678。
如此來看苗沧,如果你的本機需要壓測百度刊棕,那么,你最多可以創(chuàng)建多少個連接呢待逞?我在文章《云思路|輕松構(gòu)建千萬級投票系統(tǒng)》里也稍微提過這個問題甥角,沒有閱讀過本文的,可以發(fā)送“投票系統(tǒng)“閱讀识樱。
第二個問題嗤无,TIME_WAIT有什么用震束?
如果我們來做個類比的話,TIME_WAIT的出現(xiàn)当犯,對應(yīng)的是你的程序里的異常處理垢村,它的出現(xiàn),就是為了解決網(wǎng)絡(luò)的丟包和網(wǎng)絡(luò)不穩(wěn)定所帶來的其他問題:
第一嚎卫,防止前一個連接【五元組嘉栓,我們繼續(xù)以180.172.35.150:45678, tcp, 180.97.33.108:80為例】上延遲的數(shù)據(jù)包或者丟失重傳的數(shù)據(jù)包,被后面復(fù)用的連接【前一個連接關(guān)閉后拓诸,此時你再次訪問百度侵佃,新的連接可能還是由180.172.35.150:45678, tcp, 180.97.33.108:80這個五元組來表示,也就是源端口湊巧還是45678】錯誤的接收(異常:數(shù)據(jù)丟了恰响,或者傳輸太慢了)趣钱,參見下圖:
SEQ=3的數(shù)據(jù)包丟失,重傳第一次胚宦,沒有得到ACK確認
如果沒有TIME_WAIT首有,或者TIME_WAIT時間非常端,那么關(guān)閉的連接【180.172.35.150:45678, tcp, 180.97.33.108:80的狀態(tài)變?yōu)榱薈LOSED枢劝,源端口可被再次利用】井联,馬上被重用【對180.97.33.108:80新建的連接,復(fù)用了之前的隨機端口45678】您旁,并連續(xù)發(fā)送SEQ=1,2的數(shù)據(jù)包
此時烙常,前面的連接上的SEQ=3的數(shù)據(jù)包再次重傳,同時鹤盒,seq的序號剛好也是3(這個很重要蚕脏,不然,SEQ的序號對不上侦锯,就會RST掉)驼鞭,此時,前面一個連接上的數(shù)據(jù)被后面的一個連接錯誤的接收
第二尺碰,確保連接方能在時間范圍內(nèi)挣棕,關(guān)閉自己的連接。其實亲桥,也是因為丟包造成的洛心,參見下圖:
主動關(guān)閉方關(guān)閉了連接,發(fā)送了FIN题篷;
被動關(guān)閉方回復(fù)ACK同時也執(zhí)行關(guān)閉動作词身,發(fā)送FIN包;此時番枚,被動關(guān)閉的一方進入LAST_ACK狀態(tài)
主動關(guān)閉的一方回去了ACK法严,主動關(guān)閉一方進入TIME_WAIT狀態(tài)璧瞬;
但是最后的ACK丟失,被動關(guān)閉的一方還繼續(xù)停留在LAST_ACK狀態(tài)
此時渐夸,如果沒有TIME_WAIT的存在嗤锉,或者說,停留在TIME_WAIT上的時間很短墓塌,則主動關(guān)閉的一方很快就進入了CLOSED狀態(tài)瘟忱,也即是說,如果此時新建一個連接苫幢,源隨機端口如果被復(fù)用访诱,在connect發(fā)送SYN包后,由于被動方仍認為這條連接【五元組】還在等待ACK韩肝,但是卻收到了SYN触菜,則被動方會回復(fù)RST
造成主動創(chuàng)建連接的一方,由于收到了RST哀峻,則連接無法成功
所以涡相,你看到了,TIME_WAIT的存在是很重要的剩蟀,如果強制忽略TIME_WAIT催蝗,還是有很高的機率,造成數(shù)據(jù)粗亂育特,或者短暫性的連接失敗丙号。
那么,為什么說缰冤,TIME_WAIT狀態(tài)會是持續(xù)2MSL(2倍的max segment lifetime)呢犬缨?這個時間可以通過修改內(nèi)核參數(shù)調(diào)整嗎?第一棉浸,這個2MSL怀薛,是RFC 793里定義的,參見RFC的截圖標紅的部分:
這個定義涮拗,更多的是一種保障(IP數(shù)據(jù)包里的TTL乾戏,即數(shù)據(jù)最多存活的跳數(shù)迂苛,真正反應(yīng)的才是數(shù)據(jù)在網(wǎng)絡(luò)上的存活時間)三热,確保最后丟失了ACK,被動關(guān)閉的一方再次重發(fā)FIN并等待回復(fù)的ACK三幻,一來一去兩個來回就漾。內(nèi)核里,寫死了這個MSL的時間為:30秒(有讀者提醒念搬,RFC里建議的MSL其實是2分鐘抑堡,但是很多實現(xiàn)都是30秒)摆出,所以TIME_WAIT的即為1分鐘:
所以,再次回想一下前面的問題首妖,如果一條連接偎漫,即使在四次握手關(guān)閉了,由于TIME_WAIT的存在有缆,這個連接象踊,在1分鐘之內(nèi),也無法再次被復(fù)用棚壁,那么杯矩,如果你用一臺機器做壓測的客戶端,你一分鐘能發(fā)送多少并發(fā)連接請求袖外?如果這臺是一個負載均衡服務(wù)器史隆,一臺負載均衡服務(wù)器,一分鐘可以有多少個連接同時訪問后端的服務(wù)器呢曼验?
TIME_WAIT很多泌射,可怕嗎?
如果你通過ss -tan state time-wait | wc -l發(fā)現(xiàn)鬓照,系統(tǒng)中有很多TIME_WAIT魄幕,很多人都會緊張。多少算多呢颖杏?幾百幾千纯陨?如果是這個量級,其實真的沒必要緊張留储。第一翼抠,這個量級,因為TIME_WAIT所占用的內(nèi)存很少很少获讳;因為記錄和尋找可用的local port所消耗的CPU也基本可以忽略阴颖。
會占用內(nèi)存嗎?當然丐膝!任何你可以看到的數(shù)據(jù)量愧,內(nèi)核里都需要有相關(guān)的數(shù)據(jù)結(jié)構(gòu)來保存這個數(shù)據(jù)啊。一條Socket處于TIME_WAIT狀態(tài)帅矗,它也是一條“存在“的socket偎肃,內(nèi)核里也需要有保持它的數(shù)據(jù):
內(nèi)核里有保存所有連接的一個hash table,這個hash table里面既包含TIME_WAIT狀態(tài)的連接浑此,也包含其他狀態(tài)的連接累颂。主要用于有新的數(shù)據(jù)到來的時候,從這個hash table里快速找到這條連接。不同的內(nèi)核對這個hash table的大小設(shè)置不同紊馏,你可以通過dmesg命令去找到你的內(nèi)核設(shè)置的大辛霞ⅰ:
還有一個hash table用來保存所有的bound ports,主要用于可以快速的找到一個可用的端口或者隨機端口:
由于內(nèi)核需要保存這些數(shù)據(jù)朱监,必然岸啡,會占用一定的內(nèi)存。
會消耗CPU嗎赫编?當然凰狞!每次找到一個隨機端口,還是需要遍歷一遍bound ports的吧沛慢,這必然需要一些CPU時間赡若。
TIME_WAIT很多,既占內(nèi)存又消耗CPU团甲,這也是為什么很多人逾冬,看到TIME_WAIT很多,就蠢蠢欲動的想去干掉他們躺苦。其實身腻,如果你再進一步去研究,1萬條TIME_WAIT的連接匹厘,也就多消耗1M左右的內(nèi)存嘀趟,對現(xiàn)代的很多服務(wù)器,已經(jīng)不算什么了愈诚。至于CPU她按,能減少它當然更好,但是不至于因為1萬多個hash item就擔憂炕柔。
如果酌泰,你真的想去調(diào)優(yōu),還是需要搞清楚別人的調(diào)優(yōu)建議匕累,以及調(diào)優(yōu)參數(shù)背后的意義陵刹!
TIME_WAIT調(diào)優(yōu),你必須理解的幾個調(diào)優(yōu)參數(shù)
在具體的圖例之前欢嘿,我們還是先解析一下相關(guān)的幾個參數(shù)存在的意義衰琐。
net.ipv4.tcp_timestamps
RFC 1323在TCP?Reliability一節(jié)里,引入了timestamp的TCP option炼蹦,兩個4字節(jié)的時間戳字段羡宙,其中第一個4字節(jié)字段用來保存發(fā)送該數(shù)據(jù)包的時間,第二個4字節(jié)字段用來保存最近一次接收對方發(fā)送到數(shù)據(jù)的時間框弛。有了這兩個時間字段辛辨,也就有了后續(xù)優(yōu)化的余地捕捂。
tcp_tw_reuse和tcp_tw_recycle就依賴這些時間字段瑟枫。
net.ipv4.tcp_tw_reuse
字面意思斗搞,reuse TIME_WAIT狀態(tài)的連接。
時刻記住一條socket連接慷妙,就是那個五元組僻焚,出現(xiàn)TIME_WAIT狀態(tài)的連接,一定出現(xiàn)在主動關(guān)閉連接的一方膝擂。所以虑啤,當主動關(guān)閉連接的一方,再次向?qū)Ψ桨l(fā)起連接請求的時候(例如架馋,客戶端關(guān)閉連接狞山,客戶端再次連接服務(wù)端,此時可以復(fù)用了叉寂;負載均衡服務(wù)器萍启,主動關(guān)閉后端的連接,當有新的HTTP請求屏鳍,負載均衡服務(wù)器再次連接后端服務(wù)器勘纯,此時也可以復(fù)用),可以復(fù)用TIME_WAIT狀態(tài)的連接钓瞭。
通過字面解釋驳遵,以及例子說明,你看到了山涡,tcp_tw_reuse應(yīng)用的場景:某一方,需要不斷的通過“短連接“連接其他服務(wù)器鸭丛,總是自己先關(guān)閉連接(TIME_WAIT在自己這方)霍殴,關(guān)閉后又不斷的重新連接對方。
那么来庭,當連接被復(fù)用了之后,延遲或者重發(fā)的數(shù)據(jù)包到達,新的連接怎么判斷章母,到達的數(shù)據(jù)是屬于復(fù)用后的連接蚪缀,還是復(fù)用前的連接呢哩盲?那就需要依賴前面提到的兩個時間字段了。復(fù)用連接后眨猎,這條連接的時間被更新為當前的時間,當延遲的數(shù)據(jù)達到,延遲數(shù)據(jù)的時間是小于新連接的時間鳄乏,所以蝌焚,內(nèi)核可以通過時間判斷出毕谴,延遲的數(shù)據(jù)可以安全的丟棄掉了核偿。
這個配置诚欠,依賴于連接雙方,同時對timestamps的支持漾岳。同時聂薪,這個配置,僅僅影響outbound連接蝗羊,即做為客戶端的角色藏澳,連接服務(wù)端[connect(dest_ip, dest_port)]時復(fù)用TIME_WAIT的socket。
net.ipv4.tcp_tw_recycle
字面意思耀找,銷毀掉TIME_WAIT翔悠。
當開啟了這個配置后业崖,內(nèi)核會快速的回收處于TIME_WAIT狀態(tài)的socket連接。多快蓄愁?不再是2MSL双炕,而是一個RTO(retransmission timeout,數(shù)據(jù)包重傳的timeout時間)的時間撮抓,這個時間根據(jù)RTT動態(tài)計算出來妇斤,但是遠小于2MSL。
有了這個配置丹拯,還是需要保障
丟失重傳或者延遲的數(shù)據(jù)包站超,不會被新的連接(注意,這里不再是復(fù)用了乖酬,而是之前處于TIME_WAIT狀態(tài)的連接已經(jīng)被destroy掉了死相,新的連接,剛好是和某一個被destroy掉的連接使用了相同的五元組而已)所錯誤的接收咬像。在啟用該配置算撮,當一個socket連接進入TIME_WAIT狀態(tài)后,內(nèi)核里會記錄包括該socket連接對應(yīng)的五元組中的對方IP等在內(nèi)的一些統(tǒng)計數(shù)據(jù)县昂,當然也包括從該對方IP所接收到的最近的一次數(shù)據(jù)包時間肮柜。當有新的數(shù)據(jù)包到達倒彰,只要時間晚于內(nèi)核記錄的這個時間狸驳,數(shù)據(jù)包都會被統(tǒng)統(tǒng)的丟掉撰糠。
這個配置,依賴于連接雙方對timestamps的支持。同時辉词,這個配置敷搪,主要影響到了inbound的連接(對outbound的連接也有影響,但是不是復(fù)用),即做為服務(wù)端角色,客戶端連進來映胁,服務(wù)端主動關(guān)閉了連接抛人,TIME_WAIT狀態(tài)的socket處于服務(wù)端,服務(wù)端快速的回收該狀態(tài)的連接。
由此,如果客戶端處于NAT的網(wǎng)絡(luò)(多個客戶端,同一個IP出口的網(wǎng)絡(luò)環(huán)境)臼隔,如果配置了tw_recycle,就可能在一個RTO的時間內(nèi)例嘱,只能有一個客戶端和自己連接成功(不同的客戶端發(fā)包的時間不一致,造成服務(wù)端直接把數(shù)據(jù)包丟棄掉)。
我盡量嘗試用文字解釋清楚即寡,但是著蟹,來點案例和圖示奸披,應(yīng)該有助于我們徹底理解洪鸭。
我們來看這樣一個網(wǎng)絡(luò)情況:
客戶端IP地址為:180.172.35.150,我們可以認為是瀏覽器
負載均衡有兩個IP,外網(wǎng)IP地址為115.29.253.156,內(nèi)網(wǎng)地址為10.162.74.10;外網(wǎng)地址監(jiān)聽80端口
負載均衡背后有兩臺Web服務(wù)器同木,一臺IP地址為10.162.74.43洲尊,監(jiān)聽80端口惊来;另一臺為10.162.74.44,監(jiān)聽80端口
Web服務(wù)器會連接數(shù)據(jù)服務(wù)器厘擂,IP地址為10.162.74.45昆淡,監(jiān)聽3306端口
這種簡單的架構(gòu)下锰瘸,我們來看看刽严,在不同的情況下,我們今天談?wù)摰膖w_reuse/tw_recycle對網(wǎng)絡(luò)連接的影響避凝。
先做個假定:
客戶端通過HTTP/1.1連接負載均衡舞萄,也就是說,HTTP協(xié)議投Connection為keep-alive管削,所以我們假定倒脓,客戶端
對
負載均衡服務(wù)器
的socket連接,客戶端會斷開連接含思,所以崎弃,TIME_WAIT出現(xiàn)在客戶端
Web服務(wù)器和MySQL服務(wù)器的連接,我們假定含潘,Web服務(wù)器上的程序在連接結(jié)束的時候饲做,調(diào)用close操作關(guān)閉socket資源連接,所以遏弱,TIME_WAIT出現(xiàn)在Web服務(wù)器端盆均。
那么,在這種假定下:
Web服務(wù)器上漱逸,肯定可以配置開啟的配置:tcp_tw_reuse泪姨;如果Web服務(wù)器有很多連向DB服務(wù)器的連接游沿,可以保證socket連接的復(fù)用。
那么肮砾,負載均衡服務(wù)器和Web服務(wù)器诀黍,誰先關(guān)閉連接,則決定了我們怎么配置tcp_tw_reuse/tcp_tw_recycle了
方案一:負載均衡服務(wù)器
首先關(guān)閉連接
在這種情況下仗处,因為負載均衡服務(wù)器對Web服務(wù)器的連接蔗草,TIME_WAIT大都出現(xiàn)在負載均衡服務(wù)器上,所以疆柔,在負載均衡服務(wù)器上的配置:
net.ipv4.tcp_tw_reuse = 1 //盡量復(fù)用連接
net.ipv4.tcp_tw_recycle = 0 //不能保證客戶端不在NAT的網(wǎng)絡(luò)啊
在Web服務(wù)器上的配置為:
net.ipv4.tcp_tw_reuse = 1 //這個配置主要影響的是Web服務(wù)器到DB服務(wù)器的連接復(fù)用
net.ipv4.tcp_tw_recycle:
設(shè)置成1和0都沒有任何意義咒精。想一想,在負載均衡和它的連接中旷档,它是服務(wù)端模叙,但是TIME_WAIT出現(xiàn)在負載均衡服務(wù)器上;它和DB的連接鞋屈,它是客戶端范咨,recycle對它并沒有什么影響,關(guān)鍵是reuse
方案二:Web服務(wù)器首先關(guān)閉來自負載均衡服務(wù)器的連接
在這種情況下厂庇,Web服務(wù)器變成TIME_WAIT的重災(zāi)區(qū)渠啊。負載均衡對Web服務(wù)器的連接,由Web服務(wù)器首先關(guān)閉連接权旷,TIME_WAIT出現(xiàn)在Web服務(wù)器上替蛉;Web服務(wù)器對DB服務(wù)器的連接,由Web服務(wù)器關(guān)閉連接拄氯,TIME_WAIT也出現(xiàn)在它身上躲查,此時,負載均衡服務(wù)器上的配置:
net.ipv4.tcp_tw_reuse:0或者1都行译柏,都沒有實際意義
net.ipv4.tcp_tw_recycle=0 //一定是關(guān)閉recycle
在Web服務(wù)器上的配置:
net.ipv4.tcp_tw_reuse = 1 //這個配置主要影響的是Web服務(wù)器到DB服務(wù)器的連接復(fù)用
net.ipv4.tcp_tw_recycle=1 //由于在負載均衡和Web服務(wù)器之間并沒有NAT的網(wǎng)絡(luò)镣煮,可以考慮開啟recycle,加速由于負載均衡和Web服務(wù)器之間的連接造成的大量TIME_WAIT
回答幾個大家提到的幾個問題
1.請問我們所說連接池可以復(fù)用連接鄙麦,是不是意味著典唇,需要等到上個連接time wait結(jié)束后才能再次使用?
所謂連接池復(fù)用,復(fù)用的一定是活躍的連接胯府,所謂活躍介衔,第一表明連接池里的連接都是ESTABLISHED的,第二盟劫,連接池做為上層應(yīng)用夜牡,會有定時的心跳去保持連接的活躍性。既然連接都是活躍的,那就不存在有TIME_WAIT的概念了塘装,在上篇里也有提到急迂,TIME_WAIT是在主動關(guān)閉連接的一方,在關(guān)閉連接后才進入的狀態(tài)蹦肴。既然已經(jīng)關(guān)閉了僚碎,那么這條連接肯定已經(jīng)不在連接池里面了,即被連接池釋放了阴幌。
2.想請問下勺阐,作為負載均衡的機器隨機端口使用完的情況下大量time_wait,不調(diào)整你文字里說的那三個參數(shù)矛双,有其他的更好的方案嗎渊抽?
第一,隨機端口使用完议忽,你可以通過調(diào)整/etc/sysctl.conf下的net.ipv4.ip_local_port_range配置懒闷,至少修改成net.ipv4.ip_local_port_range=1024 65535,保證你的負載均衡服務(wù)器至少可以使用6萬個隨機端口栈幸,也即可以有6萬的反向代理到后端的連接愤估,可以支持每秒1000的并發(fā)(想一想,因為TIME_WAIT狀態(tài)會持續(xù)1分鐘后消失速址,所以一分鐘最多有6萬玩焰,每秒1000);如果這么多端口都使用完了芍锚,也證明你應(yīng)該加服務(wù)器了昔园,或者,你的負載均衡服務(wù)器需要配置多個IP地址闹炉,或者蒿赢,你的后端服務(wù)器需要監(jiān)聽更多的端口和配置更多的IP(想一下socket的五元組)
第二,大量的TIME_WAIT渣触,多大量?如果是幾千個壹若,其實不用擔心嗅钻,因為這個內(nèi)存和CPU的消耗有一些,但是是可以忽略的店展。
第三养篓,如果真的量很大,上萬上萬的那種赂蕴,可以考慮柳弄,讓后端的服務(wù)器主動關(guān)閉連接,如果后端服務(wù)器沒有外網(wǎng)的連接只有負載均衡服務(wù)器的連接(主要是沒有NAT網(wǎng)絡(luò)的連接),可以在后端服務(wù)器上配置tw_recycle碧注,然后同時嚣伐,在負載均衡服務(wù)器上,配置tw_reuse萍丐。
3.如果想深入的學(xué)習(xí)一下網(wǎng)絡(luò)方面的知識轩端,有什么推薦的?
學(xué)習(xí)網(wǎng)絡(luò)比學(xué)一門編程語言“難“很多逝变。所謂難基茵,其實,是因為需要花很多的時間投入壳影。我自己不算精通拱层,只能說入門和理解⊙邕郑基本書可以推薦:《TCP/IP協(xié)議詳解》舱呻,必讀;《TCP/IP高效編程:改善網(wǎng)絡(luò)程序的44個技巧》悠汽,必讀箱吕;《Unix環(huán)境高級編程》,必讀柿冲;《Unix網(wǎng)絡(luò)編程:卷一》茬高,我只讀過卷一;另外假抄,還需要熟悉一下網(wǎng)絡(luò)工具怎栽,tcpdump以及wireshark,我的notes里有一個一站式學(xué)習(xí)Wireshark:https://github.com/dafang/notebook/issues/114宿饱,也值得一讀熏瞄。有了這些積累,可能就是一些實踐以及碎片化的學(xué)習(xí)和積累了谬以。
寫在最后
這篇文章我斷斷續(xù)續(xù)寫了兩天强饮,內(nèi)容找了多個地方去驗證,包括看到Vincent Bernat的一篇文章以及Vincent在多個地方和別人的討論为黎。期間邮丰,我也花了一些時間和Vincent探討了幾個我沒在tcp源碼里翻找到的有疑問的地方。
我力求比散布在網(wǎng)上的文章做到準確并盡量整理的清晰一些铭乾。但是剪廉,也難免會
有疏漏或者有錯誤的地方,高手看到可以隨時指正炕檩,并和我討論斗蒋,大家一起研究!
感謝您閱讀。