TIME_WAIT 太多的解决办法

TIME_WAIT linux


客户端与服务器端创建TCP/IP链接后关闭SOCKET后,服务器端链接的端口状态为TIME_WAIT.主动关闭的一方在发送最后一个 ack 后 nginx

就会进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间 vim

这个是TCP/IP必不可少的,也就是“解决”不了的,也就是TCP/IP设计者原本是这么设计的 服务器

主要有两个缘由 cookie

1。防止上一次链接中的包,迷路后从新出现,影响新链接 app

(通过2MSL,上一次链接中全部的重复包都会消失) 异步

2。可靠的关闭TCP链接 socket

在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会从新发fin, 若是这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。因此主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。 tcp

TIME_WAIT 并不会占用很大资源的,除非受到攻击。 spa

还有,若是一方 send 或 recv 超时,就会直接进入 CLOSED 状态


1

netstat -an

查看下,发现系统中有不少time_wait的链接。所以直接用一下命令查看详细状况


1

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

具体的解决方式


vim /etc/sysctl.conf

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

//修改系統默认的 TIMEOUT 时间

/sbin/sysctl -p   //保存后生效


目前看来最好的办法是让每一个TIME_WAIT早点过时。

在linux上能够这么配置:

#让TIME_WAIT状态能够重用,这样即便TIME_WAIT占满了全部端口,也不会拒绝新的请求形成障碍
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
#让TIME_WAIT尽快回收,我也不知是多久,观察大概是一秒钟
echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle

不少文档都会建议两个参数都配置上,可是我发现只用修改tcp_tw_recycle就能够解决问题的了,TIME_WAIT重用TCP协议自己就是不建议打开的。

不能重用端口可能会形成系统的某些服务没法启动,好比要重启一个系统监控的软件,它用了40000端口,而这个端口在软件重启过程当中恰好被使用了,就可能会重启失败的。linux默认考虑到了这个问题,有这么个设定:

#查看系统本地可用端口极限值
cat /proc/sys/net/ipv4/ip_local_port_range

用这条命令会返回两个数字,默认是:32768 61000,说明这台机器本地能向外链接61000-32768=28232个链接,注意是本地向外链接,不是这台机器的全部链接,不会影响这台机器的80端口的对外链接数。但这个数字会影响到代理服务器(nginx)对app服务器的最大链接数,由于nginx对app是用的异步传输,因此这个环节的链接速度很快,因此堆积的链接就不多。假如nginx对app服务器之间的带宽出了问题或是app服务器有问题,那么可能使链接堆积起来,这时能够经过设定nginx的代理超时时间,来使链接尽快释放掉,通常来讲极少能用到28232个链接。

相关文章
相关标签/搜索