第 2 章 アップロード経路: チャンク分割、並列処理、再開 (重要)

アップロード側の目標は、変動するネットワークの下でも「帯域を使い切る」状態に可能な限り近づけつつ、失敗によるコストを最小限 (失敗したチャンクだけを再送) に抑えることです。 この 2 つの目標を合わせることで、アップロードが速く感じられる理由の大部分を説明できます。

2.1 チャンク分割

  • クライアントは、ファイルを複数のチャンクに分割しなければなりません (MUST)。チャンクは、アップロードと再試行の最小単位です。
  • 並列処理のスケジューリングと状態の表現を単純にするため、チャンクは固定サイズ (またはファイルごとにサイズを決める方針) とすべきです (SHOULD)。
  • すぐに得られる利点: 失敗が起きても、影響を受けるのはファイル全体ではなく 1 つのチャンクだけです。

2.2 並列アップロード

並列処理の目的は「スレッドを増やすこと」ではありません。現実のネットワークで単一接続が抱える、次の 3 つの制約を避けることです。

  • スロースタートとウィンドウの拡大: 単一の接続は立ち上がりが遅く、特にリージョンをまたぐ RTT が大きい場合に顕著です。
  • 回線のジッター: 1 本の接続でジッターが起きると、全体の速度が落ちることがあります。並列処理によってその影響が平準化されます。
  • フローごとのシェーピング: 単一のフローを絞り込むネットワークもあります。複数のフローを使うと、(コンプライアンス上の制約の範囲内で) 帯域の上限に近づける場合があります。
  • クライアントは、同時実行数を制限して (たとえば 4~12) 使うべきです (SHOULD)。性能の低いデバイスでは、メモリの急増を避けるために同時実行数を下げます。
  • クライアントは、同時実行数を適応的に調整してもかまいません (MAY)。スループットが上がれば増やし、エラー率が上がれば減らします。

2.3 冪等性と再試行

  • 同じチャンクを繰り返しアップロードしても冪等でなければなりません (MUST)。重複して送信されても、すでに完了した状態を壊してはなりません。
  • サーバーは、(transferId, fileId, chunkIndex) またはそれと同等の制約で一意性を保証すべきです (SHOULD)。
  • クライアントは、指数バックオフによる再試行を実装しなければなりません (MUST)。失敗時は、失敗したチャンクだけを再試行すべきです (SHOULD)。

2.4 再開できるアップロード

  • サーバーは、クライアントが完了済みのチャンクを飛ばせるように、「どのチャンクがすでにアップロードされているか」に答えられなければなりません (MUST)。
  • チャンク数に比例して状態のサイズが増えるのを避けるため、アップロード済みの集合は、ビットマップや範囲の集合として表現すべきです (SHOULD)。
  • 速度面の利点: ネットワークの中断、ブラウザーのクラッシュ、ネットワークの切り替えのあとでも、再開すれば 0% からやり直しにはなりません。

2.5 「アップロードしながら共有」 (任意)

  • システムは、納品のワークフローを加速するために、アップロードの進行中でも、利用できる転送 ID と共有リンクを発行してもかまいません (MAY)。
  • アップロードの完了前に共有を許可する場合は、受信者に何が見えるのかを明示しなければなりません (MUST)。たとえば、未完了のコンテンツはまだダウンロードできない、あるいは進捗だけが表示される、といった内容です。