当前位置: 首页 > 科技观察

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

时间:2023-03-20 10:23:01 科技观察

写在开头。大约在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(最大包生存时间)的2倍TIME_WAIT状态:在TCP连接中,状态出现主动关闭连接的一方;(收到FIN命令,进入TIME_WAIT状态,返回ACK命令)保持2MSL时间,即4分钟;(MSL为2分钟)解决上述问题大量time_wait状态存在,导致新建连接失败,一般解决方法:Client,HTTP请求的header,连接设置tokeep-alive,保持存活一段时间:目前的浏览器一般都是这样做的。服务器允许重用处于time_wait状态的套接字,以减少time_wait时间,并将其设置为1MSL(即2分钟)。总结:几个核心点time_wait状态影响:在一个TCP连接中,“主动发起关闭连接”的一端会进入time_wait状态。默认情况下,time_wait状态将持续2MSL(最大数据包生命周期)。一般为2x2minstime_wait状态下TCP连接占用的端口。,不能复用的TCP端口数,上限为6.5w(65535,16位)存在大量time_wait状态,会导致新建TCP连接出错,地址已在使用:connect异常现实服务器side,generalsettings:不允许“主动关闭连接”但是在HTTP请求中,http头的connection参数可能设置为close,那么服务器在处理完请求后会主动关闭TCP连接。现在在浏览器中,HTTP请求的连接参数一般设置为keep-aliveNginx反向代理场景可能会出现大量的短链接,服务器端可能会有解决方案。服务器端允许重用处于time_wait状态的套接字,以减少time_wait时间,并将其设置为1MSL(即2分钟)。附录几个方面:查询TCP连接状态的MSL时间TCP三次握手和四次握手附录A:查询TCP连接状态在Mac上,查询TCP连接状态的具体命令://Mac,toqueryTCPconnectionstatus$netstat-nat|grepTIME_WAIT//Mac,查询TCP连接状态,其中-E表示grep或$netstat-nat|grep-E"TIME_WAIT|LocalAddress"ProtoRecv-QSend-QLocalAddressForeignAddress(state)tcp400127的匹配逻辑。0.0.1.1080127.0.0.1.59061TIME_WAIT//统计:各种连接数$netstat-n|awk'/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}'ESTABLISHED1154TIME_WAIT1645附录B:MSL时间MSL,MaximumSegmentLifetime,“PacketmaximumTimetolive”,任何消息在网络上存在的最长时间,超过这个时间消息将被丢弃(IP消息)TCP消息(段)是数据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”一般设置为“不”主动关闭连接”,而服务器通常执行的是“被动关闭”。但是,在HTTP请求中,http头中的连接参数可能设置为close,那么服务器在处理完请求后会主动关闭TCP连接.关于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数据包延迟到达”问题;