背景
前几天同事迁移数据库到新服务器上,启动后第二天发现系统登录不上,查看Java程序日志报错’host_name’ is blocked because of many connection errors.Unblock with ‘mysqladmin flush-hosts’,因为是周末,简单查了一下,发现直接说执行flush hosts
就可以解决,就临时处理了一下,果然可以。顺带看了一下原因说是错误的连接数太多,想着排查也麻烦,就不管了,但后续上班又发现出现了问题,于是研究了半天。
研究思路
日志
查看各种日志,包括mysql,应用程序
mysql日志
less /var/log/mysqld.log
# shift g 跳转到最后
# 看到了一些bad handshake提示,其他的没什么特殊的了
应用程序
找到自己部署的程序上的日志,一样的方式查看,只能看到连接的报错,报错内容是
'host_name' is blocked because of many connection errors.Unblock with 'mysqladmin flush-hosts'
顺便百度了一下这个报错,能够关联到max_connect_errors
这个参数
本质上就是每次链接报错,connect-error就会+1,当达到设置的最大值,就会出现is blocked because of many connection errors
报错
# 查询报错情况
select * from performance_schema.host_cache;
# 临时解决方案,治标不治本,清空统计次数
flush hosts;
根据上面日志和搜索结果判断就是某个程序链接失败,导致bad handshake
在我flush hosts后,在查询可以观察到错误次数又开始增加了
说明某个程序一直在不间断的发送
查找发请求的程序
根据上面的条件,我只能判断出某个程序有问题,但是确认不了是哪个程序
根据经验,在连接mysql的时候,本地会有一个端口,能够找到这个端口,那就可以找到pid,进而找到是哪个程序
# 找到和服务器3306端口有关的连接
# 但是结果只能查看到正常的连接,没有CLOSE也没有WAIT,都是目前运行正常的
# 猜测是连接失败后直接就关闭了
ss -ano | grep '10.68.1.20:3306'
# 利用tcpdump监控
# -i enp4s1 指定网卡
# -n 过滤 指定ip为10.68.6.62,端口3306, 状态异常的
# 能够查看到一直在往3306发数据,端口号也有
# 但是ss根据端口号查pid却查不到
tcpdump -i enp4s1 -n host 10.68.6.62 and port 3306 and 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'
# 使用-w导出pcap包,放到wireshark查看
# 分析后可以看到是发了一个登陆请求,但是username为空
tcpdump -i enp4s1 -n host 10.68.6.62 and port 3306 -w mysql.pcap
![](https://i-blog.csdnimg.cn/blog_migrate/cc1656562639cb1fff54893352fcffc7.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/a77014a018c9d888091d2051cc44b0bf.jpeg)
从上面可以进一步确定一直在发登陆包,但是仍然无法确定是哪个程序发起的
能够拿到端口号,但是等我去ss查看的时候已经关闭了,猜测如果够快就可以监听到
但是我用watch 0.1s也无法获取到,就放弃这个思路了
了解到iftop可以监控网络情况
# 查看发往目标ip的流量情况
# 一样可以看到端口,可以看到一直在请求,流量一直在加
# 但是仍然无法看到pid,iftop并不能筛选出哪一个程序发起的请求
iftop -pP -N -f "dst host 10.68.6.62"
最后一个思路,利用strace
# strace可以跟踪系统调用,因此可以很详细看到网络情况,最主要是,可以根据pid过滤
# -e trace指定network,输出网络相关的
# -o 指定输出文件
# -p pid
# 那这个pid,怎么找呢。。。
# 我用的老办法,观察几个可能的程序
# 目前服务器都是java类的,使用jps查看,就几个
# 把这几个pid一个一个输进去查看,结果第二个就出结果了
strace -f -e trace=network -o 245484.log -p 245484
这张图片不是实际的,只是随便找了个测试,大概效果就这样,可以看到ip和端口都是对的
由此确实是哪一个程序在发送
收尾
确认是哪一个程序以后
# 通过pid确认程序位置
# 发现是一个jar包
ps -ef | grep pid
# 找到jar包位置
find / -name 'xxx.jar'
# 查看jar包的日志,并解压jar包查看配置文件
# 是一个SpringBoot,但是没有配置数据库账号密码
前面一开始其实就已经利用了jps查看到了有2个jar包,也观察了日志,但是看漏了(doge
总结
学习了各个网络工具的使用,以及排查网络问题的思路
但是不确定是否有更优解,有待学习
另外看日志确实要看完整一点,一开始其实已经用jps发现了有问题的jar,但是看日志看漏了
期间还遇到一点,系统是centos8没有装工具
下载工具的时候发现yum无法下载元数据
可能是centos8停止维护的原因,换了各种源都不行
最后也没解决,直接下载了rpm包安装