服务器TIME_WAIT堆积如山?这是我踩过的坑和解决方案
大家好,我是33blog的技术博主。上周我们的生产环境突然出现了一个奇怪的问题:服务器响应变慢,通过netstat -antp
一看,好家伙,TIME_WAIT状态的连接数竟然达到了惊人的3万+!今天我就来分享一下这次排查的全过程。
什么是TIME_WAIT状态?
在TCP四次挥手过程中,主动关闭连接的一方会进入TIME_WAIT状态。这个状态会持续2MSL(Maximum Segment Lifetime,报文最大生存时间,通常为60秒)。
用大白话解释就是:当你的服务器主动关闭连接后,它会在内存里保留这个连接的信息一段时间,防止网络中还有延迟的数据包到达。
为什么会出现大量TIME_WAIT?
根据我的经验,常见原因有:
- 短连接泛滥:每次请求都新建连接,用完就关
- 连接池配置不当:连接池太小导致频繁创建新连接
- 服务器主动关闭连接:比如Nginx默认会主动关闭空闲连接
- TCP参数配置不合理:比如
tcp_tw_reuse
和tcp_tw_recycle
设置不当
我是如何排查的?
首先用这个命令查看TIME_WAIT连接情况:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
输出类似这样:
TIME_WAIT 32456
ESTABLISHED 23
CLOSE_WAIT 5
然后通过lsof -i:端口号
发现大部分都是来自我们的Java应用服务器。进一步检查发现是连接池配置太小(只有10个连接),而QPS有200+,这明显不够用啊!
解决方案
经过多次测试,我采取了以下措施:
- 增大连接池:将连接池大小调整到50
- 启用TCP重用:修改
/etc/sysctl.conf
:net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 # 注意:NAT环境下慎用! net.ipv4.tcp_fin_timeout = 30
- 优化应用代码:确保正确关闭连接,避免泄漏
修改后执行sysctl -p
生效,TIME_WAIT数量很快降到了正常水平。
血泪教训
这里要特别提醒大家:tcp_tw_recycle
在NAT环境下会导致严重问题!我们测试环境就因此出现过连接失败的情况。后来查阅资料才知道,这个参数会基于时间戳拒绝”过时”的报文,而在NAT环境下可能误杀合法连接。
所以我的建议是:生产环境慎用tcp_tw_recycle
,优先考虑增大连接池和设置tcp_tw_reuse
。
总结
遇到TIME_WAIT堆积不要慌,按照这个思路排查:
- 确认是否是短连接导致
- 检查连接池配置
- 合理调整TCP参数
- 监控效果,持续优化
希望我的这次踩坑经历能帮到你们。如果你也遇到过类似问题,欢迎在评论区分享你的解决方案!
遇到过同样的问题!连接池配太小真是太坑了,感谢分享解决方案 👍
想问下大佬,tcp_tw_recycle在云服务器上是不是也会有问题?我们在腾讯云上遇到过
说得很详细!原来NAT环境下tcp_tw_recycle会有问题,学到了 🤔