http://itindex.net/detail/50213-%E6%9C%8D%E5%8A%A1%E5%99%A8-time_wait-close_waithtml
http://itindex.net/detail/47690-time_wait-tcp-%E6%80%A7%E8%83%BDmysql
http://itindex.net/detail/50143-time_wait-socket-time_waitnginx
http://itindex.net/detail/53528-nginx-time_waitweb
http://itindex.net/detail/53493-tcp-ip-time_waitsql
系统上线以后,经过以下语句查看服务器时,发现有很多TIME_WAIT和CLOSE_WAIT。windows
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]}'
打印显示以下:cookie
TIME_WAIT 297 ESTABLISHED 53 CLOSE_WAIT 5
TIME_WAIT:表示主动关闭,经过优化系统内核参数可容易解决。网络
CLOSE_WAIT:表示被动关闭,须要从程序自己出发。数据结构
ESTABLISHED:表示正在通讯
经过上网了解,总结以下:
1、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
2、CLOSE_WAIT(须要从程序自己出发)
TCP状态转移要点
TCP协议规定,对于已经创建的链接,网络双方要进行四次握手才能成功断开链接,若是缺乏了其中某个步骤,将会使链接处于假死状态,链接自己占用的资源不会被释放。网络服务器程序要同时管理大量链接,因此颇有必要保证无用链接彻底断开,不然大量僵死的链接会浪费许多服务器资源.
客户端TCP状态迁移:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
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