把断点续传写成可执行步骤,先写哪三行更稳妥
很多人第一次做断点续传,把断步骤容易一上来就写分片、点续并发、传写成重试队列,执行结果代码越堆越多,先写行更真正出问题时却不知道从哪查。稳妥更稳妥的把断步骤做法是先把“断点续传写成可执行步骤”这件事拆小:先写三行能跑通、能验证、点续能回退的传写成骨架,再往上加能力。执行下面按实际开发场景说清楚先写哪三行、先写行更为什么是稳妥这三行,以及常见坑怎么处理。把断步骤
先写哪三行:状态、点续位置、传写成校验
第一行先写任务状态。不要急着传文件,先把“这个任务当前处于什么状态”落下来,比如 pending、uploading、paused、done、failed。状态是断点续传的根,没有状态就无法判断该继续、该重试还是该放弃。实际落地时,状态可以存在本地数据库、配置文件或服务端任务表里,以你的存储条件为准。
第二行写已传位置。位置不是“传了多少字节”这么简单,要明确是已确认落盘或已确认接收的偏移量。比如分片上传就记录已完成的分片序号和字节偏移,单流上传就记录服务端确认的 offset。这里的关键是“确认”二字:客户端自己算出来的进度不算数,必须以服务端返回或本地持久化成功的记录为准。
第三行写校验依据。至少要有文件标识和分片校验信息,比如文件大小、修改时间、内容哈希或分片哈希。没有校验,续传时很容易把旧文件的新内容接在旧偏移上,表面成功、实际文件损坏。校验算法和粒度以业务要求和厂家接口说明为准,不必一开始就上最重的方案。
把三行变成可执行步骤
写完这三行,接着按顺序补步骤:先初始化任务并写入状态;再读取已传位置,向服务端询问该位置是否有效;然后从有效位置继续传输;每完成一个分片或一段数据,先持久化位置,再更新状态;最后整体校验通过才标记完成。这个顺序不能反,尤其是“先持久化再更新状态”,否则崩溃恢复时会出现状态说完成了、位置却没落盘的情况。
实际写代码时,建议把这三行做成一个很小的恢复函数:输入任务标识,输出状态、偏移量和校验信息。恢复函数只做判断,不直接传数据。这样断点续传写成可执行步骤时,主流程和恢复逻辑分开,排查问题会快很多。失败时先看恢复函数返回的偏移量是否合理,再看服务端是否接受该偏移,最后才查网络和并发。
常见坑与别硬扛的情况
第一个坑是把内存里的进度当断点。进程一重启,进度归零,续传变重传。第二个坑是分片大小频繁变,旧分片和新分片对不上,偏移量失去意义。第三个坑是只校验文件大小,不校验内容,遇到同名不同内容的文件就会静默出错。遇到这些情况,先停掉并发写入,回到单任务串行验证,确认三行数据一致后再恢复并发。
如果服务端接口不提供偏移确认,或者存储层无法保证持久化顺序,不要自己硬造一套“看起来能续”的逻辑。此时应以服务端或存储厂家的当期说明为准,必要时改成整文件重传加校验,或者引入专门的对象存储断点能力。涉及计费、审计和重要数据时,建议让后端或运维同事一起确认恢复策略,别只在前端做表面续传。
收束一下:先写状态、已确认位置、校验依据这三行,再把恢复函数和主传输流程拆开,每步先落盘再改状态。跑通单任务串行恢复后,再考虑并发和重试。这样把断点续传写成可执行步骤,后面加功能才不容易把已有断点弄丢。