網(wǎng)絡連接存在大量time_wait和close_wait的原因以及解決方法
如果對tcp中的握手揮手不了解的同學,請先看這篇博客:《關于三次握手與四次揮手你要知道這些》。

四次揮手過程:
第一次揮手:主機A(可以是客戶端,也可以是服務器端),設置Sequence Number和Acknowledgment Number,向主機B發(fā)送一個FIN報文段;此時,主機A進入FIN_WAIT_1狀態(tài);這表示主機A沒有數(shù)據(jù)要發(fā)送給主機B了。
第二次揮手:主機B收到了主機A發(fā)送的FIN報文段,向主機A回一個ACK報文段,Acknowledgment Number為Sequence Number加1,主機A進入FIN_WAIT_2狀態(tài);主機B告訴主機A,我也沒有數(shù)據(jù)要發(fā)送了,可以進行關閉連接了。
第三次揮手:主機B向主機A發(fā)送FIN報文段,請求關閉連接,同時主機B進入CLOSE_WAIT狀態(tài)。
第四次揮手:主機A收到主機B發(fā)送的FIN報文段,向主機B發(fā)送ACK報文段,然后主機A進入TIME_WAIT狀態(tài);主機B收到主機A的ACK報文段以后,就關閉連接;此時,主機A等待2MSL后依然沒有收到回復,則證明主機B已正常關閉,那好,主機A也可以關閉連接了。
大量time_wait
問題原因
《關于三次握手與四次揮手你要知道這些》中有關于“四次揮手釋放連接時,等待2MSL的意義”的解釋。正因為有2ML的存在,所以可能會發(fā)生大量time_wait存在的現(xiàn)象,從而影響服務器性能,甚至導致套接字數(shù)量達到服務器上限。
實際上,TIME_WAIT對于系統(tǒng)資源的消耗影響比較小,而真正需要考慮因為TIME_WAIT多而觸碰到限制的是如下幾個方面:
源端口數(shù)量 (net.ipv4.ip_local_port_range)
TIME_WAIT bucket 數(shù)量 (net.ipv4.tcp_max_tw_buckets)
文件描述符數(shù)量 (max open files)
解決方法
只需要優(yōu)化服務器系統(tǒng)的網(wǎng)絡配置,連接配置,使用socket重用或及時釋放資源即可。(由于系統(tǒng)不斷迭代,所以這里不給出具體參數(shù)修改)
大量close_wait
問題原因
主機B一直沒有進行第三次揮手,會導致主機B存在大量close_wait狀態(tài)的連接。大量這種情況發(fā)生會影響服務器性能,同樣可能導致套接字數(shù)量達到服務器上限。
網(wǎng)絡連接未及時釋放,通常是服務端發(fā)生異常后未關閉連接或者close_wait的配置時間過長。如果是mysql數(shù)據(jù)庫也可能存在事務開啟后沒有正確rollback或commit的可能。
總之,都是大概率是服務端代碼或配置的問題。
解決方法
以下方法并不存在順序,定位問題時也并不是一定同時需要。
top查看cpu利用率和load情況(大量close_wait屬于io密集型,會導致load相比cpu利用率高出很多)
netstat觀察close_wait的數(shù)量變化。
wireshark輔助查看網(wǎng)絡包的發(fā)送情況。
perf或者火焰圖定位熱點函數(shù)。
java可以將服務器線程堆棧dump,查看大量線程在哪里blocked。
