
1. 目标:降低上传延迟、提高吞吐量、保证稳定性和可恢复性。关键点:分片(chunk)上传、并发控制、断点续传、连接复用、零拷贝、使用CDN/对象存储的预签名直传。
2. 步骤:优先考虑客户端直传(pre-signed URL或STS),省去服务器带宽;若需鉴权或剪辑,则采用服务端生成签名+客户端上传。实现:使用S3/OSS/COS的预签名Put,每个视频分片生成签名。
3. 建议:分片大小 5MB–50MB,常用 8-16MB;并发线程 4–8(视带宽/IO),过高会造成TCP拥塞。实际步骤:测网速,计算并发 = (总带宽 / 每分片吞吐);在代码中使用线程池 Executors.newFixedThreadPool(n)。
4. 使用库:推荐 Apache HttpClient 或 OkHttp。启用连接池、启用Keep-Alive。示例设置:PoolingHttpClientConnectionManager,maxPerRoute=50;在上传时用InputStreamEntity或RequestBody.create(stream)进行流式发送,避免将整个文件读入内存。
5. 在服务端拼接或转发大文件时,优先使用 FileChannel.transferTo/transferFrom 实现零拷贝,减少 GC 和内存拷贝;若使用 Netty 可启用 FileRegion。
6. 实现:每分片上传前计算 MD5 或 CRC32,服务端记录已完成分片索引。客户端重试时先请求已完成列表并跳过。保存上传会话ID与每片状态,持久化到数据库或 Redis。
7. 对失败分片实现指数退避(例如 base 500ms, factor 2, 最大 8 次),遇到 5xx 则重试,4xx 则快速失败并记录日志;并在重试前检查已完成分片,避免重复上传。
8. 上传后在对象存储或CDN设置正确的 Content-Type、Cache-Control(如视频可长期缓存:max-age=31536000)和 CORS 允许源。上传完成后触发 CDN 的缓存预热或 invalidation(按需)。
9. 监控点:上传成功率、平均延迟、带宽利用率、错误码分布。实现限流:每个用户/IP限制并发上传数,防止突发流量导致源站过载。结合熔断器(Resilience4j)保护下游。
10. Q: 分片大小如何选择才最优?
10. A: 根据网络延迟和带宽折衷:高延迟网络使用较大分片(≥16MB)减少握手开销;高丢包环境可适当减小分片以降低单片重传成本。先做 3-5 次样本测试再定参数。
11. Q: 断点续传时如何管理分片状态避免重复?
11. A: 在服务端为每个上传会话生成唯一 uploadId,客户端上传每片时返回 ETag 或 MD5,服务端记录已完成片号。客户端重连先调用 `listParts(uploadId)` 跳过已完成部分,并把状态持久化(数据库或 Redis)。
12. Q: 上传很慢,该如何逐项排查?
12. A: 逐项检查:1) 客户端带宽与网络延迟;2) 并发线程/分片大小是否合适;3) 是否使用连接池与 Keep-Alive;4) 是否在内存中完整读取文件导致GC;5) 服务端是否成为瓶颈(CPU/IO);用 tcpdump/ss 或 CloudWatch/监控面板定位。