MSL,即Maximum Segment Lifetime,一個數據分片(報文)在網絡中能夠生存的最長時間,在RFC 793中定義MSL通常為2分鍾,即超過兩分鍾即認為這個報文已經在網絡中被丟棄了。對於一個TCP連接,在雙方進入TIME_WAIT后,通常會等待2倍MSL時間后,再關閉掉連接,作用是為了防止由於FIN報文丟包,對端重發導致與后續的TCP連接請求產生順序混亂,具體原理這里就不詳細解釋了,可以參考:http://blog..net/qwertyupoiuytr/article/details/68938963
MSL的時長其實是一個估計值,由於這個值會影響很多基於TCP的應用的連接復用和調優,所以在實際生產中,需要針對具體的應用來調整MSL的具體值(需要注意的是,由於MSL值是對於系統層面來說,所以調整后,會對系統中部署的全部應用產生影響)。下面說明了針對Linux系統和Windows系統調整MSL的方法。
Linux,以CentOS為例:
查看默認的MSL值(60s):
[root@DanCentOS65var]# cat /proc/sys/net/ipv4/tcp_fin_timeout
60
修改默認60為120:
[root@DanCentOS65var]# echo 120 > /proc/sys/net/ipv4/tcp_fin_timeout
修改完成后,重新加載配置文件:
[root@DanCentOS65var]# sysctl -p /etc/sysctl.conf
查看是否已經生效:
[root@DanCentOS65var]# sysctl -a | grep fin
net.ipv4.tcp_fin_timeout= 120
Windows上修改"2MSL"的值:
打開注冊表編輯器(regedit):

找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,在右側找到TcpTimedWaitDelay這一個鍵值(Win2000之后的系統中可能會沒有這個值,如果沒有,創建一個即可):

指定對應的值即可:

