linux下TIME_WAIT过多的解决办法(ip_local_port_range)(转)

时间:2022-06-16 15:22:42
p.s. 最近nginx不正常,表现为首次打开的时候会很慢或者干脆打不开,要刷新下才能继续。fast-cgi的TIME_WAIT比较多5百左右,占到总连接 4分之1。试试是不是ip_local_port_range问题,原则就是不与本地已经使用的端口范围冲突,设置端口 2**** 到 4**** 。 (重启系统需要重新设置)


如 果使用了nginx代理,那么系统TIME_WAIT的数量会变得比较多,这是由于nginx代理使用了短链接的方式和后端交互的原因,使得nginx 和后端的ESTABLISHED变得很少而TIME_WAIT很多。这不但发生在安装nginx的代理服务器上,而且也会使后端的app服务器上有大量的 TIME_WAIT。查阅TIME_WAIT资料,发现这个状态很多也没什么大问题,但可能因为它占用了系统过多的端口,导致后续的请求无法获取端口而造 成障碍。


虽然TIME_WAIT会造成一些问题,但是要完全枪毙掉它也是不正当的,虽然看起来这么做没什么错。具体可看这篇文档:


http://hi.baidu.com/tim_bi/blog/item/35b005d784ca91d5a044df1d.html


所以目前看来最好的办法是让每个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个连接。


因为有软件使用了40000端口监听,常常出错的话,可以通过设定ip_local_port_range的最小值来解决:


echo "40001 61000" > /proc/sys/net/ipv4/ip_local_port_range


但是这么做很显然把系统可用端口数减少了,这时可以把ip_local_port_range的最大值往上调,但是好习惯是使用不超过32768的端口来侦听服务,另外也不必要去修改ip_local_port_range数值成1024 65535之类的,意义不大。


因为使用了nginx代理,在windows下也会造成大量TIME_WAIT,当然windows也可以调整:


在注册表(regedit)的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,值就是秒数,即可。


windows默认是重用TIME_WAIT,我现在还不知道怎么改成不重用的,本地端口也没查到是什么值,但这些都关系不大,都可以按系统默认运作。


可以看看这篇文档:http://morganchengmo.spaces.live.com/blog/cns!9950CE918939932E!1721.entry




修改ip_local_port_range的方法
引用
[配置开机自动启动Nginx + PHP + MySQL]
# vi /etc/rc.local


在末尾增加以下内容:
/bin/sh /usr/local/webserver/mysql/bin/mysqld_safe --defaults-file=/usr/local/webserver/mysql/my.cnf &
ulimit -SHn 51200
/usr/local/webserver/php/sbin/php-fpm start
/usr/local/webserver/nginx/sbin/nginx


[优化Linux内核参数]
# vi /etc/sysctl.conf


在文件末尾增加以下内容:
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000 65000
# /sbin/sysctl -p


↑ 使配置立即生效





以下为推荐在etc/sysctl.conf里加入

net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024 65000