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

posted on 2019-03-01 14:28  nmap  阅读(11341)  评论(1编辑  收藏  举报

导航