tcp通道关闭时,发生了什么? time_wait close_wait
答案:2 悬赏:50 手机版
解决时间 2021-02-08 20:39
- 提问者网友:嘚啵嘚啵
- 2021-02-08 04:29
tcp通道关闭时,发生了什么? time_wait close_wait
最佳答案
- 五星知识达人网友:廢物販賣機
- 2021-02-08 05:02
当第一次遇到这种问题的时候,你可能会有如下的问题:
其实,你真正想问的是:
TCP通道是一个连接,连接的两端都可以向通道里写数据或者从通道里读数据,连接的两端都可以发起关闭操作。整个TCP通道的关闭流程如下:
A(socketfd:10) <——–TCP Connction ———-B(socketfd:20)
关闭A,则A向B发送FIN;
如果程序显式的关闭了B,那么B会向A发送一个FIN,然后B就处于LAST_ACK状态了;
A在接受到B的FIN后,发出最后一个ACK,此时A就处于知名的TIME_WAIT状态了。TIME_WAIT时间一般会比较长。
尽量避免TIME_WAIT过多的一端主动关闭socket
使用SocketPool,避免频繁创建/关闭socket
提到Thrift ThreadPoolServer有时候会出现较多的close wait状态,有朋友问我这是不是thrift的bug?写过Server比较多的同志们应该能意识到这个问题的原因,不值得说,可是我今天实在是太郁闷无聊了,我就写写我的想法吧。
我觉得这当然不能算是Thrift的Bug,如果出现了这样的问题,其实是因为错误的选择了Server的类型,错误的实现了Client,过于保守的Server Max Connection配置等等原因。
对于ThreadPoolServer而言,每一个客户端连接,Server端都需要提供一个固定的线程来维护,在空闲时,线程堵塞在read()操作,等待客户端数据的到来。Thrift ThreadPoolServer中使用的默认线程池是定长线程池,意味着Server端能提供的线程池数是有限的。当线程用完时,新的连接将不能得到Server殷勤的服务,它不会在乎你的生死,你必须等待。
Server会接受这个连接,连接成功建立;
Server没有合适的线程来处理这个连接,于是将这个连接放到暂存列表;
如果这个时候有线程空闲了,则一切顺利,这个线程将接管这个连接;
但遗憾的是,我们没有空闲线程,所以这个连接一直处于空闲状态,直到客户端程序timeout(如果设置了timeout的话);
连接timeout,意味着暂存列表里的连接已经失效了,此时对应的socket处于CLOSE_WAIT中(出现了本文开头的情况),遗憾的是,我们依然没有空闲的线程来处理这个连接,所以它一直处于CLOSE_WAIT中。
终于,某一个时刻,有一个客户端关闭了连接,我们有了空闲线程,它去查看暂存列表。发现有一个socket fd,尝试去接管它,对这个fd执行read(),然后得到一个Connection Reset error,终于,我们可以优雅的关闭它了(CLOSE_WAIT结束)。
以上就是全部的故事。
其实,你真正想问的是:
TCP通道是一个连接,连接的两端都可以向通道里写数据或者从通道里读数据,连接的两端都可以发起关闭操作。整个TCP通道的关闭流程如下:
A(socketfd:10) <——–TCP Connction ———-B(socketfd:20)
关闭A,则A向B发送FIN;
如果程序显式的关闭了B,那么B会向A发送一个FIN,然后B就处于LAST_ACK状态了;
A在接受到B的FIN后,发出最后一个ACK,此时A就处于知名的TIME_WAIT状态了。TIME_WAIT时间一般会比较长。
尽量避免TIME_WAIT过多的一端主动关闭socket
使用SocketPool,避免频繁创建/关闭socket
提到Thrift ThreadPoolServer有时候会出现较多的close wait状态,有朋友问我这是不是thrift的bug?写过Server比较多的同志们应该能意识到这个问题的原因,不值得说,可是我今天实在是太郁闷无聊了,我就写写我的想法吧。
我觉得这当然不能算是Thrift的Bug,如果出现了这样的问题,其实是因为错误的选择了Server的类型,错误的实现了Client,过于保守的Server Max Connection配置等等原因。
对于ThreadPoolServer而言,每一个客户端连接,Server端都需要提供一个固定的线程来维护,在空闲时,线程堵塞在read()操作,等待客户端数据的到来。Thrift ThreadPoolServer中使用的默认线程池是定长线程池,意味着Server端能提供的线程池数是有限的。当线程用完时,新的连接将不能得到Server殷勤的服务,它不会在乎你的生死,你必须等待。
Server会接受这个连接,连接成功建立;
Server没有合适的线程来处理这个连接,于是将这个连接放到暂存列表;
如果这个时候有线程空闲了,则一切顺利,这个线程将接管这个连接;
但遗憾的是,我们没有空闲线程,所以这个连接一直处于空闲状态,直到客户端程序timeout(如果设置了timeout的话);
连接timeout,意味着暂存列表里的连接已经失效了,此时对应的socket处于CLOSE_WAIT中(出现了本文开头的情况),遗憾的是,我们依然没有空闲的线程来处理这个连接,所以它一直处于CLOSE_WAIT中。
终于,某一个时刻,有一个客户端关闭了连接,我们有了空闲线程,它去查看暂存列表。发现有一个socket fd,尝试去接管它,对这个fd执行read(),然后得到一个Connection Reset error,终于,我们可以优雅的关闭它了(CLOSE_WAIT结束)。
以上就是全部的故事。
全部回答
- 1楼网友:鸠书
- 2021-02-08 06:31
解决close_wait的方法:
1 一般原因都是tcp连接没有调用关闭方法。需要应用来处理网络链接关闭。
2 对于web请求出现这个原因,经常是因为response的bodystream没有调用close.
比如widnows下:
使用httpwebrequest 一定要保证getrequeststream和getresponse对象关闭,否则容易造成连接处于close_wait状态
3 tcp的keeplive功能,可以让操作系统替我们自动清理掉close_wait的连接。
但是keeplive在windows操作系统下默认是7200秒,也就是2个小时才清理一次。往往满足不了要求。可以调小该数值。
windows下的调整方法为
hkey_local_machine/currentcontrolset/services/tcpip/parameters下的以下三个参数:
keepaliveinterval,设置其值为1000 www.2cto.com
keepalivetime,设置其值为300000(单位为毫秒,300000代表5分钟)
tcpmaxdataretransmissions,设置其值为5
close_wait引发的问题:
close_wait会占用一个连接,网络可用连接小。数量过多,可能会引起网络性能下降,并占用系统非换页内存。 尤其是在有连接池的情况下(比如httprequest)
会耗尽连接池的网络连接数,导致无法建立网络连接。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