暂停、继续、追帧与断线重连
Category
server / sync 子树。节点定位:暂停、继续、追帧与断线重连是四件不同的事——最容易暴露架构真相的场景,必须共用同一时钟模型。
Definition
暂停和继续不是一个 UI 细节,而是同步体系里最容易暴露架构真相的场景。很多团队以为“客户端点了暂停,战斗时钟不步进”就叫支持暂停,结果一到联网战斗、后台挂起、掉线恢复、服务器不停跑和断线重连,系统立刻露馅。
Problem
「客户端点了暂停、战斗时钟不步进」不是支持暂停:联网战斗、后台挂起、掉线恢复、服务器不停跑才见真章。暂停与恢复共用同一时钟模型这条约束不提前定,系统一到联机场景就露馅。
先把四件不同的事分开
现实工程里,很多人把下面四种情况都叫“暂停”,其实它们根本不是一回事:
- 本地 UI 暂停:玩家打开菜单、暂停渲染或暂停输入,但房间逻辑可能继续跑。
- 房间级战斗暂停:整局战斗的权威逻辑时间停止推进,所有参与者停在同一帧。
- 客户端挂起或卡死:客户端本地停止推进,但服务器和其他人可能根本没停。
- 掉线重连与追帧:客户端离开了一段时间,回来时要重新追上权威帧。
这四类场景如果不先分开,后面所有设计都会互相打架。
联网战斗里真正的“暂停”只有一种
联网战斗里,真正的战斗暂停只有一种定义:权威战斗时钟暂停推进。也就是说,不只是客户端画面停住,而是服务端或房间协调端明确把逻辑帧锁在某一帧上,直到恢复命令生效。
如果只是某个客户端本地不再步进,但服务器仍在继续推进:
- 对服务器来说,这不是暂停,而是客户端掉队或挂起。
- 对其他玩家来说,这不是暂停,而是房间继续正常进行。
- 对重连客户端来说,它回来后面对的是追帧恢复问题,而不是暂停继续问题。
这正是很多失败案例的根因:系统以为自己实现了暂停,实际上只是某个端本地停了。
房间级暂停应该由谁控制
如果项目允许联网战斗暂停,比较稳妥的做法通常是:
- 由权威服务器或房间协调端决定是否进入暂停态。
- 暂停态绑定明确的房间状态和当前帧号。
- 暂停期间不再生成新逻辑帧,也不再消费未来输入。
- 恢复时从同一权威帧继续推进,而不是靠各端自己“接着跑”。
同时还要定义清楚暂停权限:
- 谁能发起暂停。
- 暂停是否需要全员同意。
- 暂停最多持续多久。
- 掉线玩家是触发自动暂停、托管,还是比赛继续。
这些规则不是产品旁枝,而是同步系统的一部分。
很多失败案例本质上是什么问题
“服务器没有停一直在跑,客户端断线重连之后一直追帧、一直加载”这种现象,通常不是单点 Bug,而是几个设计问题叠加:
- 把客户端挂起误当成了战斗暂停。
- 没有房间级权威暂停语义,服务器自然继续推进。
- 没有周期性战斗检查点,重连只能从很久以前逐帧补。
- 没有追帧上限,客户端会永远试图靠 CPU 把历史帧补完。
- 加载流程和追帧流程耦合,资源还没准备好,逻辑也追不上。
这时客户端“在加载”的往往不是某个单一资源,而是在同时做几件不该一起硬做的事:拉房间状态、恢复对象图、补历史帧、重建技能与 Buff 时序、补齐表现资源、对齐当前权威帧。只要任何一项跟不上,就会出现持续 loading。
重连时到底应该先恢复什么
更合理的问题不是“重连时该不该追帧”,而是“先恢复到哪个基点,再追多少帧”。比较稳妥的答案通常是:
- 房间基础信息:地图、模式、当前阶段、玩家列表、阵营。
- 最近权威检查点:角色位置、朝向、血量、资源、Buff、冷却、投射物、召唤物和战斗子状态。
- 检查点之后的少量增量帧:从检查点帧到当前权威帧这一小段输入或事件。
- 当前权威帧号和时间基准:告诉客户端现在要追到哪里。
- 最低必要表现资源:不是把全历史表现都重播,而是保证当前状态能正确显示。
关键点只有一个:重连恢复的目标是尽快回到当前权威状态,不是忠实重播断线期间的每一个历史表现细节。
为什么不能无脑逐帧追
逐帧追只有在落后很少时才合理。落后多了以后,它几乎一定会出问题:
- 客户端一边追逻辑,一边还要加载资源和重建对象,CPU 很容易先炸。
- 如果渲染和逻辑没有彻底分离,追帧时体验会很差。
- 一旦又有新帧进来,目标继续往前滚,客户端可能永远追不上。
因此,成熟系统通常会设置多个恢复档位:
- 落后很少:直接快速追帧。
- 落后中等:加载最近检查点,再补一小段增量帧。
- 落后太多:直接状态跳转到最新检查点,必要时丢弃部分中间表现。
- 超过恢复窗口:不再强行恢复,转为重新入局、托管或判负。
没有这些档位,重连恢复通常会演变成“理论正确,线上不可用”。
追帧应该怎样跑才不拖垮客户端
追帧本质上是一个受限的快速模拟过程,常见实践包括:
- 追帧期间降级或关闭部分表现系统。
- 限制单次渲染循环内最多追多少逻辑帧,防止卡死。
- 把资源加载与逻辑追帧拆开,避免互相阻塞。
- 对关键对象优先恢复,非关键表现延后补齐。
- 当发现差距越追越大时,立即切换到检查点恢复,而不是继续硬扛。
追帧不是把正常战斗循环开倍速,而是专门设计的一种恢复模式。
暂停和断线恢复必须共用同一时钟模型
如果系统有房间级暂停,那么暂停和恢复都必须落在权威战斗时钟上。否则会出现几种常见灾难:
- 客户端以为自己停在第 2000 帧,服务器其实已经到了第 2150 帧。
- 暂停期间客户端还在局部推进动画或技能逻辑,恢复后状态错位。
- 恢复时不同客户端从不同本地时钟继续跑,整局立刻分叉。
比较好的设计通常是:
- 停或继续的对象是权威帧推进器,不是 UI。
- 暂停态是房间状态机的一部分,不是本地开关。
- 恢复时所有客户端对齐同一权威帧和同一检查点。
一组必须持续观测的指标
如果系统支持暂停、恢复和重连,至少应该持续监控:
- 房间暂停次数与平均暂停时长。
- 断线重连成功率。
- 重连后平均恢复耗时。
- 快照恢复命中率。
- 平均追帧数与最大追帧数。
- 因超出恢复窗口而失败的次数。
没有这些指标,你根本不知道恢复慢是因为网络慢、快照太旧、资源加载阻塞,还是逻辑追帧策略本身有问题。
常见误区
- 把客户端本地停步进当成联网战斗暂停。
- 没有检查点,重连只能从断点开始一帧一帧补。
- 追帧流程和资源加载强耦合,客户端越恢复越落后。
- 没有恢复失败兜底,系统宁可永远 loading,也不肯明确判定这次恢复已经不可行。
这一页真正要解决的,不是“暂停怎么写”,而是房间时钟、重连恢复和追帧策略怎样统一在一套可落地语义里。
实战案例:一次「断线重连一直转圈加载」的追帧与检查点排查
案例为教学示例(非摘自真实项目),数字经过取整简化。它把本页「先把四件不同的事分开」「很多失败案例本质上是什么问题」「追帧应该怎样跑才不拖垮客户端」用到深水区:断线后回来就一直 loading,越等越久——这是重连追帧与检查点缺失的排查,也是「怎样让恢复回到当前权威状态而不是重播历史」的完整展开。
背景与现象:某 MMO 团本,断线重连成功率 82%,平均恢复耗时 47 秒,长尾超过 3 分钟;落后较多的会话几乎必然卡在 loading 界面。客服口径是「断线重连就进不去了」,同期网络指标正常。
第一步:现象与口径——先按落后帧数分档
恢复耗时口径:平均 47 秒、P99 190 秒;落后 900 帧以内的会话平均 8 秒,落后超过 900 帧的会话几乎全部失败。
失败形态口径:卡在 loading 的客户端同时在拉房间状态、补历史帧、重建技能与 Buff 时序、加载表现资源——正是本页说的「在同时做几件不该一起硬做的事」。
时钟口径:断线期间服务端从未停过,客户端回来时权威帧已经领先 1200 帧以上——服务器没停,客户端却按「暂停」的心智回来。
第二步:分层归因——按本页失败清单逐项排查
重连失败 18% 归因
无周期检查点,重连从断点逐帧补 48%
追帧与资源加载耦合,越补越落后 31%
无追帧上限与恢复档位,超窗口也不判失败 21%排查路径:网络链路正常(排除);服务端帧号一直在推进(确认服务器没停);问题在恢复策略——没有检查点只能从断点逐帧补,落后 900 帧以上永远追不上;追帧和资源加载耦合,CPU 先炸;没有恢复档位,超窗口也不肯判定失败,宁可永远 loading。
第三步:根因——把客户端挂起当成了暂停,恢复没有基点和档位
团队以为「客户端点了暂停、战斗时钟不步进」就是支持暂停,但联网战斗里真正的暂停只有权威战斗时钟暂停这一种。掉线客户端回来后面对的是追帧恢复问题,而系统既没有周期检查点作恢复基点,也没有追帧上限和恢复档位,恢复自然演变成永久 loading。
第四步:处置与回填——先给恢复基点,再分档
- 周期检查点:每 300 帧生成房间检查点(角色位置、血量、Buff、冷却、投射物、召唤物、战斗子状态),重连优先加载最近检查点。
- 恢复档位四档:落后很少直接快速追帧;落后中等加载检查点补一小段增量帧;落后太多直接跳到最新检查点;超过恢复窗口转重新入局或托管。
- 追帧与资源加载解耦:追帧期间降级或关闭表现系统,关键对象优先恢复,非关键表现延后补齐;单次渲染循环限制最多追 4 帧逻辑。
- 暂停语义归位:房间级暂停绑定权威帧号,掉线触发托管而不是让整局等待。
复核账:重连成功率 82% → 98.6%;平均恢复耗时 47 秒 → 6 秒;P99 190 秒 → 18 秒;永久 loading 类工单清零;快照恢复命中率 91%。
回填清单:
| 回填项 | 动作 | 回填处 |
|---|---|---|
| 四事分开 | 本地 UI 暂停、房间级暂停、客户端挂起、断线重连分别定义,不共用一套语义 | 先把四件不同的事分开 |
| 权威暂停语义 | 暂停绑定权威帧号与房间状态机,掉线触发托管而非整局等待 | 联网战斗里真正的“暂停”只有一种 |
| 恢复顺序与档位 | 先恢复房间信息与最近检查点,再补少量增量帧;按落后程度分四档 | 重连时到底应该先恢复什么 |
| 追帧不拖垮客户端 | 追帧期降级表现,逻辑与资源加载解耦,超窗口转重新入局 | 追帧应该怎样跑才不拖垮客户端 |
案例的三个教训
- 联网战斗里服务器不停,「暂停」心智就是错的。掉线客户端回来面对的是追帧恢复,不是暂停继续——四件事不先分开,恢复策略必然拧巴。
- 没有检查点,重连就只能从断点逐帧补,落后多了永远追不上。检查点是恢复的基点,也是长对局能不能做稳的前提。
- 追帧要设上限和档位,宁可明确判失败也不要永远 loading。恢复的目标是尽快回到当前权威状态,不是忠实重播断线期间的每一个历史表现。
Used By
暂停与断线恢复设计;追帧策略评审;重连恢复顺序约定。
Related
关系链:四事分开 → 唯一暂停 → 控制权 → 失败本质 → 恢复顺序 → 追帧不拖垮 → 时钟共用。上游:sync/01(时钟)、sync/03(帧同步的追帧)。下游:sync/05(预测纠正的状态分层)。
Reference
本页为工程经验归纳;页内实战案例为教学示例(数字取整简化)。