背景
最近遇到一个很恶心的问题,项目上在内网环境部署了Apache Doris,现需要通过VPN访问。大多数同事都可以正常访问并提取数据,但是在我的Windows 11开发机器上,使用DBeaver/GoNavi访问,数据库连接可以建立,但是查询数据的时候就会长时间hang住,直至超时。
我进行了一些自查:
- Ping/Telnet Doris机器均正常;
- Python小查询可以成功,但返回稍大结果集时容易超时。
刚开始以为是代理和奇安信VPN冲突了,但是关闭了代理发现问题依然存在,这就很挠头了。但是项目上又是重度使用Apache Doris,这个问题必须排查出来。
2. 第一轮:收集数据库连接异常现象
2.1 数据库IDE与Python脚本的相似和异常点
使用DBeaver/GONavi/Python脚本访问数据库:
相似点:
- 使用Wireshark抓包发现,数据库MySQL协议握手成功;
- GoNvai可以展示数据库中的数据表,并完成例如空表的数据查询,但是查询大数据表的时候会卡住;
- DBeaver点击连接,会长时间卡在初始界面上,无法执行更进一步的操作;
- Python脚本可以执行诸如
SELECT 1、SHOW DATABASES等SQL,但是查询大数据表的数据会卡住,若是添加limit,限制在较小的数据集会成功。
3. 第二轮:查找数据库连接走的是哪个网卡
要排查问题,首先要确定当前VPN的流量是哪块网卡在承接。这里使用AI提供的PowerShell命令查询
3.1 查找VPN流量网卡
PS C:\Users\test> Test-NetConnection 192.168.73.78 -Port 9030 -InformationLevel Detailed
ComputerName : 192.168.73.78
RemoteAddress : 192.168.73.78
RemotePort : 9030
NameResolutionResults : 192.168.73.78
MatchingIPsecRules :
NetworkIsolationContext : Internet
IsAdmin : False
InterfaceAlias : 以太网 2
SourceAddress : 192.168.102.224
NetRoute (NextHop) : 183.220.194.12
TcpTestSucceeded : True
通过以上内容可知,当前访问Doris(192.168.73.78),数据库流量走的是以太网2(VPN 出口)。
3.2 查看网卡的概要信息
PS C:\Users\test> netsh interface ipv4 show subinterfaces
MTU MediaSenseState 输入字节 输出字节 接口
---------- --------------- ------------ ------------ -------------
4294967295 1 0 8660 Loopback Pseudo-Interface 1
1500 1 133451841 29795696 WLAN
1500 5 0 0 本地连接* 1
1500 5 0 0 蓝牙网络连接
1500 5 0 0 本地连接* 2
1500 1 214769 71063 以太网 2
1400 5 0 0 以太网 3
通过以上内容可知,现在开发机通过WLAN接入公司网络,其中“以太网 2”作为VPN承接网卡,有实际的数据数据流动。
4. 要不要试试看MTU
这时候脑海中突然想到一般上Windows主机的MTU是1500,但是当前是通过VPN访问开发机器,VPN会对数据包进行再次封装,那么其实际MTU应该是小于1500的,要不试试看
4.1 使用DF Ping做路径MTU探测
执行:
$mtus = 1472,1464,1452,1440,1420,1400,1380,1360,1320,1280
foreach ($m in $mtus) {
ping -n 1 -f -l $m 192.168.73.78
}
测试结果:
正在 Ping 192.168.73.78 具有 1472 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1464 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1452 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1440 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1420 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1400 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1380 字节的数据:
请求超时。
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失),
正在 Ping 192.168.73.78 具有 1360 字节的数据:
来自 192.168.73.78 的回复: 字节=1360 时间=6ms TTL=55
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 6ms,最长 = 6ms,平均 = 6ms
正在 Ping 192.168.73.78 具有 1320 字节的数据:
来自 192.168.73.78 的回复: 字节=1320 时间=10ms TTL=55
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 10ms,最长 = 10ms,平均 = 10ms
正在 Ping 192.168.73.78 具有 1280 字节的数据:
来自 192.168.73.78 的回复: 字节=1280 时间=4ms TTL=55
192.168.73.78 的 Ping 统计信息:
数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 4ms,最长 = 4ms,平均 = 4ms
查看这个输出结果,可以发现:
- 包大于1380及以上,均无法正常Ping通;
- 包大小为1360、1320、1280成功。
推导路径MTU:Windows ping的-l是ICMP payload,那么这个网卡的实际MTU应该是payload + 28,也就是大致为1360 + 28 = 1388。
哈哈,这里基本上可以断定,这就是MTU设置不合理导致的问题,网卡的MTU应该从1500往下调节。
4.2 与SQL查询怪异情况对应
当查询的SQL返回数据较小的时候,IP Packet的payload可能小于1360,这时候SQL执行正常;
但是在查询较大的数据表时,返回的数据内容堆积,这时候按照MTU 1500进行分包,就会出现数据包丢失的情况,这样就表现为界面卡死,查询超时。
这与MTU黑洞现象高度一致:
- 小包可以正常通行;
- 大包/连续回包在隧道路径中被丢弃或重传;
- 应用层表现为“查询超时”或者“连接丢失”。
6. 为什么同事机器正常
在初步判定是MTU设置的原因后,就去同事的电脑上查看,这时候发现同事的电脑是MAC。
通过ifconfig查询,发现同事的VPN承接网卡的MTU是1360,这真的是悲伤的消息啊,也许我应该换MAC。
7. 解决方案与落地步骤
通过AI查找了MTU设置命令,执行了之后发现DBeaver以及Python脚本均能正常工作了
7.1 临时验证(当前会话生效)
netsh interface ipv4 set subinterface "以太网 2" mtu=1360 store=active
7.2 持久化(重启后保留)
netsh interface ipv4 set subinterface "以太网 2" mtu=1360 store=persistent
但是还是存在疑问,Apache Doris是兼容MySQL协议的,但是在开发机上是可以正常通过VPN访问MySQL(5.7到8以上的版本),但是通过VPN访问Doris就不正常。
但是今天的坑就填到这里吧,后续再去验证这个差异点。