SSTP 中的 TCP:为什么重传会发生两次
SSTP 通过 TLS 之上的 TCP 流承载隧道。当路径丢包时,外层和内层的恢复会同时退让。
口耳相传先于协议到来。四处问问,SSTP 就是那个慢的选项,除非有东西逼你,否则你会避开它。这个名声描述的只是一种路径上的一种故障模式。
机制是真实的。它也是有条件的,而名声从不提这一点。
一条路径上的两条可靠流
SSTP 将其隧道封装在 HTTPS 会话中。HTTPS 运行在 TCP 之上,而那条外层流保证有序交付。因此,一个缺失的段就会挡住排在它后面的一切。属于其他内层会话的后续字节照样要等待。
内层 TCP 流保留自己的顺序和拥塞控制。它们看不到外层的恢复,所以只能观察到停顿。停顿就是告诉它们路径拥塞的信号。
现在两层同时退让。这就是全部的相互作用,而丢一个段就足以触发它。
效果出现的地方与不出现的地方
在干净的路径上,外层流很少恢复什么。这种相互作用从不触发,SSTP 也能很好地承载交互式流量。笼统的说法恰恰在这一点上不成立。
当丢包或重排到达底层路径时,效果就会出现。拥塞的 Wi-Fi 链路或延迟多变的移动连接会创造条件。被阻塞的外层队列随后变成隧道内可见的延迟。
它还会随工作负载扩大。大量并行流填满队列,使队头阻塞更严重。同一条路径上的单个交互式会话也许感觉还可以接受。
症状通常不是什么
并非每个缓慢的会话都是这个问题。从第一个包起就稳定偏低的速率指向容量、限速或服务器限制。与本地拥塞对得上的停顿指向接入链路上的排队。
补救办法各不相同,所以诊断要先做。调整缓冲区对被限速的链路毫无作用。更换协议对容量耗尽的服务器毫无作用。反复重置指向完全不同的地方。
# outer path quality to the SSTP endpoint
ping -c 50 203.0.113.44 | tail -3
mtr -rwc 50 203.0.113.44
# is the local link saturated while the session stalls?
sar -n DEV 2 5
# retransmissions on the outer connection
ss -tin dst 203.0.113.44
在问题发生时进行测量。在健康的一分钟里抓的包,丝毫不能说明出问题的那一分钟里运行的环路。
值得信任的对比
如果确实存在另一种传输方式,就在受控条件下比较。同一主机、同一网络、同一目的地和同一任务。两次运行都应落在同样的十分钟内,这样路径条件才一致。
换端口并不能换协议。把无关的配置文件导入 SSTP 客户端并不会创造替代传输。只有当服务器提供第二种选择时,这种比较才有意义。
始终开启 TLS 验证。性能工作不是接受未验证证书的理由。如果停顿主要出现在上行链路饱和时,先检查排队,再怪罪分层。