来源:http://ningg.top/computer-bas...几个方面:问题描述:什么现象?什么作用?问题分析解决方案底层原理1.问题描述模拟一个高并发场景,会出现一批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。2.问题分析大量TIME_WAIT状态的TCP连接存在,本质原因是什么?存在大量的短连接,尤其是在HTTP请求中。如果连接头的值设置为关闭,“服务器”将发起连接的主动关闭。在TCP四次挥手关闭连接的机制中,为了保证重发ACK和丢弃延迟数据,将time_wait设置为MSL(Maximummessagesurvivaltime)的2倍TIME_WAIT状态:在TCP连接中,状态出现主动关闭连接的一方;(收到FIN指令,进入TIME_WAIT状态,返回ACK指令)保持2MSL时间,即4分钟;(MSL为2分钟)三、解决方案针对上述time_wait状态大量存在,导致新建连接失败的问题,一般解决方案:1.客户端,HTTP请求的header,设置connectiontokeep-alive,并保持存活一段时间:目前的浏览器一般都是这样做的,具体可以参考:https://www.cnblogs.com/yjf51...结论:几个核心点1.time_wait状态的影响:在一个TCP连接中,“主动主动关闭连接”的一端会进入time_wait状态time_wait状态,默认会持续2MSL(消息的最大生命周期),一般为2x2minstime_wait状态,TCP连接占用的端口不能再次使用TCP端口数,上限为6.5w(65535,16位)大量time_wait状态如果存在,会导致新建TCP连接时出错,addressalreadyinuse:connect异常2.真实场景:服务器端,一般设置:不允许“主动关闭连接”,但是在http请求中,http头中的connection参数可能设置为close,那么,服务器处理完请求后会主动关闭TCP连接现在在浏览器中,HTTP请求连接参数一般设置为keep-aliveNginx反向代理场景,可能存在大量短链接,服务器可能存在3.解决方案:服务器端,允许time_wait重用status中的socket,减少time_wait时间,设置为1MSL(即2分钟)。查询TCP连接状态的具体命令://Mac,查询TCP连接状态$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-?|awk'/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}'`ESTABLISHED1154`TIME_WAIT1645附录B:MSL时间MSL,最大段生命周期,"消息的最大生存期是任何消息在网络上存在的最长时间,过了这个时间,消息将被丢弃(IP消息),TCP消息(segment)是ip数据报(datagram)的数据部分。Tips:RFC793规定MSL为2分钟,实际应用中常用30秒、1分钟、2分钟2MSL,TCP的TIME_WAIT状态,也称为2MSL等待状态:当TCP的一端发起主动shutdown(收到FIN请求),在发送完最后一个ACK响应后,也就是第三次握手完成后,第四次握手发送ACK包后,进入TIME_WAIT状态。必须在这个状态停留2次MSL时间,等待2MSL时间的主要目的是防止对方收到最后一个ACK包,然后对方会在超时后重发第三次握手的FIN包,并主动关闭终端接收重发.在FIN数据包之后,您可以发送另一个ACK??响应数据包。在TIME_WAIT状态下,两端端口都不能使用,只能在2MSL时间结束后才能使用。(IP层)当连接处于2MSL等待阶段时,任何迟到的报文段都将被丢弃。但在实际应用中,可以通过设置“SO_REUSEADDR选项”,而无需等待2MSL时间结束就可以使用占用的端口。附录C:TCP三次握手和四次握手详解,参考:TCP三次握手和四次握手(详细+动画)具体示意图:三次握手,四次握手建立连接时,以及连接释放过程中的几个核心问题:1.time_wait是“服务器端”的状态吗?或“客户”状态?RE:time_wait是“主动关闭TCP连接”的一方的状态,可能是“客户端”,也可能是“服务器端”。一般情况下,是“客户端”的状态;设置“不主动关闭连接”2、服务端对外服务时,断开连接是否由“客户端”发起?还是“服务器”发起的断开连接?一般情况下,断开是由“客户端”发起的。“服务器”一般设置为“不主动关闭连接”,服务器通常执行“被动关闭”。但是在HTTP请求中,http头中的connection参数可能设置为close,那么服务器在处理完请求后会主动关闭TCP连接。Apachehttpd服务器的相关配置参考:https://elf8848.iteye.com/blo...关于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:1、TCP连接建立后,“主动关闭连接”的一端收到对方的FIN请求后会处于time_wait状态,并发送ACK响应;2、time_wait状态的必要性:TCP完全终止双工连接的可靠实现:在四次挥手关闭TCP连接的过程中,“主动关闭连接”结束发送最后一个ACK。如果这个ACK丢失,对方会重新发送FIN请求。在“connection”部分,需要维护一个time_wait状态来处理对方重新发送的FIN请求;处理延迟数据包:由于路由器可能抖动,TCP数据包会延迟到达,为了避免“延迟的TCP数据包”被误认为是“新的TCP连接”数据,之前需要保持不可用状态允许创建新的TCP连接,并等待所有延迟消息消失。一般设置为MSL(消息的最大生存期)的2倍),解决“TCP包延迟到达”的问题;近期热点文章推荐:1.1000+Java面试题及答案(2021最新版)花样真香!!3.操!Java中xx≠null的新语法是什么?4、SpringBoot2.5发布,深色模式太炸了!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!
