上个月我们有个驻场项目,客户在郊区一个工业园区里,办公室的WiFi信号差到什么程度呢——我拿手机测试过,平均延迟380ms,丢包率8%,上行带宽不到1Mbps。最离谱的是他们每天要同步大量施工图纸,单个文件50MB起步。
那段时间我基本每天都在处理同步失败的工单。文件传到一半断了,或者干脆就卡在"同步中"一动不动。客户直接打电话给我:你们这个云盘是不是有问题?我一开始也怀疑是产品bug,查了半天日志,最后发现不是产品的问题,就是这个破网络带不动大文件。
弱网这个事儿,得先诊断清楚
不是说一句"网络差"就能概括的。我建议先搞清楚到底是哪种差:
- 高延迟但稳定:ping值高但基本不丢包,调整超时时间就能解决
- 丢包率高:TCP层丢包,大文件直传基本没戏
- 带宽不足:上行带宽极低,任何大文件上传都是噩梦
我这边的客户三个问题全占了。后来我用ping和traceroute做了一次基础诊断,确认是高延迟+高丢包+带宽不足的三重打击。
分片上传:说起来简单,做起来全是坑
第一个想到的方案就是分片。把大文件切成若干小块,每块独立上传,单块失败只重传那一块。
我们一开始按固定4MB分片,心想应该够了。结果实测下来问题一堆:
4MB分片在2Mbps的弱网下,单个分片传输需要大约16秒,一旦丢包就得重来。更要命的是200MB的文件分50个块,每块8%的失败概率叠加下来,成功率只有 (1-0.08)^50 ≈ 1.5%——一百个文件传过去,能完整上去的不超过两个。
后来改成动态分片。思路是:先探测一下当前网络的RTT和带宽,算出一个合理的分片大小,而不是用一个固定值硬套。具体公式大概是 分片大小 = 带宽 × RTT × 安全系数。在我们那个项目里算出来最优是512KB到1MB之间。
还有一个很反直觉的发现:分片之间不能连续发,要加间隔。一开始我们连续发,结果TCP拥塞窗口被压得很小,越传越慢。后来加了100ms的间隔,反而整体速度提上来了。原因是给TCP缓冲区留出恢复时间。
断点续传:这个功能我们踩了三次雷才做对
分片解决的是"单次成功率"的问题,但弱网环境下中断是常态,所以断点续传必须做。
我们最初的做法是在本地维护一个同步记录文件,网络恢复后从断点继续。听起来很简单,但实际踩了三个坑:
第一个坑是怎么判断网络恢复了。我最开始用的是ping检测,结果发现ping能通不代表业务网络真的通了——有些防火墙会放行ICMP但拦截HTTPS。后来改成发一个小的HTTP请求到云盘API,确认TCP连接能建立且返回200,才认为网络可用。
第二个坑是文件在离线期间被改了怎么办。用户在地铁里打开文件做了修改,网络恢复后同步软件要判断:继续传旧版本还是从头传新版本?我们最后用mtime对比——本地文件修改时间如果比同步记录里的时间更新,就丢弃未完成的分片重新开始。
进度条跳动也很烦人。做UI的时候发现进度百分比跳来跳去的,用户体验很差。后来改成按分片计数而不是按字节数,显示"已上传12/200个分片",看起来平滑很多。
冲突处理:多人离线编辑是个大麻烦
弱网场景下多人协作,离线期间各自编辑了文件,网络恢复后同时上传,冲突几乎是必然的。
我们分了三个层级处理:
文件级冲突最简单,两个人的文件都保留,后上传的自动加_conflict_20260518后缀,双方自己合并。
目录级冲突比较有意思——两个人都新建了一个叫"报价单"的文件夹。我们用的方案是用UUID做目录ID而不是用名称,所以两个"报价单"文件夹都能保留,各自对应不同的UUID。用户自己决定留哪个。
最麻烦的是同一文件的部分修改。比如一个人改了Excel的Sheet1,另一个人改了Sheet2,理论上可以合并,但实际上根本没法做diff。我们最后采用了保守策略:谁先同步成功谁赢,后来的人收到冲突通知,自己手动合并。虽然不够智能,但至少不会丢数据。
几个实战优化技巧
压缩传输:对Office文档(docx/xlsx/pptx)先在本地压缩再上传,平均能省60%的传输量。但jpg、mp4、zip这类已经压缩过的格式就别重复压了,压完反而更大。
后台静默同步:不要让用户盯着进度条看。我们把同步任务放进后台队列,用户正常操作文件就行,完成后发个通知。这个功能做起来边界情况很多——比如用户删除了正在同步的文件怎么办?我们在同步前加了文件存在检查,不存在的文件直接跳过。
增量同步:只传文件变化的部分,而不是整个文件。用rolling hash做块对比,这个思路类似rsync。实测对于改了几行字的文档,增量同步只需要传几十KB,而不是整个几MB的文件。
智能排队:小文件优先处理(快速清空队列),用户当前正在浏览的文件优先,大文件和非紧急任务安排在深夜自动跑。
最后说个诊断工具
弱网同步出问题了,怎么快速定位是网络问题、服务器问题还是客户端问题?我们给用户做了一个状态面板,显示当前网络质量评分(RTT和丢包率)、每个文件的同步进度、重试次数。出了问题一目了然。
还有个功能很好用:同步日志导出。用户报告"同步又失败了",直接让他导30分钟的日志给我,里面有每次请求的耗时、状态码、错误信息。不用反复追问"你网络好不好",有数据说话效率高很多。
这个项目做下来,那个工业园区客户的同步成功率从最初不到20%,提升到了95%以上。虽然弱网下每次同步确实比好网络慢不少,但至少不会丢文件、不会卡死。对这类用户来说,能稳定同步比什么都重要。