昨天上班过来,像往常一样打开线上记录日志,突然发现大量的 “(HY000/2003): Can't connect to MySQL server” 信息。
第一反应就是:
1、网络的波动
2、MySQL服务提供商出了问题(线上MySQL服务是使用第三方云服务商)
3、代码里面未执行 mysql.close()
猜测到原因后,立即排查。对于第一条,使用ping 命令
ping xxx.xxx.xxx.xxx # MySQL服务器地址
与此同时,询问第三方云服务商MySQL情况。根据其反馈的信息知道MySQL服务是正常的,并提出了一个可能性:TIME_WAIT。
看了下ping的信息,并无异常,继续ping。然后去根据报错信息查看对应代码,检查使用MySQL上下文处代码,仔细检查后确认使用完MySQL并 close了。
既然有 TIME_WAIT 的可能性,那就不能错过。执行以下命令
netstat -ae | grep 'TIME_WAIT' | wc -l
最后的结果是:六万左右。(当时排查问题时忘记截图)
瞬间觉得不对劲,为了保险起见,输入以下命令
netstat -ae | grep mysql | grep 'TIME_WAIT' | wc -l
得到的结果与上面稍微小了一点,但依然在六万这个量。
查阅相关资料,修改了下面四个参数
vi /etc/sysctl.conf
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 = 30 #修改系統默认的TIMEOUT时间;
/sbin/sysctl -p #让参数生效
五秒之后,再执行下面命令,发现其值下降到四万左右
netstat -ae | grep 'TIME_WAIT' | wc -l
几分钟后,其值降到几百左右。
今天早上过来上班,查看日志,直到写此篇博客时,已无MySQL连接不上错误信息。