在性能测试中,经常会遇到TIME_WAIT过多的问题,这个问题会导致本地端口用满(Linux下默认是65535),从而导致无法创建新的TCP链接,进而无法发出http请求。
在Linux系统中,我们可以使用netstat -nlatp | grep TIME_WAIT | wc -l来统计目前TIME_WAIT的总数量。如果该指标随着时间的增加而不断增加,并且没有减少的迹象,那么就有可能出现TIME_WAIT数量过多的问题。
TIME_WAIT来自于TCP连接断开时,四次挥手的最后一步,主动断开的一方在发送sync后,会处于TIME_WAIT状态,并且持续一段时间(默认是2*mls,即2分钟)。因此在遇到机器上存在大量的TIME_WAIT,那么首先考虑的就是本地的TCP连接主动断开,可以利用wireshark等工具抓取TCP连接,确认本地机器是否发送来代表关闭连接的FIN包。
由于TCP是建立在七层网络结构中的第三层,因此我们在实际应用中很少实际使用,通常而言,在应用层我们使用http连接较多,而http协议就是建立在TCP协议之上的。对于http协议而言,主动断开连接的场景就比较多,最常见的就是http短连接,http1.0协议默认使用短连接,需要显式带着connection:keep-alive的返回头才可以;http1.1协议默认使用长连接,但是,如果返回头带着connection:close,那么即使是使用了http1.1协议,那么请求端也会主动断开连接,这种情况下,请求端就会关闭TCP连接,从而出现大量的TIME_WAIT。
那么为什么使用了http1.1协议,响应端还会带有connection:close的header呢?一般而言分以下两种情况:
1、作为最常用的Web服务器之一,Tomcat对于http长连接的处理有着自己的规则,其中有两个重要的参数:maxKeepAliveRequests和keepAliveTimeout。这两个参数会对tomcat处理长连接的能力进行配置,即如果请求数量大于maxKeepAliveRequests或者长连接持续时间超过keepAliveTimeout,那么tomcat会向访问端发送一个带有connection:close的header,访问端就会主动将http连接进行关闭;如果设置为 1,将会禁用掉 KeepAlive,如果设置为小于 0 的数,KeepAlive 的最大请求数将没有限制。也就是说在 Tomcat 里,默认长连接是打开的,当我们想关闭长连接时,只要将 maxKeepAliveRequests 设置为 1 就可以;
2、如果使用Nginx等反向代理服务器进行中转,那么需注意,在默认情况下,nginx与后端服务器的连接是短连接,如果想要变成长连接的话需要自己进行配置。