两秒卡顿:是 VPN 还是 Wi-Fi?
两秒的停顿与一次新的 VPN 会话是两件不同的事。在改动任何计时器之前,先把接入路径和隧道放到各自的时间线上。
一次在两秒内自行恢复的卡顿,无论隧道重新协商,还是无线侧打了个嗝,看起来都一样。也可能根本没有断过,这个可能性值得先测。短暂的丢包爆发、一次重新协商、应用的卡顿,在打字的人看来是同一回事。三者中只有一个能靠修改隧道配置来解决。
记两份,不是一份
记下底层连接发生了什么,再单独记下隧道本身做了什么。然后把应用的停顿对着这两份记录摆放。这是两组有时重合但彼此独立的事件序列,把三者一律称作断线,等于一开始就假定了答案。
一分钟才探一次的监控,看不出两秒的中断。把那天报告成健康,技术上准确,实际上无用。每引用一个结果,就把采样间隔写在旁边。
应用卡住期间,接入链路做了什么
采样间隔和超时决定了监控究竟能看到什么,所以两者都要记在结果旁边。当仪器每六十秒才采一次样时,记录里没有中断,意义很小。接着用时间戳探三个位置:本地路由器、经普通路径到达的获准外部主机,以及隧道之后的资源。
先确认路由,因为公网目标本身也可能走隧道,那时测到的是隧道而不是接入路径。真正能给中断定日期的证据在更下面一层:路由器上的链路事件、调制解调器上的重新同步记录,以及变化的 WAN 地址。累计错误计数器只说明出过问题,从不说明什么时候。把这些记录与事件时间窗关联起来,而不是孤立地读。
ping -i 0.5 -c 40 192.168.60.1
mtr -rwc 40 203.0.113.25
ip -brief address show
昨天升高的计数器,解释不了今早的卡顿。把关联范围限定在用户报告的时间窗内。
寻找重启记录
丢一个 UDP 数据报本身,并不会让 Community OpenVPN 开始新的 TLS 协商。重启行为取决于 ping-restart,而生效值可能是服务器下发的;2.6 手册定义了这些计时器。投递中断一瞬间,阈值从未被越过,日志保持空白。因此要在停顿前后的日志里找重启行、新连接,或变化过的会话标识。三者都没有出现,隧道多半什么也没做,计时器从来不是问题。
把每个 keepalive 都缩短,会让检测看起来更快,同时挪动了“一次抖动变成一次重连”的那条线。每次重连都要花一轮认证和路由重装。把计时器拉长,除了让死掉的路径看起来还活着更久之外,什么也换不来。两者都是有代价的调参决定,不是免费的改进。
没有发生的事件同样是证据,而且正是那种人们会跳过的证据,因为日志里没有任何东西把它指出来。记下你执行过的搜索,而不只是结果。
让对比来决定修什么
两份记录并排之后,归因通常自己就写出来了。两条路径上都有路由器链路事件,说明对象是接入连接。隧道安静而普通路径可用,说明对象是协商。
| What you observed | Tunnel log at that second | Where to look next |
|---|---|---|
| two-second pause, plain path answers throughout | nothing | the monitor's resolution, then a loss burst |
| pause plus a router link event, plain path stops and returns | no restart line | the access link, not the tunnel timer |
| pause, then a new session identifier | restart line | the restart threshold and what triggered it |
| one application freezes while both paths answer | nothing | that application and its server-side work |
每一行都是线索,不是判决:端点会降低 ICMP 的优先级,两个目的地也不一定共享同一条路径。让客户端、网关与应用三者的时钟保持一致,比较才有可能。同时落进两列的那一行,需要再多一次观测,而不是一个决定。
经得起复核的报告会回答四件事:卡顿持续了多久、哪些路径一直在应答、隧道在那一秒记录了什么、监控多久采样一次。这四个事实让下一位读者能复现观测,而不是相信一份摘要。可用率百分比恰好藏起了你关心的那个区间,“VPN 掉了”这句话也一样。