←

大文件上传:失败只重传当前这一块

扫描要先把仓库传到服务端。仓库常常是几百 MB,大的超过 1GB。弱网下整文件传到中途失败,就得从头再来,扫描完成率起不来。

客户端先去掉 .git、node_modules 这类不参与扫描的目录,再压成一个 .tar.gz 流。不把成千上万个小文件分别上传。

流进分块写入器。缓冲区攒到 4MB,切成一块,分配 chunkId。4MB 是用大约 100MB 的常见仓库试出来的:再小,请求的固定开销占比太高;再大,失败一次要重传的太多。上传固定 4 路并发,把带宽用上,又避免把本来不稳的链路打满。

一块失败,例如超时或 503,不放弃整个文件。等待 1 秒、2 秒、4 秒各再试一次,最多 3 次。更长的中断靠断点。开始前用文件内容做出指纹,服务端返回 upload_session_id。每一块成功后,把这个会话已经收到的 chunkId 记在 Redis 里。重连时用同一个指纹来,服务端返回已收到的块,客户端跳过它们。

完整性对三次。开始前把整文件哈希和块号列表交给服务端。每一块的哈希随块上传,对不上就只重试这一块。按块号合并之后,再算一次整文件哈希,和开始时的比对。

上线后,由上传失败带下来的扫描成功率提高了大约 40%。