概述
业务反馈连接数过多有很多种原因,比如:
- 磁盘不够
- 连接数确实不够分配
- 系统连接数太多
- 等等
本文介绍的是由于tcp回收过慢导致的连接数过多问题。
背景:
一天业务开发反馈说最近总是出现时不时连接数据库失败,php现在有时会报 连接数过多。返回too much connections....
排查
登录数据库服务器,第一时间直接查看tcp连接数:
[root@s0001-gz ~]# netstat -nalpt | grep 3306 |wc -l 9093 |
登录数据库服务查看实际连接数:
mysql>show processlist;
....
468 rows
连接数才468个,而设置的max_connection=1000;
一半都达不到,那问题就肯定出在系统的连接数上了。
查看实际的连接用户:
90%全部是TIME_WAIT。
为什么全部是TIME_WAIT呢?
TIME_WAIT是什么?
TIME_WAIT是表示系统在等待客户端响应,以便再次连接时候能快速响应。TCP协议的三次握手中规定发起socket主动关闭的一方 socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime)。我们看下tcp的三次握手机制:
从 上面的示意图可以看得出来,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 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。
快速恢复方法:
编辑文件,加入以下内容:
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_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 时间
查看结果: