两台 Windows 机器之间的文件复制本来很快,直到两台机器都加入同一个 VPN,速度就骤然下降,而同一对机器之间的吞吐测试却仍报告接近线速的结果。这个落差就是诊断结论:链路本身没问题,是某个东西在为传输本身挑选更差的路径。这个东西通常就是 SMB3 多通道,它只是在做自己被设计来做的事。把多余的那条通道排除在外,复制就会回到物理链路上。

症状在等它最慢的那条通道

多通道允许一个 SMB 会话使用多条 TCP 连接,客户端与服务器之间每一对合适的地址对应一条。当两台机器同时位于局域网和同一条隧道上时,Windows 会把局域网地址和隧道地址配对,并把两对都视为可用。会话最终保有的通道数超过物理链路所需,而其中一条要慢得多。

它不会失败。它只是在等,因为会话不可能比它最慢的通道更快完成。

这就是为什么带宽测试看起来很健康,复制却在爬行:单流测量可能只选中一条路径,而传输其实分散在两条上。在改动任何网卡设置之前先读取通道列表,并且要在复制仍在运行时读取,因为空闲的会话什么都显示不出来。你要记下的应当是每条通道背后的接口,而不只是结果感觉有多慢。

确认存在第二条通道

有两个 cmdlet 可以直接回答这个问题。连接列表显示正在使用的通道,会话摘要则显示连接本身。在缓慢复制期间把两者都运行一遍。

Get-SmbMultichannelConnection
Get-SmbConnection

寻找同一台服务器下被标记为已选中的多行,然后解析那行可疑记录里的客户端地址。如果该地址属于隧道网卡,第二条路径就是真实且已被确认的。如果每一行都属于物理接口,那么多通道就不是你的问题,复制慢另有原因。先做这项确认,因为修复动作干扰性够大,值得花一分钟取证。

Get-NetIPAddress -IPAddress 10.20.30.44

这里的地址都是占位符。请换成你自己输出中报告的值,因为从博客上抄来的地址,正是让一条能用的命令变成令人困惑的报错信息的方式。

把隧道从 SMB 中移除,然后重新测量

停用多通道是确认诊断结论最快的办法,而且可以回退。在负责复制的那台机器上应用客户端设置,在承载共享的那台机器上应用服务器设置,因为任何一侧单独都能让多余通道继续存在。这项更改对新连接生效,对已有连接不生效,所以已打开的会话会躲过它。在测量任何东西之前,先重启两台机器,或者至少关闭所有指向该共享的句柄。

Set-SmbClientConfiguration -EnableMultiChannel $false -Force
Set-SmbServerConfiguration -EnableMultiChannel $false -Force

确认新的状态,然后看看服务器现在向客户端通告了什么。

Get-SmbClientConfiguration | Select-Object EnableMultiChannel
Get-SmbServerNetworkInterface | Format-List *

隧道接口应当从那份通告列表中消失。如果没有消失,说明设置落到了错误的一端,或者旧的会话仍然开着。如果文件共享就是不该走隧道,那就改从该网卡上解绑服务器组件,这样隧道对其他所有服务都仍然可用。

Get-NetAdapterBinding -Name "OpenVPN Data Channel Offload"
Disable-NetAdapterBinding -Name "OpenVPN Data Channel Offload" -ComponentID ms_server

优先走局域网路径,但别假装它能删掉通道

接口跃点数告诉 Windows 新连接该优先走哪条路径。它并不能移除多通道已经决定要打开的通道。提高隧道的跃点数仍然值得做,因为它能让无关流量远离慢路径,并让优先路由变得可预测,但那只是轻推,不是过滤器。

Get-NetIPInterface | Sort-Object InterfaceMetric | Select-Object InterfaceAlias, InterfaceMetric
Set-NetIPInterface -InterfaceAlias "OpenVPN Data Channel Offload" -AutomaticMetric Disabled -InterfaceMetric 1000

别名请从输出中复制,不要手打,因为有些安装会把网卡名称本地化,英文字符串就对不上了。

然后再测两个数字:文件复制,以及同一对机器之间的吞吐测试。如果吞吐测试从来没慢过而复制恢复了,那么多通道就是元凶,你可以收工了。如果两者一起崩,隧道才是瓶颈,多通道只是把它放大了。如果两条路径看起来都对而复制依旧慢,剩下的问题就在共享、存储或某个过滤驱动里,那是另一项排查。

相关文章