參數設置
默認情況下tcp_tw.recycle & tc_tw_reuse是關閉的,即值為1;tcp_timestamps默認情況下開啟的
tcp_recycle在4.10內核已不在使用,4.12版本的內核相關代碼正式刪除;tcp_tw_reuse則繼續保留
-
net.ipv4.tcp_tw_recycle = 1
-
net.ipv4.tcp_tw_reuse = 1
-
net.ipv4.tcp_timestamps = 1
查看方法
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ss -ant | awk 'NR>1 {++s[$1]} END {for(k in s) print k,s[k]}'
參數區別
- tcp_tw_reuse
官方引文
Enable reuse of TIME-WAIT sockets for new connections when it is safe from protocol viewpoint.
當在協議的角度安全時,開啟復用TIME_WAIT sockets用於新建的TCP連接
tcp_tw_reuse參數依賴於tcp_timestamps,Linux官方2.6以上的內核標志着該參數默認是開啟的
tcp_tw_reuse 中文字面理解,重復利用已存在TIME_WAIT狀態的連接
復用的條件如下
-
既然tcp_tw_reuse使用到tcp_timestmps,那說明一定和時間戳有關系,如果后發報文中的時間戳比之前緩存的時間戳大,將會從已建立的TIME_WAIT的連接選擇進行數據傳輸
-
根據代碼顯示,TIME_WAIT狀態的連接必須大於1秒才可復用
連接復用的過程,如下圖
復用前的狀態,主動關閉發起端收到被動關閉接收端的fin確認包后,同時發出ack包給被動關閉方,同時進入了TIME_WAIT狀態,標准正常4次打招呼方式,這時發起新連接並使用復用此條TIME_WAIT狀態的連接
-
TIME_WAIT的連接被復用后,首先主動發起方,發送SYN包給接收端,此時發起方是SYN_SENT狀態
-
但是接收端並不會應答該SYN包,並且同時忽略RST包,但是返回一個FIN給發起方
-
然后發起方發送一個RST包給接收方,促使對端跳過LASK-ACK階段,然后在一秒之后,再次將初始發送的SYN至接收方,整個過程看上去沒啥錯誤,只是在鏈路上延遲一會
值得注意的是,如果發生了復用,則會在/proc/net/netstat中的字段TWRecycled累積
- tcp_tw_recycle
該內核參數默認情況下是關閉的,即值為0,開啟值為1
官方說明
tcp_tw_recycle - BOOLEAN
Enable fast recycling TIME-WAIT sockets. Default value is 0.It should not be changed without advice/request of technical experts.
快速回收TIME_WAIT狀態的連接
tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)[Translator’s Note: From the description of linux man tcp] Enable fast recycling of TIME-WAIT sockets. Enabling this option is not recommended since this causes
problems when working with NAT (Network Address Translation).
Enable fast recovery of sockets in TIME-WAIT state. This option is not recommended. In a NAT (Network Address Translation) network, a large number of TCP connection establishment errors will be caused.
在2.4說明,在NAT環境中,此參數不再推薦開啟,問題表現為如果遇到峰值的TCP連接會報錯
在4.12內核版本,官方release說明,將移除相關tcp_tw_recycle代碼
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/networking/ip-sysctl.txt?h=v4.12 (技術文檔已刪除與之tw_recycle相關的說明文檔)
https://github.com/torvalds/linux/commit/4396e46187ca5070219b81773c4e65088dac50cc
如何實現快速回收,如下
-
首先tw_recycle也需要依賴於tcp_timestampsg開啟
-
具體快速回收時間與TCP中的RTO相關,相關的RTO時間可在(https://github.com/torvalds/linux/blob/v3.10/include/net/tcp.h)查看(MIN & MAX),根據(https://github.com/torvalds/linux/blob/v3.10/net/ipv4/tcp_minisocks.c 329)代碼的意思理解,回收TIME_WAIT優先使用RTO的時間,否則按默認的TCP_TIMEWAIT_LEN的時間
-
一般這個時間差不多700ms,基本判斷條件就是,如果存在TIME_WAIT就執行recycle
解釋NAT環境丟包的問題
-
tcp_tw_recycle是必須依賴於tcp_timestamps,而tcp_timestamps則是解決PAWS的問題,所以PAWS的原則如下,RFC1323
An additional mechanism could be added to the TCP,a per-host cache of the last timestamp received from any connection.This value could then be used in the PAWS mechanism to reject old duplicate segments from earlier incarnations of the connection,if the timestamp clock can be guaranteed to have ticked at least once since the old connection was open.This would require that the TIME-WAIT delay plus the RTT together must be at least one tick of the sender’stimestamp clock. Such an extension is not part of the proposal of this RFC.原文解釋了,TCP存在一種機制,per-host會緩存保留已建立連接的最新一個timestamp,而該timestamp要遵循PAWS的機制,具體作用就是如果下次接收的數據報文的時間戳早於記錄的最后一個報文的時間戳,則直接丟棄該報文
- 當在NAT環境中,一般指多台服務器出公網都是由NAT地址轉換的形式,則很難保證后端服務器時間是同步的,而引起的時間戳錯亂,導致連接的數據報被drop
總結
關於該參數,既然在4.12版本的內核被移除,沒必要再討論,版本升級再也不會遇到這個問題
參考文獻
https://perthcharles.github.io/2015/08/27/timestamp-NAT/
https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
https://blog.csdn.net/yunhua_lee/article/details/8146856
https://blog.csdn.net/yunhua_lee/article/details/8146845
https://blog.huoding.com/2012/01/19/142
https://blog.huoding.com/2013/12/31/316
https://www.cnblogs.com/zy09/p/13958915.html
https://mp.weixin.qq.com/s?__biz=MzA3MzYwNjQ3NA==&mid=403232978&idx=1&sn=4ed396ac1999add1c866419bd62b0e75&scene=0#wechat_redirect