S3 MPU 上传partSize推荐32MB或者64MB的原因

30 阅读2分钟
  1. 「≤100 MB 单次推送」≠「partSize 必须 ≤100 MB」
    浏览器限制的是“一个 XMLHttpRequest/fetch 的 body 大小”,而 MPU 里每个 part 都是独立的 PUT;只要你的代码把 32 MB 读完就发,单个 PUT 永远只有 32 MB,自然满足“≤100 MB”这条红线。
    反过来,如果你把 partSize 设成 128 MB,那每一个 PUT 就会是 128 MB,直接撞墙,所以 32 / 64 MB 是在“尽可能大”与“不触发浏览器/网关限制”之间折中的结果。

  2. 为什么常见 8 MB、16 MB、32 MB、64 MB?

    • 历史习惯:AWS Java/.NET SDK 早期把 8 MB 作为最小 part,后续版本为了对齐 2 的幂,继续翻倍到 16/32/64 MB,文档示例里也都是这些值,“抄作业”成本最低
    • 内存对齐:浏览器、Node、Java 的 Buffer/ArrayBuffer 申请 2 的幂时零头最少,GC 压力小;64 MB 正好是 67 108 864 B,整数好算好记
    • 比特位运算:很多 SDK 在计算“第几段”时用 partNumber = byteOffset >> partSizeShift,partSize 是 2 的幂可以直接右移,免一次除法
      并没有协议层面的强制,但“8 的倍数”只是 2 的幂的口语说法——选 2 的幂最省事
  3. 那干脆 72 MB、80 MB、96 MB 不是更少 part 吗?

    • 网关/代理限制:公司出口 Nginx、CDN、SLB 常常把单请求体限制在 100 MB 以内,留 20 % 余量才安全;72 MB 虽然<100 MB,但 TLS 帧、HTTP 头、重试缓冲加起来很容易膨胀到 105 MB,一过界就 413 Request Entity Too Large。
    • 重试代价:part 越大,丢一次包重传的字节就越多;72 MB 段在 2 Mbit/s 上行要 5 min,万一 4 min 时断网,整 72 MB 得重来;32 MB 段只需 2 min,失败损失更小。
    • 并发粒度:浏览器最多 6 并发,32 MB × 6 ≈ 192 MB 同时在飞;换成 80 MB × 6 = 480 MB,内存峰值翻倍,低端笔记本/手机直接 OOM。
    • API 费用:S3 的 MPU 计价按“Initiate + UploadPart 次数”算,72 MB 只是把 part 数从 32 降到 14,成本降幅有限,却换来上面一堆风险,ROI 不划算

所以业界最后收敛到“≤64 MB 且 2 的幂”这个甜点区:既能把 part 数压下来,又给自己留 30 % 以上的缓冲区,避免踩到各种 100 MB 隐形红线。