手机在电梯里断了几十秒网络。门一开,信号回来了,页面也终于动了。
然后事情开始不对劲:两条相同的消息一起出现,上传进度从 70% 跳回 0%,刚刷新出来的新数据又被旧页面盖掉。服务端监控那边也突然冒出一小波请求。
断网时大家只是等,网络恢复后,积压的事情同时醒了。
很多弱网问题并不发生在最差的那几秒。真正混乱的时间,往往是恢复后的半分钟。
网络恢复不是按下一个开关
手机重新显示 5G 或 Wi-Fi,只说明当前有一条网络通道可用。之前建立的连接未必还能继续,等待中的请求也不会自动获得正确答案。
有的请求已经失败,有的仍在等待超时,还有的其实被服务器处理完了,只是响应没能回来。与此同时,页面刷新、后台同步和用户手动点击都可能发起新请求。
这些任务属于不同时间,却挤在网络刚恢复的几秒里执行。App 如果只监听到一句“网络已连接”,然后把所有事情重新来一遍,重复和乱序几乎是迟早的事。
超时不等于服务端什么都没做
还是用付款来举例。
用户点击付款,请求成功到达服务器,服务器完成扣款。返回结果时网络断了,App 等到超时,只能显示失败。
网络恢复后,如果 App 直接重发付款请求,第二次扣款就有可能发生。用户看到的只是一次转圈和一次重试,系统里却出现了两次写操作。
下单、发评论、领取优惠券都有类似风险。只要操作会改变服务端状态,就不能把“没收到响应”当成“服务端没执行”。
处理这类情况,通常需要给一次业务操作稳定的身份。重试时仍然表示“刚才那一单”,服务端识别出它已经处理过,就返回原来的结果。支付超时后,App 也应该优先查询订单状态,而不是重新创建付款。
用户不需要知道这套机制的名字。他只在乎一件事:别让我点一次,系统做两次。
旧响应可能比新响应更晚回来
恢复期还有一种很常见的问题:返回顺序乱了。
假设用户先搜索“北京”,网络卡住后又改成搜索“上海”。第二个请求走新连接,很快返回上海的结果;第一个请求经过重传,过几秒才回来。如果页面谁最后返回就显示谁,用户明明输入上海,眼前却变回了北京。
请求 A:搜索北京 ─────────────→ 晚返回
请求 B:搜索上海 ─────→ 先返回并显示
请求 A 返回后覆盖页面
翻页、筛选和商品详情也会遇到这种乱序。解决办法通常不复杂:页面只接受仍然属于当前状态的结果。用户已经换了关键词,旧搜索即使成功,也没有资格再更新界面。
麻烦在于正常网络下两个请求往往按顺序返回,这个漏洞很难露面。弱网把时间拉开,它就出现了。
自动重试会在恢复时扎堆
重试本身没有错。网络偶尔抖一下,自动再试一次,能省掉用户不少操作。
问题是每个模块都觉得自己应该马上重试。
首页刷新一次,消息列表重连,上传任务恢复,埋点开始补传,后台同步也醒了。如果每个请求还有自己的多次重试,网络刚恢复就会出现一批集中流量。服务端可能才从故障中缓过来,又被新的请求推高负载。
用户连续点击会继续放大这个数量。页面没有反馈,他点了三次提交;App 的自动重试又各跑两次,原本一次操作很快变成多次请求。
恢复任务最好有一点秩序。当前页面和用户正在等待的操作可以优先,后台任务稍后再走;重试之间留出间隔,并加一点随机错开,避免大量设备在整点般的同一时刻发起请求。
如果某个服务已经明确不可用,继续高频重试没有意义。先停下来,等下一次合适的时机,通常比不停敲门更省事。
不同业务,恢复方式不能一刀切
普通查询最轻松。失败后重新获取即可,旧结果过期就丢掉。
写操作要谨慎得多。点赞、评论和下单需要防重复,页面也要知道当前是提交中、结果未知,还是已经确认成功。
大文件上传适合保存已经确认完成的部分。网络回来后从断点继续,比重新发送几百 MB 更快,也能减少用户流量。这里不能只记住进度条显示到哪里,还要以服务端确认的数据为准。
实时音视频通常会重新建立连接。恢复后先保证声音和画面回来,再逐步提高码率比较稳妥。网络刚连上就立刻冲到最高画质,很可能又把链路塞满。
消息业务还要考虑顺序。离线期间发送的内容、恢复后新发的内容以及服务端补下来的历史消息,需要按稳定的标识整理,不能只按到达手机的先后顺序排列。
这些差异说明,“网络恢复后全部重试”不是一条可执行的业务策略。团队得先知道每类操作重做一次会发生什么。
页面要承认自己还在恢复
系统显示网络已连接,不代表 App 已经准备好。连接重建、状态确认和任务恢复都需要时间。
这几秒里,页面可以说实话。
付款场景显示“正在确认付款结果”,比重新亮起付款按钮安全;上传任务显示“网络已恢复,正在继续”,用户就不必反复点击。实时通话也可以短暂提示“正在重连”,而不是让画面停在那里,假装一切正常。
按钮是否可用,要看业务状态,不能只看网络图标。用户已经提交过一次,结果还没确认时,简单粗暴地重新开放按钮会把风险交给用户承担。
当然,提示也别堆满屏幕。状态发生变化时给一句准确的话,比轮流弹出“网络异常”“请求失败”“重试中”三个提示更清楚。
测试时,多盯恢复后的 30 秒
一个恢复场景可以很短:
正常网络 10 秒
→ 断网 5 秒
→ 低带宽恢复 10 秒
→ 正常网络 20 秒
断网前发起一次业务操作,断网期间再进行一次用户点击,然后观察恢复阶段。重点检查这些现象:
- 是否出现重复订单、重复消息或重复文件;
- 旧响应有没有覆盖当前页面;
- 积压请求是否在同一时间大量发出;
- 上传、播放和长连接能否继续;
- 页面状态最终能否和服务端一致。
最好再快速重复几轮。第一次恢复正常,第三次开始出现两个连接或一批旧任务,往往说明会话结束时没有清理干净。
写在最后
网络重新连上,只完成了恢复的第一步。后面还有旧请求收尾、任务重排和业务状态确认。
把恢复当成一个过程,问题会好理解很多:哪些任务可以重做,哪些只能查询结果,哪些旧响应已经没有用了。把这些规则定清楚,App 才不会在信号满格后突然手忙脚乱。
下一篇我们给这套体验定个标准。弱网测试没有崩溃、请求最后也成功了,究竟能不能算通过?
328



被折叠的 条评论
为什么被折叠?



