长连接掉线有个很讨厌的特点:它不影响你刷网页,所以很容易被归结成「玄学」。实际上这类问题的线索相当具体,只是需要先花十几分钟把断开的规律记下来,而不是一上来就翻客户端的参数页。

第一步是记录,不是调参

拿一个能持续产生长连接的场景做观察,比如挂一个 SSH 会话、开一个在线文档、或者让聊天应用保持前台。记录三件事:

  • 每次断开距离上次连接成功过了多久;
  • 断开时你是否正在传数据,还是处于空闲状态;
  • 断开前后设备的网络有没有变化(切了 Wi-Fi、锁屏、休眠)。

记满三到五次,规律基本就出来了。有没有这份记录,后面的排查效率差好几倍。

断开规律对应的方向

观察到的规律大概率成因从哪里入手
间隔固定,几乎精确到分钟某个设备的空闲超时在回收连接心跳间隔与中间设备设置
只在空闲一段时间后断,有数据往来时不断NAT 会话表回收缩短心跳间隔
传大文件或数据量大时才断MTU 或分片处理异常调整 MTU
间隔完全不规律,伴随延迟波动线路质量问题换节点,或参考时段规律
锁屏、休眠、切换网络后断系统回收网络栈客户端后台权限与自动重连
固定时段密集发生,其他时段正常线路拥塞晚高峰变慢的成因

先把自己的现象归位,再往下看对应的那一节。

空闲超时:最常见的那一类

一条 TCP 连接在链路上不是只有你和服务器两方在管。中间的家用路由器、运营商设备、机房的负载均衡、服务端前面的反向代理,每一个都可能维护着自己的会话表,并且都设了空闲超时。一旦在超时时间内没有任何数据往来,这条会话就被悄悄丢掉——注意是悄悄,通常不会给你发关闭通知,所以客户端要等到下次发数据时才发现连接已经没了。

对应的处理是让连接不要真的空闲下来,也就是心跳。要点有三个:

心跳间隔必须小于链路上最短的那个超时。 链路上有多个设备,谁的超时最短谁说了算。不知道具体数值时,从较小的间隔开始试,能稳住再往上放。

心跳要开在正确的层。 应用自己的心跳、代理协议的心跳、TCP keepalive 是三个不同的东西。前两者通常有效,系统级 TCP keepalive 的默认间隔往往长达一两个小时,基本指望不上,除非你手动改小。

别把间隔调大来省流量。 心跳包很小,省下来的流量微不足道,换来的却是掉线。

NAT 与会话回收

家用网络下,你的设备通过路由器的 NAT 映射出去。路由器的会话表容量有限,连接数多的时候会优先回收看起来空闲的条目。这在同时连着大量设备、或者有 P2P 类应用占用大量会话的家庭里特别明显。

判断方法:换到手机热点上做同样的观察。热点下的会话表压力小得多,如果掉线明显减少,基本可以确认是本地路由器的回收行为。这种情况下重启路由器只能短暂缓解,更有效的是减少同时在线的会话数,或者在路由器上调大会话超时(有此选项的话)。

MTU 与分片

如果掉线集中发生在传输较大数据的时候,而空闲时反而稳定,方向要换。

代理隧道会在原始数据外面再包一层,总长度可能超过链路允许的最大包长。正常情况下会触发分片或者路径发现,但部分中间设备会丢弃相关的控制报文,结果就是大包发不出去,小包一切正常。表现出来就是网页能开、聊天能发字、一传文件就断。

处理方式是在客户端里把隧道的 MTU 往下调,常见做法是从默认值开始每次减少几十再测试,找到既能稳定传输又不至于过度损失效率的值。调完记得实测大文件传输而不只是打开网页。

客户端与系统层面的回收

移动设备和笔记本上还有一类和线路完全无关的中断。

系统为了省电会限制后台应用的网络活动,客户端被挂起后,它维护的连接自然就断了。Android 各家的省电策略差别很大,把客户端加入不受限制的名单是必要操作;iOS 上则要确认应用没有被系统回收,长时间切到后台后回来需要手动确认连接状态。

笔记本休眠唤醒后也是同理:整个网络栈重建,原有连接全部作废。这种情况下客户端能否自动重连,以及重连后分流规则是否正确恢复,值得单独测一次。

Wi-Fi 与蜂窝之间的切换会造成同样的效果。如果你的掉线总是发生在出门、进电梯、走出路由器覆盖范围的时候,那这就不是故障。

换协议是不是更省事

有时候确实是。基于 UDP 的传输方式在保活机制上和 TCP 差别很大,遇到某些设备的会话回收策略时表现更好;反过来在对 UDP 处理不友好的网络里又会更差。Hysteria 2 的机制就属于这一类,值得作为对照项试一次。

但要清楚这是缓解而不是定位。如果同一个节点在换协议后好了,只能说明新的组合恰好绕开了那个环节,原来的超时设置或设备行为依然存在。真正想定位根因,还是得靠前面那份断开规律记录。

另外提醒一点:连接建立不上和连接建立后频繁断,是两类问题。如果日志里出现的是握手阶段的错误,应该走 TLS 握手失败那条线;只有个别节点表现异常时,则先看部分节点失效的判断方法

怎么验证改动有效

改完参数别急着下结论,长连接问题最容易出现「刚改完好像好了,过半小时又断」的假象。建议这样验证:

  • 挂一个空闲的长连接,不做任何操作,持续观察至少三十分钟;
  • 再挂一个持续有数据往来的连接,同时进行,对照两者表现;
  • 至少覆盖一次原本高发的时间段;
  • 期间做一次锁屏再唤醒,看连接能否自动恢复。

四项都通过,才算稳住。

反馈时该带上什么

这类问题描述得越具体,对方越容易判断。准备这些:

  • 断开时间点的记录,以及每次间隔的具体数值;
  • 断开时是空闲还是正在传输;
  • 客户端日志里断开前后的片段;
  • 节点名称、协议、端口,以及你设置的心跳与 MTU 值;
  • 换网络环境(家庭宽带 / 手机热点)后的对照结果;
  • 使用的应用类型,不同应用自己的重连逻辑差别很大,这一项能帮对方判断是不是应用侧的行为。