通过 VPN 打开共享文件夹,等着目录列表一点点爬出来,是熟悉的体验,第一反应往往是怪带宽。通常链路几乎空闲。协议把时间花在等待回复上,每次等待都付掉一个局域网从不计费的完整往返。改变工作的形态,共享就重新可用。

远程工作副本的形态是错的

SMB 打开文件、读取元数据,并在许多小交换中确认。映射驱动器上的版本控制工作副本默认本地文件系统延迟,会读取大量小文件。桌面数据库随用户操作不断拉取页。这些都会把延迟变成乘数,因为开销随该操作进行的交换次数增长;因此 40 ms 的隧道会把几百次操作变成几秒。在那套算法里,负载大小几乎无关紧要。

加密开销只占一小部分;丢包更糟,因为一次重传加上塌缩的拥塞窗口,代价远高于涉及的那点字节。

先数往返次数,再谈兆字节

买容量之前先测延迟。一次 ping 就能说明每次交换要付出什么。

ping -c 10 fileserver.example.net

统计会给出最小、平均和最大往返时间,而离散程度与平均值同等重要。把平均值乘以一次目录列表所做的交换次数,再与你实际观察到的时间对比。如果一个大文件传得很快、浏览却很慢,约束就是延迟与请求数。给一条从不饱和的链路增加十倍容量,什么都不会改变。

搬工作,别搬字节

不要为更粗的管道付钱,而是改变工作发生的位置。把仓库当作服务提供,而不是挂载它;用只发送差异的工具做批量复制。

rsync -av --info=progress2 ./project/ [email protected]:/srv/share/project/

像 hgweb 或远程 Git 那样把仓库作为服务提供,客户端就能在本地克隆上工作,文件系统调用不再穿过隧道。rsync 会遍历两端,只发送变化的块,省掉朴素复制支付的大部分交换。桌面数据库应该放在服务器端引擎上,客户端退化为前端;或者整个客户端跑在内部主机上。每种选择都在改变协议暴露在多少延迟之下,这才是关键。

在相同大小附近卡住,是 MTU 的症状

大传输在差不多相同的数据量之后停滞,而 ping 和小页面正常,说明问题在分组大小,不在带宽。

ping -M do -s 1400 -c 3 fileserver.example.net

探测成功意味着 1428 字节的 IP 分组能不分片地通过路径,因为 ICMP 与 IP 首部要加 28 字节。带禁止分片标志时失败,说明隧道可用 MTU 小于服务器假设的值。服务器把 9000 字节的缓冲区送上 1500 字节的路径,就会强制分片或丢包;ICMP 被过滤时,路径 MTU 发现还会静默失败。降低隧道 MTU,在 OpenVPN 上启用 mssfix,或缩小服务器缓冲区,然后重跑同一传输来确认。

测量真正重要的差距

在策略允许的地方,用三种方式跑同一操作:本地、经隧道、走直连互联网路径。对每一种记录往返时间、单条大流的速率,以及目录列表或打开应用所需的时间。把本地运行与隧道运行相比,就能看出哪种开销占主导。结束得慢的复制指向速率或延迟问题;在固定位置死掉的复制,则指向分组大小或路径上的有状态设备。

如果只是开头几个兆字节拖慢,先看认证和元数据;如果一切都爬,先看容量与丢包。修掉对应的原因,别再指望 WAN 链路表现得像局域网网线。

相关文章