欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

探讨如何减少Linux服务器TIME_WAIT过多的问题

程序员文章站 2022-06-04 10:38:23
time_wait状态的意义: 客户端与服务器端建立tcp/ip连接后关闭socket后,服务器端连接的端口状态为time_wait是不是所有执行主动关闭的socket都会...

time_wait状态的意义:
客户端与服务器端建立tcp/ip连接后关闭socket后,服务器端连接的端口状态为time_wait
是不是所有执行主动关闭的socket都会进入time_wait状态呢?
有没有什么情况使主动关闭的socket直接进入closed状态呢?
主动关闭的一方在发送最后一个 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 并不会占用很大资源的,除非受到攻击。
在squid服务器中可输入如下命令:
#netstat -n | awk '/^tcp/ {++s[$nf]} end {for(a in s) print a, s[a]}'
last_ack 14
syn_recv 348
established 70
fin_wait1 229
fin_wait2 30
closing 33
time_wait 18122
状态:描述
closed:无连接是活动的或正在进行
listen:服务器在等待进入呼叫
syn_recv:一个连接请求已经到达,等待确认
syn_sent:应用已经开始,打开一个连接
established:正常数据传输状态
fin_wait1:应用说它已经完成
fin_wait2:另一边已同意释放
itmed_wait:等待所有分组死掉
closing:两边同时尝试关闭
time_wait:另一边已初始化一个释放
last_ack:等待所有分组死掉
也就是说,这条命令可以把当前linux服务器的网络连接状态分类汇总。
下面解释一下为啥要这样写:
一个简单的管道符连接了netstat和awk命令。
先来看看netstat:
netstat -n
active internet connections (w/o servers)
proto recv-q send-q local address foreign address state
tcp 0 0 123.123.123.123:80 234.234.234.234:12345 time_wait
你实际执行这条命令的时候,可能会得到成千上万条类似上面的记录,不过我们就拿其中的一条就足够了。
再来看看awk:
/^tcp/
滤出tcp开头的记录,屏蔽udp, socket等无关记录。
state[]
相当于定义了一个名叫state的数组
nf
表示记录的字段数,如上所示的记录,nf等于6
$nf
表示某个字段的值,如上所示的记录,$nf也就是$6,表示第6个字段的值,也就是time_wait
state[$nf]
表示数组元素的值,如上所示的记录,就是state[time_wait]状态的连接数
++state[$nf]
表示把某个数加一,如上所示的记录,就是把state[time_wait]状态的连接数加一
end
表示在最后阶段要执行的命令
for(key in state)
遍历数组
print key,”\t”,state[key]
打印数组的键和值,中间用\t制表符分割,美化一下。
如发现系统存在大量time_wait状态的连接,通过调整内核参数解决,
vim /etc/sysctl.conf
编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行 /sbin/sysctl -p 让参数生效。
linux下高并发的squid服务器,tcp time_wait套接字数量经常达到两、三万,服务器很容易被拖死。通过修改linux内核参数,可以减少squid服务器的time_wait套接字数量。
vi /etc/sysctl.conf
增加以下几行:引用
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
说明:
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 表示如果套接字由本端要求关闭,这个参数决定了它保持在fin-wait-2状态的时间。
net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,tcp发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192 表示syn队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000表示系统同时保持time_wait套接字的最大数量,如果超过这个数字,time_wait套接字将立刻被清除并打印警告信息。默认为 180000,改为5000。对于apache、nginx等服务器,上几行的参数可以很好地减少time_wait套接字数量,但是对于squid,效 果却不大。此项参数可以控制time_wait套接字的最大数量,避免squid服务器被大量的time_wait套接字拖死。
执行以下命令使配置生效:
/sbin/sysctl -p