注意在Windows系統中,這個注冊表鍵值就直接等於TIME_WAIT到CLOSED狀態的等待市場,也就是2MSL的值,而不像Linux中,我們修改的是MSL的值。
打開CSDN,閱讀體驗更佳
更多相似內容
最近網站流量有些上升,感覺到訪問速度有些慢;用netstat -na命令發現系統中有大量狀態為TIME-WAIT的TCP連接,google了下;修改了/etc/sysctl.conf中一些內核參數;解決了TCP連接中TIME-WAIT sockets的問題。
編輯/etc/sysctl.conf文件,增加如下內容:
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
再執行以下命令,讓修改結果立即生效:
sysctl -p
用以下語句看了一下服務器的TCP狀態:
返回結果如下:
TIME_WAIT 4654
FIN_WAIT1 576
FIN_WAIT2 91
ESTABLISHED 866
SYN_RECV 654
CLOSING 285
LAST_ACK 78
效果:處於TIME_WAIT狀態的sockets從原來的20000多減少到5000左右;同時處於SYN_RECV等待處理狀態的sockets也下降了。
通過上面的設置以后,你可能會發現一個新的問題,就是netstat時可能會出現這樣的警告:
warning, got duplicate tcp line
這正是上面允許tcp復用產生的警告,不過這不算是什么問題,總比不允許復用而給服務器帶來很大的負載合算的多
盡管如此,還是有解決辦法的:
[root@root2 opt]# rpm -Uvh net-tools-1.60-62.1.x86_64.rpm
Preparing... ########################################### [100%]
1:net-tools ########################################### [100%]
[root@root2 opt]#
對於下載的是源碼的rpm則需要使用以下方法安裝:
2、 安裝rpm源碼包方法:
a) 安裝src.rpm:
# [root@root1 opt]# rpm -i net-tools-1.60-62.1.src.rpm
……
b) 制作rpm安裝包:
[root@root1 opt]# cd /usr/src/redhat/SPECS/
[root@root1 SPECS]# rpmbuild -bb net-tools.spec
c) rpm包的升級安裝:
[root@root1 SPECS]# pwd
/usr/src/redhat/SPECS
[root@root1 SPECS]# cd ../RPMS/x86_64/
[root@root1 x86_64]# rpm -Uvh net-tools-1.60-62.1.x86_64.rpm
3、 再使用netstat來檢查時系統正常。
附錄:
內核參數說明:
net.ipv4.tcp_syncookies = 1 表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認為0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉。
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。
net.ipv4.tcp_keepalive_time = 1800 表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改為20分鍾。
net.ipv4.ip_local_port_range = 1024 65000 表示用於向外連接的端口范圍。缺省情況下很小:32768到61000,改為1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN隊列的長度,默認為1024,加大隊列長度為8192,可以容納更多等待連接的網絡連接數。
net.ipv4.tcp_max_tw_buckets = 5000 表示系統同時保持TIME_WAIT套接字的最大數量,如果超過這個數字,TIME_WAIT套接字將立刻被清除並打印警告信息。默認為180000,改為5000。對於Apache、Nginx等服務器,上幾行的參數可以很好地減少TIME_WAIT套接字數量,但是對於Squid,效果卻不大。此項參數可以控制TIME_WAIT套接字的最大數量,避免Squid服務器被大量的TIME_WAIT套接字拖死(本站正好采用的是squid+apache,修改前面幾項參數后time_wait連接數依舊沒有減少,最后修改了此參數)。
net.ipv4.route.gc_timeout = 100 路由緩存刷新頻率,當一個路由失敗后多長時間跳到另一個
默認是300
net.ipv4.tcp_syn_retries = 1 對於一個新建連接,內核要發送多少個 SYN 連接請求才決定放棄。不應該大於255,默認值是5,對應於180秒左右。
TCP狀態的變遷圖:
狀態描述:
CLOSED:無連接是活動的或正在進行
LISTEN:服務器在等待進入呼叫
SYN_RECV:一個連接請求已經到達,等待確認
SYN_SENT:應用已經開始,打開一個連接
ESTABLISHED:正常數據傳輸狀態
FIN_WAIT1:應用說它已經完成
FIN_WAIT2:另一邊已同意釋放
ITMED_WAIT:等待所有分組死掉
CLOSING:兩邊同時嘗試關閉
TIME_WAIT:另一邊已初始化一個釋放
LAST_ACK:等待所有分組死掉
TCP中TIME_WAIT的相關原理:
在socket的TIME_WAIT狀態結束之前,該socket所占用的本地端口號將一直無法釋放。編寫過高TCP並發並且采用短連接方式進行通訊的軟件程序的人,都可能體會到,這樣的通訊系統在高並發高負載下運行一段時間后,就常常會出現做為客戶端的程序無法向服務端建立新的socket連接的情況。此時用"netstat-anp"命令查看系統將會發現機器上存在大量處於TIME_WAIT狀態的socket連接,並且占用大量的本地端口號。最后,當該機器上的可用本地端口號被占完,而舊的大量處於TIME_WAIT狀態的socket尚未被系統回收時,就會出現無法向服務端創建新的socket連接的情況。此時的通訊系統幾乎停轉,空有再好的性能也發揮不出來。
如果能夠在客戶端程序主動關閉socket之前,讓該socket的接收隊列中仍保留一些數據(至少要有多余的一個字節的數據),然后調用close關閉,那么上述的無法向服務端創建新的socket連接的情況將不會出現。這是因為當socket的接收隊列中仍有數據未被應用程序讀走就被強行關閉時,操作系統(至少在筆者驗證過的操作系統上的確如此)的TCP/IP協議棧驅動程序會在底層主動向服務端發送一個要求結束TCP連接的控制包,並將該TCP包頭的flag控制字段中的RESET位置位,從而迅速結束了此TCP連接。這其實是操作系統對TCP連接斷開的一種異常處理。而正常情況下(socket 的接收隊列中無未讀數據),當應該程序調用close關閉連接時,底層驅動程序向服務端發送的要求結束TCP連接的控制包頭的flag控制字段中是將 FIN位置位,並且嚴格遵循上圖所示的狀態轉換過程,最終到達TIME_WAIT狀態並持續2*MSL的時間。
awk命令解釋
/^tcp/
濾出tcp開頭的記錄,屏蔽udp, socket等無關記錄。
state[]
相當於定義了一個名叫state的數組
NF
表示記錄的字段數,如上所示的記錄,NF等於6
$NF
表示某個字段的值,如上所示的記錄,$NF也就是$6,表示第6個字段的值,也就是TIME_WAIT
state[$NF]
表示數組元素的值,如上所示的記錄,就是state[TIME_WAIT]狀態的連接數
++state[$NF]
表示把某個數加一,如上所示的記錄,就是把state[TIME_WAIT]狀態的連接數加一
END
表示在最后階段要執行的命令
for(key in state)
遍歷數組
print key,"\t",state[key]
打印數組的鍵和值,中間用\t制表符分割,美化一下。
