未解之谜
继之前一篇 TCPing 未解之谜 后,又是一个没有完全解决的问题,其实这个 Mysql Ping 连接异常的问题发生在去年,当时接手问题还没分析多长时间,开发同事选择优先恢复业务(改变了 Mysql 部署架构),该问题随着环境改变随之消失,因此无法进一步检测分析,该问题不了了之。
之后断断续续的回想起这个问题,也咨询了各方专家,虽然有那么一丢丢进展,但始终是纯理论,无最终实际环境验证。
用一句话聊以自慰, 网络数据包的世界,不是所有问题都有答案
。
Mysql Ping 连接异常
网络拓扑
简单描述下拓扑,数据中心 A 和 B 之间通过广域网专线互连,中间设备包括多个交换机和防火墙。
业务连接为 客户端 192.168.1.1 -> LVS 10.2.1.1 -> Mysql 数据库 10.1.1.1
。
问题现象
首先开发同事通过监控发现客户端存在连接问题,Mysql 连接不定期的过段时间就会发生中断并重连,影响业务运行,之后联合 LVS 服务器同事进行了相关排查,未有发现,疑似网络问题,遂上报至网络团队。
常规的网络检查并无问题,之后让在客户端和 LVS 服务器上抓包以排查问题,通过对数据包的分析发现了如下奇异的问题。
客户端抓包
TCP 三次握手,RTT 0.026511s,客户端 MSS 1460,服务器 MSS 1452,Window scale 均支持,值为 7。
Wireshark 指定端口 3334 为 Mysql 端口,可以看到一些交互信息,Request Query 和 Response OK,以及 Request Ping 和 Response OK。其中 Mysql Ping 的概念参考如下:
https://baike.baidu.com/item/mysql_ping/4503428?fr=aladdinhttps://dev.mysql.com/doc/connectors/en/apis-php-mysqli.ping.html
大概是用来检查服务器是否关闭了连接。如果连接正常,返回0;如果有错误发生,则返回非0值,返回非0值并不意味着服务器本身关闭掉,也有可能是网络原因导致网络不通。
因为反馈 Mysql 连接中断,所以尝试通过 mysql.error_code
或者 mysql.error.message
过滤,并返回 tcp.stream
查看具体数据包。
客户端在进行一次 Ping 检查后,服务器回复了 ERR,信息为 Unkonwn command
,随后客户端进行了 Request Quit ,然后四次挥手连接中断。检查了帧 69774 中的命令,显示 Mysql Ping 命令正常,那么 问题是否发生在中间传输阶段或是在服务器上。
进一步分析
LVS 服务器抓包
因为在中间路由交换传输,数据包并没有改变其 ip.id ,通过定位客户端抓包文件中帧 69774 的 ip.id == 0x1a5b
, 在 LVS 服务器抓包文件中快速过滤定位,检查出以下问题
客户端发送的帧 69774包中的 Mysql Ping ,在 LVS 服务器接收时,命令竟然变成了 SLEEP,且数据包标记成 Malformed Packet ,针对此帧进行详细对比。
客户端
LVS 服务器
可以明显看到,同一个数据帧中 MySQL 协议 Command 由 Ping (十六进制值 0e )被更改为 SLEEP ( 十六进制值 00 ),也因为此处更改,造成了 TCP 校验和失败,认为是错误包。但由于 TCP 校验和是一个端到端的校验和,LVS 服务器仍正常转发此帧,之后由 Mysql 服务器 10.1.1.1 接收,识别为未知命令,返回 ERR 信息,最终造成连接中断。
后续
经过长时间观察,发现此问题偶发,Mysql Ping 命令错乱,固定由 0e 变为 00,而不是随机改变,时不时的造成 Mysql 连接中断。
通过检查端到端的网络设备,在其余业务通讯又正常的情况下,初步排除了网络设备物理端口或线路上的 CRC 问题,因为很难做到固定的 bit 位错误。
更遗憾的是,如开篇所说,此问题网络接手还未开展进行分段抓包定位工作,即随着环境改变随之消失,问题不了了之。最终猜测是中间某个网络设备特殊的 比特位反转 问题。
总结
🤣 又一未解之谜。。。