昨天服务器的应用有开始慢了,
登陆服务器的时候输入 netstat -an|grep mysql
之前有遇到过这种情况
发现存在大量 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 状态。