网络优化之net.ipv4.tcp_tw_recycle和tcp_tw_reuse参数

 

linux TIME_WAIT 相关参数:前端

net.ipv4.tcp_tw_reuse = 0    表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 0  表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_fin_timeout = 60  表示若是套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间(可改成30,通常来讲FIN-WAIT-2的链接也极少)

注意:linux

- 不像Windows 能够修改注册表修改2MSL 的值,linux 是没有办法修改MSL的,tcp_fin_timeout 不是2MSL 而是Fin-WAIT-2状态.数据库

- tcp_tw_reuse 和SO_REUSEADDR 是两个彻底不一样的东西后端

 

查看参数:bash

cat/proc/sys/net/ipv4/tcp_tw_recycle  (表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭)服务器

cat /proc/sys/net/ipv4/tcp_tw_reuse

修改参数:
sudo bash -c 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse'
sudo bash -c 'echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle'
网络

1. tw_reuse,tw_recycle 必须在客户端和服务端timestamps 开启时才管用(默认打开)socket

2. tw_reuse 只对客户端起做用,开启后客户端在1s内回收tcp

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 会有一点点好处。

4. 业务上也能够设计由服务端主动关闭链接

 

对于服务端

1. 打开tw_reuse无效

2. 线上环境 tw_recycle 不要打开

   服务器处于NAT 负载后,或者客户端处于NAT后(这是必定的事情,基本公司家庭网络都走NAT);

 公网服务打开就可能形成部分链接失败,内网的话到时能够视状况打开;

   像我所在公司对外服务都放在负载后面,负载会把timestamp 都给清空,好吧,就算你打开也不起做用。

3. 服务器TIME_WAIT 高怎么办

   不像客户端有端口限制,处理大量TIME_WAIT Linux已经优化很好了,每一个处于TIME_WAIT 状态下链接内存消耗不多,

并且也能经过tcp_max_tw_buckets = 262144 配置最大上限,现代机器通常也不缺这点内存。

    下面像咱们一台每秒峰值1w请求的http 短链接服务,长期处于tw_buckets 溢出状态,

tw_socket_TCP 占用70M, 由于业务简单服务占用CPU 200% 运行很稳定。

复制代码
复制代码

slabtop

262230 251461  95%    0.25K  17482       15     69928K tw_sock_TCP

ss -s
Total: 259 (kernel 494)
TCP:   262419 (estab 113, closed 262143, orphaned 156, synrecv 0, timewait 262143/0), ports 80

Transport Total     IP        IPv6
*         494       -         -        
RAW       1         1         0        
UDP       0         0         0        
TCP       276       276       0        
INET      277       277       0        
FRAG      0         0         0
复制代码
复制代码

惟一不爽的就是:

系统日志中overflow 错误一直再刷屏,也许该buckets 调大一下了

TCP: time wait bucket table overflow
TCP: time wait bucket table overflow
TCP: time wait bucket table overflow
TCP: time wait bucket table overflow
TCP: time wait bucket table overflow

 

5. 业务上也能够设计由客户端主动关闭链接

 

原理分析

 1. MSL 由来

  发起链接关闭方回复最后一个fin 的ack,为避免对方ack 收不到、重发的或还在中间路由上的fin 把新链接给干掉了,等个2MSL,4min。

  也就是链接有谁关闭的那一方有time_wait问题,被关那方无此问题。

2. reuse、recycle

     经过timestamp的递增性来区分是否新链接,新链接的timestamp更大,那么小的timestamp的fin 就不会fin掉新链接。

3. reuse

     经过timestamp 递增性,客户端、服务器可以处理outofbind fin包

4. recycle

    对于服务端,同一个src ip,可能会是NAT后不少机器,这些机器timestamp递增性无可保证,服务器会拒绝非递增请求链接。

 

 细节之处还得好好阅读tcp 协议栈源码了

【案例分析1】

最近发现几个监控用的脚本在链接监控数据库的时候偶尔会连不上,报错:
 Couldn't connect to host:3306/tcp: IO::Socket::INET: connect: Cannot assign requested address
查看了一下发现系统中存在大量处于TIME_WAIT状态的tcp端口
$netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 50013
ESTABLISHED 27
SYN_RECV 1
因为要监控的主机太多,监控的agent可能在短期内建立大量链接到监控数据库(MySQL)并释放形成的。在网上查阅了一些tcp参数的相关资料,最后经过修改了几个系统内核的tcp参数缓解了该问题:
#vi /etc/sysctl.conf

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

#sysctl -p
其中:
net.ipv4.tcp_tw_reuse = 1 表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
修改完成并生效后,系统中处于TIME_WAIT状态的tcp端口数量迅速降低到100左右:
$netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 82
ESTABLISHED 36
简单记录于此,备忘。

 

【案例分析2】

网上的帖子,大多都写开启net.ipv4.tcp_tw_recycle这个开关,能够快速回收处于TIME_WAIT状态的socket(针对Server端而言)。


而实际上,这个开关,须要net.ipv4.tcp_timestamps(默认开启的)这个开关开启才有效果。
更不为提到却很重要的一个信息是:当tcp_tw_recycle开启时(tcp_timestamps同时开启,快速回收socket的效果达到),对于位于NAT设备后面的Client来讲,是一场灾难——会导到NAT设备后面的Client链接Server不稳定(有的Client能链接server,有的Client不能链接server)。也就是说,tcp_tw_recycle这个功能,是为“内部网络”(网络环境本身可控——不存在NAT的状况)设计的,对于公网,不宜使用。

一般,“回收”TIME_WAIT状态的socket是由于“没法主动链接远端”,由于无可用的端口,而不该该是要回收内存(没有必要)。即,需求是“Client”的需求,Server会有“端口不够用”的问题吗?除非是前端机,须要大量的链接后端服务——即充当着Client的角色。正确的解决这个老是办法应该是:net.ipv4.ip_local_port_range = 9000 6553 #默认值范围较小net.ipv4.tcp_max_tw_buckets = 10000 #默认值较小,还可适当调小net.ipv4.tcp_tw_reuse = 1 #net.ipv4.tcp_fin_timeout = 10 #--------------------- 做者:天府云创 来源:CSDN 原文:https://blog.csdn.net/enweitech/article/details/79261439 版权声明:本文为博主原创文章,转载请附上博文连接!

相关文章
相关标签/搜索