tcp_timestamps和tcp_tw_recycle


 

不同時開啟tcp_timestamps和tcp_tw_recycle的場景描述

FULL NAT下

FULL NAT  在client請求VIP 時,不僅替換了package 的dst ip,還替換了package的 src ip;但VIP 返回給client時也替換了src ip

lvs后端為web服務器。

假如web服務器開啟了tcp的tcp_timestamps和tcp_tw_recycle這兩個參數。那么存在下面這種情況

 

RFC1323中有如下一段描述:

An additional mechanism could be added to the TCP, a per-hostcache of the last timestamp received from any connection.This value could then be used in the PAWS mechanism to rejectold duplicate segments from earlier incarnations of theconnection, if the timestamp clock can be guaranteed to haveticked at least once since the old connection was open. Thiswould require that the TIME-WAIT delay plus the RTT togethermust be at least one tick of the sender’s timestamp clock.Such an extension is not part of the proposal of this RFC.

大概意思是說TCP有一種行為,可以緩存每個連接最新的時間戳,后續請求中如果時間戳小於緩存的時間戳,即視為無效,相應的數據包會被丟棄。意思就是同一個源IP來連接同一個目的端口的數據包時間戳必須是遞增的

Linux是否啟用這種行為取決於tcp_timestamps和tcp_tw_recycle,因為tcp_timestamps缺省就是開啟的,所以當tcp_tw_recycle被開啟后,實際上這種行為就被激活了。

現在很多公司都用LVS做負載均衡,通常是前面一台LVS,后面多台后端服務器,這其實就是NAT,當請求到達LVS后,它修改地址數據后便轉發給后端服務器,
但不會修改時間戳數據,對於后端服務器來說,請求的源地址就是LVS的地址,加上web端口會復用,所以從后端服務器的角度看,原本不同客戶端的請求經過LVS的轉發,
就可能會被認為是同一個連接,加之不同客戶端的時間可能不一致,所以就會出現時間戳錯亂的現象,於是后面的數據包就被丟棄了,
具體的表現通常是是客戶端明明發送的SYN,但服務端就是不響應ACK,還可以通過下面命令來確認數據包不斷被丟棄的現象

假如LVS地址是222.222.222.222,名字是L

web服務器地址為111.111.111.111,名字是W

比如客戶端地址客戶端C1地址為100.100.100.101,客戶端C2地址為100.100.100.102

假如出現這種情況

13:23:02這個時間點

C1發出的TCP數據包源IP和源端口為100.100.100.101:6332,目標地址和端口是222.222.222.222:80

13:23:05這個時間點

C2發出的TCP數據包源IP和源端口為100.100.100.102:52223,目標地址和端口是222.222.222.222:80

 

經過LVS的full nat。

假如在13:23:06時刻LVS收到C2的數據包

C2的數據包被轉換為

222.222.222.222:52223 ---->111.111.111.111:80

假如在13:23:07時刻LVS收到C1的數據包

C1的數據包被轉換為

222.222.222.222:6332 ---->111.111.111.111:80

假如web服務器開啟了tcp的tcp_timestamps和tcp_tw_recycle這兩個參數。web服務器根據數據包的時間戳

C1的數據包由於時間戳小於目前系統登記的此源IP連接的時間戳,被認為是重傳數據,C1的數據包就被丟棄了

 (不僅lvs的full nat會出現源地址被替換的情況,一些3層交換機作為負載均衡也會把源地址替換掉)

這個參數默認2.4的內核就禁用了。我們是能不開啟就不要開啟

 

 注意點

1. tw_reuse,tw_recycle 必須在客戶端和服務端timestamps 開啟時才管用(默認打開),其實意思就是假如服務端和客戶端兩邊有一邊timestamps沒開啟。tw_reuse和tw_recycle都沒啥作用
2. tw_reuse 只對客戶端起作用,開啟后客戶端在1s內回收。reuse就是重用time_wait的socket連接。 服務端同一個端口被連接理論上是沒限制的。
3. tw_recycle 對客戶端和服務器同時起作用,開啟后在 3.5*RTO 內回收,RTO 200ms~ 120s 具體時間視網絡狀況。
  內網狀況比tw_reuse 稍快,公網尤其移動網絡大多要比tw_reuse 慢,優點就是能夠回收服務端的TIME_WAIT數量

 

 

