昨天遇到这么一个问题,还是找啦好久才找到原因。在qa测试环境,后端有一个任务调度,时不时的调度不起来。随着逻辑找了好久,发现业务逻辑并没有错,只是取出数据有问题,一会能取出数据,一会取不出数据,但是sql语句是一样的。十分疑惑,最初以为是mysql压力过大导致的。进入数据库查看 show processlist 后如下显示:
其实就这么一点一些个处于睡眠中的查询并不会造成问题。所以排除了数据库的压力问题,就断定那就是数据库链接有问题,查看了,数据链接的log,果然报错,照着报错百度了一下,找到了答案。
为什么会mysql一会链接失败呢,是因为TCP建立链接时TimeWait过多导致的,都被占用了,所以mysql会在段时间内链接不上。以下是一个截图:
netstat -anlpt | grep TIME_WAIT | wc -l
这条命令就是查看到了,这台服务器已经有3万多个进入time_wait。
紧接着执行:netstat -anlpt | grep TIME_WAIT
会看到3306的非常之多,所以问题的导致是服务器TCP连接TimeWait过多,导致。
找了运维一起看看,运维的意思是确实是这样的问题。处理方式是:
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释放出了几千个出来,这样问题就不存在了。