高并发服务器的TIME_WAIT问题

这里探讨一下由于并发过大导致大量TIME_WAIT的问题以及解决办法

要说明TIME_WAIT的问题,需要解答以下几个问题:

1. Peer两端,哪一端会进入TIME_WAIT呢?为什么?

相信大家都知道,TCP主动关闭连接的那一方会最后进入TIME_WAIT。那么怎么界定主动关闭方呢?是否主动关闭是由FIN包的先后决定的,就是在自己没收到对端Peer的FIN包之前自己发出了FIN包,那么自己就是主动关闭连接的那一方?Peer两边都是主动关闭的一方,两边都会进入TIME_WAIT。为什么是主动关闭的一方进行TIME_WAIT呢,被动关闭的进入TIME_WAIT可以不呢?

我们来看看TCP四次挥手可以简单分为下面三个过程:
过程一:主动关闭方发送FIN;
过程二:被动关闭方收到主动关闭方的FIN后发送该FIN的ACK,被动关闭方发送FIN;
过程三:主动关闭方收到被动关闭方的FIN后发送该FIN的ACK,被动关闭方等待自己FIN的ACK。

问题就在过程三中,据TCP协议规范,不对ACK进行ACK,如果主动关闭方不进入TIME_WAIT,那么主动关闭方在发送完ACK就走了的话,如果最后发送的ACK在路由过程中丢掉了,最后没能到被动关闭方,这个时候被动关闭方没收到自己FIN的ACK就不能关闭连接,接着被动关闭方会超时重发FIN包,但是这个时候已经没有对端会给该FIN回ACK,被动关闭方就无法正常关闭连接了,所以主动关闭方需要进入TIME_WAIT以便能够重发丢掉的被动关闭方FIN的ACK。

2. IME_WAIT状态是用来解决或避免什么问题呢?

TIME_WAIT主要是用来解决以下几个问题:

  1. 上面解释为什么主动关闭方需要进入TIME_WAIT状态中提到的: 主动关闭方需要进入TIME_WAIT以便能够重发丢掉的被动关闭方FIN包的ACK。如果主动关闭方不进入TIME_WAIT,那么在主动关闭方对被动关闭方FIN包的ACK丢失了的时候,被动关闭方由于没收到自己FIN的ACK,会进行重传FIN包,这个FIN包到主动关闭方后,由于这个连接已经不存在于主动关闭方了,这个时候主动关闭方无法识别这个FIN包,协议栈会认为对方疯了,都还没建立连接你给我来个FIN包?,于是回复一个RST包给被动关闭方,被动关闭方就会收到一个错误(我们见的比较多的:connect reset by peer,这里顺便说下 Broken pipe,在收到RST包的时候,还往这个连接写数据,就会收到 Broken pipe错误了),原本应该正常关闭的连接,给我来个错误,很难让人接受;
  2. 防止已经断开的连接1中在链路中残留的FIN包终止掉新的连接2(重用了连接1的所有的5元素(源IP,目的IP,TCP,源端口,目的端口)),这个概率比较低,因为涉及到一个匹配问题,迟到的FIN分段的序列号必须落在连接2的一方的期望序列号范围之内,虽然概率低,但是确实可能发生,因为初始序列号都是随机产生的,并且这个序列号是32位的,会回绕;
  3. 防止链路上已经关闭的连接的残余数据包(a lost duplicate packet or a wandering duplicate packet) 干扰正常的数据包,造成数据流的不正常。这个问题和2)类似。
3.TIME_WAIT会带来哪些问题呢?

TIME_WAIT带来的问题注意是源于:一个连接进入TIME_WAIT状态后需要等待2*MSL(一般是1到4分钟)那么长的时间才能断开连接释放连接占用的资源,会造成以下问题:

1) 作为服务器,短时间内关闭了大量的Client连接,就会造成服务器上出现大量的TIME_WAIT连接,占据大量的tuple,严重消耗着服务器的资源;
2) 作为客户端,短时间内大量的短连接,会大量消耗的Client机器的端口,毕竟端口只有65535个,端口被耗尽了,后续就无法在发起新的连接了。

( 由于上面两个问题,作为客户端需要连本机的一个服务的时候,首选UNIX域套接字而不是TCP )。

TIME_WAIT很令人头疼,很多问题是由TIME_WAIT造成的,但是TIME_WAIT又不是多余的不能简单将TIME_WAIT去掉,那么怎么来解决或缓解TIME_WAIT问题呢?可以进行TIME_WAIT的快速回收和重用来缓解TIME_WAIT的问题。有没一些清掉TIME_WAIT的技巧呢?

问题一:kernel: TCP: time wait bucket table overflow

首先作为这里作为一台反向代理服务器,日常承载大量的请求和高并发
在这里插入图片描述
由于 net.ipv4.tcp_max_tw_buckets 过小 出现:
在这里插入图片描述
解决方法:增大 net.ipv4.tcp_max_tw_buckets
表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。

问题二:端口占满

在这里插入图片描述
这里因为要记录post体所以转发到本地的localhost:xxxx,但是也因此导致端口用尽无法再申请端口,导致业务502偶现。
解决方法:net.ipv4.tcp_tw_reuse = 1
允许timewait状态占用端口还可以用到新建的连接中

这里提供一些可以优化的参数
描述内核参数参考设置
增大处于TIME_WAIT状态的连接数net.ipv4.tcp_max_tw_buckets1048576
增大连接跟踪表的大小net.netfilter.nf_conntrack_max1048576
缩短连接跟踪表中处于TIME_WAIT状态连接的超时时间net.netfilter.nf_conntrack_tcp_timeout_time_wait30
允许TIME_WAIT状态占用端口还可以用到新建的连接中net.ipv4.tcp_tw_reuse1
增大本地端口号的范围net.ipv4.ip_local_port_range10000 65000

参考文档:https://cloud.tencent.com/developer/article/1004327

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值