windows 下解决 Time_Wait 和 CLOSE_WAIT 方法
從這張圖可以看出 TCP 連線在各種狀態之間變動的狀況與順序,其中 TIME_WAIT 連線已經是 TCP 連線在 完全關閉連線狀態 (CLOSED) 之前的一個狀態 (註:完全關閉連線是指網路完整斷線的意思),而預設 TIME_WAIT 的逾時時間為 MSL (Maximum Segment Lifetime) 時間的兩倍,在 RFC 793 規格定義的 MSL 為兩分鐘,也就是在預設的情況下,每一條連線從 打算關閉連線狀態(Closing) 換到 完整關閉連線狀態 (Closed) 之間還會停留在 TIME_WAIT 狀態約 4 分鐘的時間,如果你 4 分鐘以內使用者建立的連線數超過 65536 條連線的話,那麼很這台伺服器就再也無法連接了。 ( 註:Windows 預設的 TIME_WAIT 時間為 4 分鐘,Linux 下則會依據不同 Distribution 版本而有不同的預設值,但都可以調整其時間長短 )
MSL 為一個 TCP Segment (某一塊 TCP 網路封包) 從來源送到目的之間可續存的時間 (也就是一個網路封包在網路上傳輸時能存活的時間),由於 RFC 793 TCP 傳輸協定是在 1981 年定義的,當時的網路速度不像現在的網際網路那樣發達,你可以想像你從瀏覽器輸入網址等到第一個 byte 出現要等 4 分鐘嗎?在現在的網路環境下幾乎不可能有這種事情發生,因此我們大可將 TIME_WAIT 狀態的續存時間大幅調低,好讓 連線埠 (Ports) 能更快空出來給其他連線使用。
注意:如果當系統所有可用的 連線埠 (Ports) 都用光的話,就會接收到以下錯誤訊息:WSAENOBUFS (10055) error: "An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full."
因此在流量較大的網站或伺服器,應該是要調整 Windows 預設的 TIME_WAIT 存留時間才對,如果要縮短 Windows 預設的 TIME_WAIT 狀態的續存時間可以調整以下機碼值,微軟建議最低可設定續存時間為 30 秒,而且也提到設定 30 秒應該不會出問題,因此我幾乎都只設定 30 秒而已:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters]
"TcpTimedWaitDelay"=dword:0000001e
或可透過 reg.exe 工具直接進行機碼值設定:
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters" /v "TcpTimedWaitDelay" /t REG_DWORD /d 30 /f
調整完成後可能需要重新啟動伺服器才能讓設定生效 (註:我不知道有沒有不重開機的方法,如果有人知道麻煩留言告訴我,謝謝!),自從我設定完這個機碼後,伺服器的連線數就明顯少了許多,因此也不用怕連接埠在短期內被用光的情況了。