当前位置: 首页 > Linux

终于明白为什么服务器会产生很多TIME_WAIT了!

时间:2023-04-06 05:40:14 Linux

写在开头。大约4年前,听过一位运维同学提到的TIME\_WAIT状态下TCP连接过多的问题,但当时并没有仔细思考;因此,在测试过程中遇到的问题,需要花一些时间来详细研究。从这几个方面入手:问题描述:什么现象?什么作用?问题分析解决方案底层原理问题描述模拟一个高并发场景,会出现一批TIME_WAITTCP连接:短时间后,所有TIME_WAIT会消失并被回收,端口包括服务都正常。即在高并发场景下,存在TIME_WAIT连接,属于正常现象。线上场景,在连续高并发场景下,有一部分TIME_WAIT连接被回收,但是又产生了新的TIME_WAIT连接;在某些极端情况下,会出现大量TIME_WAIT连接。思考:上述大量TIME_WAIT状态的TCP连接对业务有影响吗?当Nginx作为反向代理时,大量的短链接可能会导致Nginx上的TCP连接处于time_wait状态:每个time_wait状态都会占用一个“本地端口”,上限为65535(16位,2字节);当大量连接处于time_wait时,建立新的TCP连接时会报错,addressalreadyinuse:connect异常统计TCP连接状态://统计:各种连接数$netstat-n|awk'/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}'ESTABLISHED1154TIME_WAIT1645Tips:TCP本地端口数,上限为65535(6.5w),因为TCP头使用16位,存储“端口号”,所以约束上限为65535。问题分析大量TIME_WAIT状态的TCP连接存在,本质原因是什么?存在大量的短连接,尤其是在HTTP请求中。如果连接头的值设置为关闭,“服务器”将发起连接的主动关闭。在TCP四次挥手关闭连接的机制中,为了保证重发ACK和丢弃延迟数据,将time_wait设置为MSL(Maximummessagesurvivaltime)的2倍TIME_WAIT状态:在TCP连接中,状态出现主动关闭连接的一方;(收到FIN指令,进入TIME_WAIT状态,返回ACK指令)保持2MSL时间,即4分钟;(MSL为2分钟)解决方法是解决上述大量time_wait状态存在,导致无法创建新连接的问题。一般解决方案:客户端,http请求的header,连接设置为keep-alive,保持一段时间:目前的浏览器一般都是这样做的。server端允许重用time_wait状态的socket,减少time_wait时间,设置为1MSL(即2mins)。结语:几个核心点time_wait状态影响:在TCP连接中,“主动发起关闭连接”的一端会进入time_wait状态。默认情况下,time_wait状态将持续2MSL(消息的最大生命周期)。一般为2x2minstime_wait状态下TCP连接占用的端口。不能再次使用的TCP端口数,上限为6.5w(65535,16位)。存在大量的time_wait状态,会导致新建TCP连接出错。closetheconnection”,但是在HTTP请求中,http头的connection参数可能会设置为close,那么服务器在处理完请求后会主动关闭TCP连接。现在在浏览器中,HTTP请求的connection参数一般设置为keep-aliveNginxreverse在proxy场景下,可能会出现大量的短链接,在server端,可能会有解决方案,在server端,允许重用time_wait状态的socket。减少time_wait时间,设置为1MSL(即2mins)附录几个方面:TCP查询连接状态MSL时间TCP三次握手和四次握手附录A:查询TCP连接状态Mac,查询TCP连接状态的具体命令://Mac,查询TCP连接状态$netstat-nat|grepTIME_WAIT//Mac接下来查询TCP连接状态,其中-E表示grep的匹配逻辑或者$netstat-nat|grep-E"TIME_WAIT|LocalAddress"ProtoRecv-QSend-QLocalAddress(state)tcp400001.1080127.0.0.1.59061TIME_WAIT//统计:各种连接数$netstat-n|awk'/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}'ESTABLISHED1154TIME_WAIT1645附录B:MSL时间MSL,MaximumSegmentLifetime,"MaximumSegmentLifetimeofPackets”,任何数据包在网络上存在的最长时间,超过这个时间的数据包将被丢弃(IPpacket)TCP段(segment)是ip数据报(datagram)的数据部分。Tips:RFC793规定MSL为2分钟。在实际应用中,常用30秒、1分钟、2分钟。2MSL,TCP的TIME_WAIT状态,也称为2MSL等待状态:当TCP的一端发起主动关闭(收到FIN请求),发送最后一个ACK响应后,即第三次握手完成后,第四次握手为发送ACK包后,进入TIME_WAIT状态。您必须在此状态下停留两倍的MSL时间。等待2MSL时间的主要目的是防止对方收到最后一个ACK包。然后对方会在超时后重发第三次握手的FIN包,并主动关闭终端接收重发。在FIN数据包之后,您可以发送另一个ACK??响应数据包。在TIME_WAIT状态下,两端端口都不能使用,只能在2MSL时间结束后才能使用。(IP层)当连接处于2MSL等待阶段时,任何迟到的报文段都将被丢弃。但在实际应用中,可以通过设置“SO_REUSEADDR选项”,而无需等待2MSL时间结束就可以使用占用的端口。附录C:TCP三次握手和四次握手,详见:TCP三次握手和四次挥手“status?”还是“client”status?RE:time_wait是“那一边的状态”主动关闭TCP连接”,可能是“客户端”,也可能是“服务器端”。一般情况下,是“客户端”的状态;当设置“不主动关闭连接”时,服务器对外服务,是“client”发起的断开连接?还是“server”发起的断开连接?一般情况下,断开连接都是“client”发起的,“server”一般设置为“do”不主动关闭连接”,服务器通常执行“被动关闭”。但是,在HTTP请求中,http头中的连接参数可能设置为close,那么服务器会在处理完后主动关闭TCP连接request.关于HTTP请求中主动关闭TCP连接的机制:TIME_WAIT只有在一方主动断开时才会出现,那么主动断开的一方是服务器?答案是肯定的。在HTTP1.1协议中,有一个Connection头。Connection有两个值,close和keep-alive。这个头相当于客户端在服务器执行完请求后告诉服务器是关闭连接还是保持连接。保持连接是指在保持连接期间,只有客户端可以主动断开连接。还有一个keep-aliveheader,设置的值代表服务器保持连接的时长。HTTP默认的Connection值是close,也就是说关闭请求的一方几乎都是服务器端发起的。那么服务器产生过多的TIME_WAIT是正常的。虽然HTTP默认的Connection值是close,但是现在的浏览器在发送请求的时候一般都会将Connection设置为keep-alive。所以有人说现在不需要通过调整参数来减少TIME_WAIT。关于time_wait:TCP连接建立后,“主动关闭连接”的一端收到对方的FIN请求后会处于time_wait状态,并发送ACK响应;time_wait状态的必要性:可靠实现TCP全双工连接Termination:在四次挥手关闭TCP连接的过程中,“主动关闭连接”结束发送最后一个ACK。如果这个ACK丢失,对方会重新发送FIN请求。因此,在“主动关闭连接”部分,需要保持一个time_wait状态来处理对方重新发送的FIN请求;处理延迟包:由于路由器抖动,TCP包会延迟到达,为了避免“延迟的TCP包”被误认为是“新的TCP连接”数据,需要保持不可用状态,然后才允许新的TCP连接被创建,并等待所有延迟消息消失。一般设置为MSL(消息的最大生命周期)的2倍,以解决“TCP数据包延迟到达”问题;来源:ningg.top/computer-basic-theory-tcp-time-wait/