對於客戶端
1. 作為客戶端因為有端口65535問題,TIME_OUT過多直接影響處理能力,打開tw_reuse 即可解決,不建議同時打開tw_recycle,幫助不大。
2. tw_reuse 幫助客戶端1s完成連接回收,基本可實現單機6w/s請求,需要再高就增加IP數量吧。
3. 如果內網壓測場景,且客戶端不需要接收連接,同時tw_recycle 會有一點點好處。

 

 

對於服務端
1. 打開tw_reuse無效,因為是客戶端連接web服務器,服務端肯定不會重用socket去主動連接客戶端。這個參數服務器一般用不到,除非web服務器又作為客戶端去連接后端數據庫才用到。

但是web服務器作為客戶端連接數據庫達到6萬端口的限制時你的數據庫早承受不了壓力癱瘓了。一般數據庫5000連接數就已經很高了。

tw_resue這個參數,只有客戶端用得到。意思就是重用處於time_wait的socket連接。


2. 線上環境 tw_recycle 不要打開
服務器處於NAT 負載后,或者客戶端處於NAT后(這是一定的事情,基本公司家庭網絡都走NAT);
公網服務打開就可能造成部分連接失敗,內網的話到時可以視情況打開;
有些負載均衡設備會把timestamp 都給清空,后端web服務器開啟不開啟tw_recycle都無所謂了。


3. 服務器TIME_WAIT 高怎么辦

服務器time_wait不用擔心,因為我是服務端,是客戶端很多IP和端口主動連接我的一個端口,比如連接我的80端口。很可能出現一種情況就是雖然我機器上有10萬個time_wait連接。但是我的端口才用到一個80端口。

不像客戶端有端口限制,處理大量TIME_WAIT Linux已經優化很好了,每個處於TIME_WAIT 狀態下連接內存消耗很少,
而且也能通過tcp_max_tw_buckets = 262144 配置最大上限,現代機器一般也不缺這點內存。

 

 

 總之,生產中,服務器不管有沒有在nat設備后面.

tcp_tw_recycle不開啟就行了。默認就是不開啟的狀態,值為0

tcp_timestamps保持默認開啟就行了,值為1

tcp_tw_reuse.客戶端最好開啟。負載均衡設備連接web服務器時,輔助均衡設備也盡量開啟

 

關於服務器端出現大量time_wait,有些人會問,我是web服務器端,為什么會出現客戶端那種time_wait。

其實關於time_wait,它是出現在主動請求關閉連接的那一段。 服務器主動關閉http的連接。它就轉變為了客戶端。

發起斷開連接這個動作,不是說就一定是客戶端發起斷開的。很多時候都是服務器端先發起斷開連接操作。比如很多http服務器,短連接。很多時候服務器主動斷開。

 

服務出現tcp連接問題可以先查看下下面,看看是否有很多,很多時候就是開啟了tcp_tw_recycle導致的

[game@localhost ~]$ netstat -s | grep timestamp
    351 packets rejects in established connections because of timestamp
[game@localhost ~]$ 

  

客戶端相關優化的地方如下。(服務器不開啟tcp_tw_recycle即可)

[root@B ~]# cat /proc/sys/net/ipv4/ip_local_port_range 
32768	61000
[root@B ~]# cat /proc/sys/net/ipv4/tcp_timestamps 
1
[root@B ~]# cat /proc/sys/net/ipv4/tcp_tw_recycle 
0
[root@B ~]# cat /proc/sys/net/ipv4/tcp_tw_reuse 
0
[root@B ~]# echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
[root@B ~]# cat /proc/sys/net/ipv4/tcp_tw_reuse 
1
[root@B ~]# echo "10240  62000" > /proc/sys/net/ipv4/ip_local_port_range
[root@B ~]# cat /proc/sys/net/ipv4/ip_local_port_range 
10240	62000
[root@B ~]# 

  

 

 

 

相關參考鏈接

http://blog.csdn.net/caianye/article/details/38540867

http://elf8848.iteye.com/blog/2089414

http://blog.sina.com.cn/s/blog_781b0c850100znjd.html

http://blog.csdn.net/yunhua_lee/article/details/8146845

http://blog.sina.com.cn/s/blog_781b0c850100znjd.html

 http://www.cnblogs.com/lulu/p/4149312.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM