TIME_WAIT、CLOSE_WAIT和FIN_WAIT2的那点事

很久很久以前,nginx的upstream还不支持HTTP 1.1的时候,nginx做反响代理时只能使用短链接。设想以下的结构中
CLient–http 1.1 keepalive —>Nginx(proxy)—http 1.1 connection: close–>APP

经常会看到后端APP上有大量的TIME_WAIT状态的链接。这几天又重新读了一下TCP详解和UNP。状态变迁图如下

根据上图如果是客户端先发FIN包主动关闭,服务端其实是不会进入TIME_WAIT状态的

如果是客户端和服务端同时关闭的话,客户端和服务端都会出现TIME_WAIT的状态

apache设置keepalive Off的时候每次都会主动关闭掉,所以TIME_wait的数量非常多。

主要不是客户端完全主动关闭,那么服务端都是会出现这个TIME_WAIT的。

针对apache的keepalive on和off都单独抓包了。

On

Off

以上2图中的客户端都是10.253.85.156
可以清楚的看到当时keepalive设置为on的时候都是客户端先发FIN包,而设置为Off的时候都是服务器端先发FIN包去关闭。

在TCP/IP详解第三卷其实也有说明

今天又发现线上的机器有很多CLOSE_WAIT状态的链接,接近1W个。。
又反复看了下TCP/IP详解的内容。基本定位为本地发起链接去连接远程的8080端口, 远程的服务端在完成了一个调用后主动发起链接关闭发了一个FIN包给本地服务器,然后就没有下文了,就产生了CLOSE_WAIT。。
正常情况下本地服务器需要回一个ACK后再向对远程服务器发一个FIN包,再等到对方回复ACK后才能CLOSE。
为了证实我的猜测我也到这里的“远程服务器“去查看了一下,发现很多链接处于FIN_WAIT2的状态。对于FIN_WAIT2的链接默认会在60s后进行回收,加入特别多的话可以降低tcp_fin_timeout。其实产生CLOSE_WAIT的原因也就是自己没有去调用close来关闭连接。
比如
connfd = accept(listenfd,xxx,xx)后
对这个connfd进行操作完就直接不管了,而对方在完成操作后自己调用了close关闭了链接,这个时候自己就一直处于CLOSE_WAIT的状态,网上有很多说法说这个状态2小时后会被回收,但是实际测试linux根本不会回收的。
叔度的这个blog也提到了类似的问题,这种情况基本都是软件有bug。。

此条目发表在System分类目录。将固定链接加入收藏夹。

发表回复