博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux服务器 大量的CLOSE_WAIT、TIME_WAIT解决办法
阅读量:5758 次
发布时间:2019-06-18

本文共 6366 字,大约阅读时间需要 21 分钟。

http://itindex.net/detail/50213-%E6%9C%8D%E5%8A%A1%E5%99%A8-time_wait-close_wait

http://itindex.net/detail/47690-time_wait-tcp-%E6%80%A7%E8%83%BD

http://itindex.net/detail/50143-time_wait-socket-time_wait

http://itindex.net/detail/53528-nginx-time_wait

http://itindex.net/detail/53493-tcp-ip-time_wait

系统上线之后,通过如下语句查看服务器时,发现有不少TIME_WAIT和CLOSE_WAIT。

  netstat -an | awk '{print $6}' | sort | uniq -c | sort -rn

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

 

打印显示如下:

TIME_WAIT 297ESTABLISHED 53CLOSE_WAIT 5

 

     TIME_WAIT:表示主动关闭,通过优化系统内核参数可容易解决。

     CLOSE_WAIT:表示被动关闭,需要从程序本身出发。

     ESTABLISHED:表示正在通信

 

    通过上网了解,总结如下:

 

一、TIME_WAIT(通过优化系统内核参数可容易解决)

       TIME_WAIT是主动关闭连接的一方保持的状态,对于服务器来说它本身就是“客户端”,在完成一个爬取任务之后,它就会发起主动关闭连接,从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定的,主要出于以下两个方面的考虑:

        1.防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)

        2.可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

        解决方案很简单,通过修改/etc/sysctl.conf文件,服务器能够快速回收和重用那些TIME_WAIT的资源  

        

#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭  net.ipv4.tcp_syncookies = 1  #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭  net.ipv4.tcp_tw_reuse = 1  #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭  net.ipv4.tcp_tw_recycle = 1#表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间  net.ipv4.tcp_fin_timeout=30

 

        生效,如下命令        

/sbin/sysctl -p

           

 

 

二、CLOSE_WAIT(需要从程序本身出发)

       TCP状态转移要点

       TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。网络服务器程序要同时管理大量连接,所以很有必要保证无用连接完全断开,否则大量僵死的连接会浪费许多服务器资源.

        客户端TCP状态迁移:        

CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
     
         服务器TCP状态迁移:      
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

       当客户端开始连接时,服务器还处于LISTENING,客户端发一个SYN包后,他就处于SYN_SENT状态,服务器就处于SYS收到状态,然后互相确认进入连接状态ESTABLISHED。

 

       TIME_WAIT状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况是服务器自己可控的,要么就是对方连接的异常,要么就是自己没有迅速回收资源,总之不是由于自己程序错误导致的。

        但是CLOSE_WAIT就不一样了,如果一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方关闭连接之后服务器程序自己没有进一步发出ack信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。个人觉得这种情况,通过服务器内核参数也没办法解决,服务器对于程序抢占的资源没有主动回收的权利,除非终止程序运行。

       什么情况下,连接处于CLOSE_WAIT状态呢?

       答案一:在被动关闭连接情况下,在已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。通常来讲,CLOSE_WAIT状态的持续时间应该很短,正如SYN_RCVD状态。但是在一些特殊情况下,就会出现连接长时间处于CLOSE_WAIT状态的情况。

        答案二:出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。

-----------------------------------------------------------------------------------------------

http://www.cnblogs.com/sunxucool/p/3449068.html

http://my.oschina.net/foxidea/blog/91431?fromerr=KjV5Lqr3

发现存在大量TIME_WAIT状态的连接

tcp        0      0 127.0.0.1:3306              127.0.0.1:41378             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:41379             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:39352             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:39350             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:35763             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:39372             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:39373             TIME_WAIT
tcp        0      0 127.0.0.1:3306              127.0.0.1:41176             TIME_WAIT
 
 
 
通过调整内核参数解决
vi /etc/sysctl.conf
编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
 
然后执行/sbin/sysctl -p让参数生效。
 
net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout修改系統默认的TIMEOUT时间
 
修改之后,再用命令查看TIME_WAIT连接数
netstat -ae|grep “TIME_WAIT” |wc –l
   发现大量的TIME_WAIT 已不存在,mysql进程的占用率很快就降下来的,网站访问正常。
 不过很多时候,出现大量的TIME_WAIT状态的连接,往往是因为网站程序代码中没有使用mysql.colse(),才导致大量的mysql  TIME_WAIT.
 
  如果你的服务器是Windows平台,可以修改下面的注册表键值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
"TcpTimedWaitDelay"=dword:0000001e
此值是TIME_WAIT状态的最长时间。缺省为240秒,最低为30秒,最高为300秒。建议为30秒。
 
