1. 程式人生 > >TIME_WAIT 太多的解決辦法

TIME_WAIT 太多的解決辦法

一秒 即使 修改 不能 可靠 wait 啟用 bin 最好

TIME_WAIT

客戶端與服務器端建立TCP/IP連接後關閉SOCKET後,服務器端連接的端口狀態為TIME_WAIT.主動關閉的一方在發送最後一個 ack 後

就會進入 TIME_WAIT 狀態 停留2MSL(max segment lifetime)時間

這個是TCP/IP必不可少的,也就是“解決”不了的,也就是TCP/IP設計者本來是這麽設計的

主要有兩個原因

1。防止上一次連接中的包,迷路後重新出現,影響新連接

(經過2MSL,上一次連接中所有的重復包都會消失)

2。可靠的關閉TCP連接

在主動關閉方發送的最後一個 ack(fin) ,有可能丟失,這時被動方會重新發fin, 如果這時主動方處於 CLOSED 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED 。

TIME_WAIT 並不會占用很大資源的,除非受到攻擊。

還有,如果一方 send 或 recv 超時,就會直接進入 CLOSED 狀態

1

netstat -an

查看下,發現系統中有很多time_wait的連接。因此直接用一下命令查看詳細情況

1

netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}‘

具體的解決方式

vim /etc/sysctl.conf

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

//修改系統默認的 TIMEOUT 時間

/sbin/sysctl -p //保存後生效

目前看來最好的辦法是讓每個TIME_WAIT早點過期。

在linux上可以這麽配置:

#讓TIME_WAIT狀態可以重用,這樣即使TIME_WAIT占滿了所有端口,也不會拒絕新的請求造成障礙
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
#讓TIME_WAIT盡快回收,我也不知是多久,觀察大概是一秒鐘
echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle

很多文檔都會建議兩個參數都配置上,但是我發現只用修改tcp_tw_recycle就可以解決問題的了,TIME_WAIT重用TCP協議本身就是不建議打開的。

不能重用端口可能會造成系統的某些服務無法啟動,比如要重啟一個系統監控的軟件,它用了40000端口,而這個端口在軟件重啟過程中剛好被使用了,就可能會重啟失敗的。linux默認考慮到了這個問題,有這麽個設定:

#查看系統本地可用端口極限值
cat /proc/sys/net/ipv4/ip_local_port_range

用這條命令會返回兩個數字,默認是:32768 61000,說明這臺機器本地能向外連接61000-32768=28232個連接,註意是本地向外連接,不是這臺機器的所有連接,不會影響這臺機器的80端口的對外連接數。但這個數字會影響到代理服務器(nginx)對app服務器的最大連接數,因為nginx對app是用的異步傳輸,所以這個環節的連接速度很快,所以堆積的連接就很少。假如nginx對app服務器之間的帶寬出了問題或是app服務器有問題,那麽可能使連接堆積起來,這時可以通過設定nginx的代理超時時間,來使連接盡快釋放掉,一般來說極少能用到28232個連接。

TIME_WAIT 太多的解決辦法