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

本文针对使用nginx代理时出现的TIME_WAIT状态较多的问题提供了解决方案。通过调整Linux内核参数,如启用TIME_WAIT重用和加快TIME_WAIT状态的回收,有效缓解了因TIME_WAIT占用大量端口而导致的新连接障碍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

<think>嗯,用户问到了TCP的TIME_WAIT状态过多的原因。首先,我需要回忆一下TCP连接关闭的过程。记得TIME_WAIT出现在主动关闭连接的一方,也就是发送最后一个ACK的那一端。这个状态会持续2MSL(Maximum Segment Lifetime)的时间,通常是2分钟,不过实际可能更短,比如在Linux中默认是60秒。 那为什么会有大量的TIME_WAIT呢?可能的原因有几个。首先,高并发短连接的情况,比如HTTP服务器通常处理大量短连接,每次处理完请求后主动关闭连接,这时候就会积累很多TIME_WAIT。例如,像一些Web服务使用完毕后立即关闭连接,导致主动关闭的一方(服务器)产生大量TIME_WAIT。 其次,是不是客户端也可能出现这个问题?比如,当客户端频繁地连接服务器然后关闭,比如爬虫或者某些客户端应用,这时候如果客户端主动关闭连接,就会产生TIME_WAIT。不过通常服务器端更容易出现,因为处理更多连接。 另外,配置问题也可能导致TIME_WAIT过多。例如,系统参数设置不当,像net.ipv4.tcp_max_tw_buckets限制了TIME_WAIT的数量,如果设置太低,虽然不会增加数量,但可能导致问题。或者有没有开启tcp_tw_reuse或tcp_tw_recycle之类的选项,这些可能会影响TIME_WAIT的处理方式,不过需要注意这些参数在不同系统版本中的效果和潜在问题。 还有,应用设计的问题,比如没有使用连接池或者长连接,导致频繁创建和关闭连接,这样自然会产生大量TIME_WAIT。这种情况下,优化应用设计,复用连接可能有效。 另外,需要考虑的是TIME_WAIT本身是TCP协议的正常机制,它的存在是为了确保最后一个ACK被正确接收,防止旧连接的报文干扰新连接。所以少量的TIME_WAIT是正常的,但过多的话会影响新连接的建立,比如耗尽端口号或占用太多内存。 用户可能是在实际运维中遇到了这个问题,想知道原因和解决办法。需要分情况讨论,是服务器端还是客户端的问题,是否应用设计有优化空间,或者系统参数是否需要调整。同时,需要提醒用户谨慎修改系统参数,因为不当的设置可能引起其他问题,比如NAT环境下的tcp_tw_recycle可能导致连接失败。 总结下来,主要原因可能包括高频率短连接、主动关闭的一方设计、系统配置限制等。解决方案可能涉及优化连接管理、调整内核参数、使用SO_REUSEADDR等选项。不过需要根据具体情况来分析,不能一概而论。</think>TCP 的 **TIME_WAIT** 状态过多通常是由高频短连接场景触发的,以下是常见原因和背后的逻辑: --- ### 1. **短连接高频使用** - **现象**:应用频繁建立 TCP 连接并快速关闭(例如 HTTP 短连接)。 - **原因**:每个连接关闭时,**主动关闭方**(如服务器)会进入 `TIME_WAIT` 状态,持续 `2*MSL`(默认 60 秒,MSL 是报文最大生存时间)。 - **典型场景**: - Web 服务器(如 Nginx)处理大量短请求时主动关闭连接。 - 客户端频繁调用后关闭连接(如爬虫、微服务间调用)。 --- ### 2. **主动关闭方设计不合理** - **问题**:若服务端被设计为主动关闭连接(例如某些 HTTP 服务器配置),会积累 `TIME_WAIT`。 - **优化思路**: - 调整关闭策略(如让客户端主动关闭)。 - 使用 HTTP `Keep-Alive` 保持长连接。 --- ### 3. **系统资源限制** - **端口耗尽**:`TIME_WAIT` 会占用端口资源(每个连接由五元组唯一标识)。 - 客户端高频连接时,端口可能被耗尽(尤其 IPv4 端口范围有限)。 - **内存消耗**:每个 `TIME_WAIT` 连接占用内核内存(通常约 4KB)。 --- ### 4. **内核参数配置** - **相关参数**: - `net.ipv4.tcp_max_tw_buckets`:限制 `TIME_WAIT` 数量上限。 - `net.ipv4.tcp_tw_reuse`:允许复用 `TIME_WAIT` 连接(需协议支持)。 - `net.ipv4.tcp_tw_recycle`:快速回收 `TIME_WAIT`(已废弃,NAT 环境下有风险)。 --- ### 解决方案 1. **优化应用设计** - 使用连接池或长连接(如 HTTP/1.1 Keep-Alive、HTTP/2 多路复用)。 - 避免服务端主动关闭连接(根据场景调整)。 2. **调整内核参数**(需谨慎评估) ```bash # 允许复用 TIME_WAIT 连接(需内核 3.2+,且协议支持时间戳) echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse # 增大端口范围 echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range # 调整 TIME_WAIT 最大数量 echo 5000 > /proc/sys/net/ipv4/tcp_max_tw_buckets ``` 3. **设置 `SO_REUSEADDR`** - 允许绑定处于 `TIME_WAIT` 状态的端口(需应用层支持)。 --- ### 为什么需要 TIME_WAIT? - **确保可靠关闭**:防止最后一个 `ACK` 丢失,导致对端重传 `FIN`。 - **避免旧连接干扰**:确保网络中属于旧连接的报文过期,避免与新连接冲突。 --- ### 总结 `TIME_WAIT` 是 TCP 协议的正常机制,但需在高频短连接场景中合理优化。通过长连接、参数调优或调整关闭策略,可有效减少其影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值