注释:
1,TCP结束的过程如下:
Server                             Client
-------------- FIN -------------->  server: fin_wait_1
<------------- ACK --------------- client: close_wait  server:fin_wait_2
<------------- FIN  --------------- client发出fin之后就关闭
-------------- ACK ------------->  server发出ack后进入time_wait状态
Time_Wait的默认时间是2倍的MLS,就是240秒钟。MLS是TCP片在网上的最长存活时间。
TIME_Wait的主要作用是保证关闭的TCP端口不立即被使用。因为当网络存在延迟时,可能当某个端口被关闭后,网络中还有一些重传的TCP片在发向这个端口,如果这个端口立即建立新的TCP连接,则可能会有影响。所以使用2倍的MSL时间来限制这个端口立即被使用。
现在的问题在于,4分钟的时间有点长。
因此,Time_wait的影响,我想,首先每个TCP连接都各自有个数据结构,叫TCP Control Block.Time_wait的时候这个数据结构没有被释放。所以当有太多的TCP连接时,内存可能会被占用很多。
 
 
 
2,To ValorZ:TIME_WAIT状态也称为2MSL等待状态,而不是2MLS,笔误吧!
每个TCP报文在网络内的最长时间,就称为MSL(Maximum Segment Lifetime),它的作用和IP数据包的TTL类似。
RFC793指出,MSL的值是2分钟,但是在实际的实现中,常用的值有以下三种:30秒,1分钟,2分钟。
注意一个问题,进入TIME_WAIT状态的一般情况下是客户端,大多数服务器端一般执行被动关闭,不会进入TIME_WAIT状态,当在服务器端关闭某个服务再重新启动时,它是会进入TIME_WAIT状态的。
举例:
1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。

2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连接还处于TIME_WAIT状态。

 

 

windows

 

TcpTimedWaitDelay和MaxUserPort设置
描述:确定 TCP/IP 可释放已关闭连接并重用其资源前,必须经过的时间。
关闭和释放之间的此时间间隔通称 TIME_WAIT 状态或两倍最大段生命周期(2MSL)状态。
此时间期间,重新打开到客户机和服务器的连接的成本少于建立新连接。
减少此条目的值允许 TCP/IP 更快地释放已关闭的连接,为新连接提供更多资源。如果运行的应用程序需要快速释放和创建新连接,而且由于 TIME_WAIT 中存在很多连接,导致低吞吐量,则调整此参数。
如何查看或设置: 使用 regedit 命令访问 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters 注册表子键并创建名为 TcpTimedWaitDelay 的新 REG_DWORD 值。
将此值设置为十进制 30,其为十六进制 0x0000001e。
该值将等待时间设置为 30 秒。
停止并重新启动系统。 缺省值:0xF0,它将等待时间设置为 240 秒(4 分钟)。
建议值:最小值为 0x1E,它将等待时间设置为 30 秒。
MaxUserPort 描述:确定在应用程序从系统请求可用用户端口时,TCP/IP 可指定的最高端口号。
如何查看或设置: 使用 regedit 命令访问 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters 注册表子键并创建名为 MaxUserPort 的新 REG_DWORD 值。
停止并重新启动系统。
缺省值:无 建议值:至少十进制 32768。
注:当在 Windows NT 或 Windows 2000 操作系统上调整 WebSphere Application Server 时,同时使用这两个参数。
希望本站的知识能给您的工作、学习和生活带来方便和乐趣!  
 
--------------------------------------------------------------------------------------------------------------
server端tcp连接状态大量TIME_WAIT解决方法:
在脚步中添加:
/*保证迭代结束后关闭所有的链接。相应的函数放于下面两个函数之间,迭代后都会关闭连接。
web_set_sockets_option("SHUTDOWN_MODE","ABRUPT");//相当于迭代重置,初始化
............
web_set_sockets_option("CLOSE_KEEPALIVE_CONNECTIONS","1"); //关闭连接
*/
web_set_sockets_option("SHUTDOWN_MODE","ABRUPT");
web_set_sockets_option("SO_REUSE_ADDRESS","1");//端口复用
web_set_sockets_option("OVERLAPPED_SEND","0");//禁用TTFB细分,问题即可解决,但是TTFB细分图将不能再使用.
你可能感兴趣的文章
51Nod 1091:线段的重叠(贪心)
查看>>
《将博客搬至CSDN》
查看>>
五大常用算法之四:回溯法
查看>>
Niagara物联网框架机制一(笔记)
查看>>
Sonar rule for multithread
查看>>
AC自动机学习笔记
查看>>
NO27 定时任务
查看>>
使用 try-catch
查看>>
python多线程编程-queue模块和生产者-消费者问题
查看>>
Quartz 2D 绘图,图像变换
查看>>
BZOJ 1189 [HNOI2007]紧急疏散evacuate
查看>>
sql语句中select……as的用法
查看>>
hdu3488 Tour 拆点+二分图最佳匹配
查看>>
设计模式
查看>>
button和submit
查看>>
内嵌iframe
查看>>
将一个Head下的Line复制到另一个Head下(ef+linq)
查看>>
装饰者模式-
查看>>
phpcms v9 csdn老手记录
查看>>
C++调用C#库简单例程
查看>>