TIME_WAIT是什么?
TIME_WAIT是表示系統(tǒng)在等待客戶端響應(yīng),以便再次連接時候能快速響應(yīng)。TCP協(xié)議的三次握手中規(guī)定發(fā)起socket主動關(guān)閉的一方 socket將進入TIME_WAIT狀態(tài),TIME_WAIT狀態(tài)將持續(xù)2個MSL(Max Segment Lifetime)。我們看下tcp的三次握手機制:
從 上面的示意圖可以看得出來,TIME_WAIT是主動關(guān)閉連接的一方保持的狀態(tài),從而進入TIME_WAIT的狀態(tài),然后在保持這個狀態(tài)2MSL(max segment lifetime)時間之后,徹底關(guān)閉回收資源。為什么要這么做?明明就已經(jīng)主動關(guān)閉連接了為啥還要保持資源一段時間呢?這個是TCP/IP的設(shè)計者規(guī)定 的,主要出于以下兩個方面的考慮:
1.防止上一次連接中的包,迷路后重新出現(xiàn),影響新連接(經(jīng)過2MSL,上一次連接中所有的重復(fù)包都會消失)
2. 可靠的關(guān)閉TCP連接。在主動關(guān)閉方發(fā)送的最后一個 ack(fin) ,有可能丟失,這時被動方會重新發(fā)fin, 如果這時主動方處于 CLOSED 狀態(tài) ,就會響應(yīng) rst 而不是 ack。所以主動方要處于 TIME_WAIT 狀態(tài),而不能是 CLOSED 。另外這么設(shè)計TIME_WAIT 會定時的回收資源,并不會占用很大資源的,除非短時間內(nèi)接受大量請求或者受到攻擊。
==============Windows操作系統(tǒng)==========
查看使用端口數(shù)量:cmd-- netsh interface ipv4 show dynamicportrange protocol=tcp
查看建立連接的數(shù)量:netsh interface ipv4 show tcpstats
大規(guī)模Windows環(huán)境下,采用Nginx反向代理服務(wù)后,操作系統(tǒng)會產(chǎn)生較多TIME_WAIT的TCP(Transmission Control Protocol)連接,操作系統(tǒng)默認(rèn)TIME_WAIT的TCP連接回收時間是4分鐘,TCP默認(rèn)動態(tài)端口范圍為開始端口49152,結(jié)束端口65535。這樣會使回收TCP過慢導(dǎo)致系統(tǒng)吞吐量下降,甚至出現(xiàn)502訪問失敗問題。如何修改操作系統(tǒng)內(nèi)核參數(shù)來縮短TIME_WAIT狀態(tài)TCP連接回收時間和添加TCP動態(tài)端口范圍,保證在大并發(fā)場景下操作系統(tǒng)的端口資源可用?
以Administrator用戶登錄Windows操作系統(tǒng)。修改TCP回收時間。
在Windows開始菜單中,單擊“運行”輸入“regedit”后按“Enter”打開注冊表編輯器。
“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters”路徑。
在“編輯”菜單中,選擇“新建 > DWORD (32-位)值”,輸入名稱“TcpTimedWaitDelay”。
右鍵單擊TcpTimedWaitDelay,選擇“修改”。在“編輯 DWORD(32位)值”對話框的“基數(shù)”區(qū)域中,選擇十進制值為“30”,并“確定”。關(guān)閉注冊表編輯器。
修改端口范圍
在Windows開始菜單中,單擊“運行”輸入“cmd”
執(zhí)行命令:netsh int ipv4 set dynamicportrange tcp startport=5000 numberofports=60000
重啟操作系統(tǒng)。
實例:
最近線上遇到windows機器訪問其他機器的時候失敗的情況。實際就是本地的端口不夠用造成的。
D:\>netsh interface ipv4 show dynamicportrange protocol=tcp
Protocol tcp Dynamic Port Range
---------------------------------
Start Port : 49152
Number of Ports : 16384
D:\>netsh interface ipv4 show tcpstats
MIB-II TCP Statistics
------------------------------------------------------
Timeout Algorithm: Van Jacobson's Algorithm
Minimum Timeout: 10
Maximum Timeout: 4294967295
Maximum Connections: Dynamic
Active Opens: 402947
Passive Opens: 989620
Attempts Failed: 122047
Established Resets: 49384
Currently Established: 135
In Segments: 47651175
Out Segments: 45510477
Retransmitted Segments: 465369
In Errors: 0
Out Resets: 65865
這個能用的端口實際就16384個,可以直接 netstat -atn查看一下每個狀態(tài)的數(shù)量。如果對外做大量的請求會造成本地端口不夠用。
可以修改一下起始端口:
netsh int ipv4 set dynamicport tcp start=2000 num=63000
netsh int ipv4 set dynamicport udp start=2000 num=63000
netsh int ipv6 set dynamicport tcp start=2000 num=63000
netsh int ipv6 set dynamicport udp start=2000 num=63000
然后修改一下注冊表縮短time-wait的時間。
regedit打開注冊表,添加
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
“MaxUserPort”=dword:0000fffe
“TcpTimeWaitDelay”=dword:0000005 (縮短為5秒)
=============linux系統(tǒng)====================
查看使用數(shù)量:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
/etc/sysctl.conf文件的修改:
#對于一個新建連接,內(nèi)核要發(fā)送多少個 SYN 連接請求才決定放棄,不應(yīng)該大于255,默認(rèn)值是5,對應(yīng)于180秒左右時間
net.ipv4.tcp_syn_retries=2
#net.ipv4.tcp_synack_retries=2
#表示當(dāng)keepalive起用的時候,TCP發(fā)送keepalive消息的頻度。缺省是2小時,改為300秒
net.ipv4.tcp_keepalive_time=1200
net.ipv4.tcp_orphan_retries=3
#表示如果套接字由本端要求關(guān)閉,這個參數(shù)決定了它保持在FIN-WAIT-2狀態(tài)的時間
net.ipv4.tcp_fin_timeout=30
#表示SYN隊列的長度,默認(rèn)為1024,加大隊列長度為8192,可以容納更多等待連接的網(wǎng)絡(luò)連接數(shù)。
net.ipv4.tcp_max_syn_backlog = 4096
#表示開啟SYN Cookies。當(dāng)出現(xiàn)SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認(rèn)為0,表示關(guān)閉
net.ipv4.tcp_syncookies = 1
#表示開啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認(rèn)為0,表示關(guān)閉
net.ipv4.tcp_tw_reuse = 1
#表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認(rèn)為0,表示關(guān)閉
net.ipv4.tcp_tw_recycle = 1
##減少超時前的探測次數(shù)
net.ipv4.tcp_keepalive_probes=5
##優(yōu)化網(wǎng)絡(luò)設(shè)備接收隊列
net.core.netdev_max_backlog=3000
修改完之后執(zhí)行/sbin/sysctl -p讓參數(shù)生效。
這里頭主要注意到的是
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.tcp_fin_timeout
net.ipv4.tcp_keepalive_*
這幾個參數(shù)。
net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle的開啟都是為了回收處于TIME_WAIT狀態(tài)的資源。
net.ipv4.tcp_fin_timeout這個時間可以減少在異常情況下服務(wù)器從FIN-WAIT-2轉(zhuǎn)到TIME_WAIT的時間。
net.ipv4.tcp_keepalive_*一系列參數(shù),是用來設(shè)置服務(wù)器檢測連接存活的相關(guān)配置。
實例:
一天業(yè)務(wù)開發(fā)反饋說最近總是出現(xiàn)時不時連接數(shù)據(jù)庫失敗,php現(xiàn)在有時會報 連接數(shù)過多。返回too much connections....
排查
登錄數(shù)據(jù)庫服務(wù)器,第一時間直接查看tcp連接數(shù):
[root@s0001-gz ~]# netstat -nalpt | grep 3306 |wc -l
9093
一看9000多個連接了,有點恐怖。
登錄數(shù)據(jù)庫服務(wù)查看實際連接數(shù):
mysql>show processlist;
....
468 rows
連接數(shù)才468個,而設(shè)置的max_connection=1000;
一半都達不到,那問題就肯定出在系統(tǒng)的連接數(shù)上了。
查看實際的連接用戶:
90%全部是TIME_WAIT。
快速恢復(fù)方法:
vi /etc/sysctl.conf
編輯文件,加入以下內(nèi)容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后執(zhí)行 /sbin/sysctl -p 讓參數(shù)生效
解釋:
net.ipv4.tcp_syncookies = 1 表示開啟SYN Cookies。當(dāng)出現(xiàn)SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認(rèn)為0,表示關(guān)閉;
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認(rèn)為0,表示關(guān)閉;
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認(rèn)為0,表示關(guān)閉。
net.ipv4.tcp_fin_timeout 修改系統(tǒng)默認(rèn)的 TIMEOUT 時間
查看結(jié)果:
如對本文有疑問,請?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會為你解答??! 點擊進入論壇