代表的な面接トピック

バックエンド面接:HTTP 413 Content Too Large のコントラクトをどのように設計しますか?

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

動画のアップロードが、それぞれ異なるサイズ制限を持つ CDN、API ゲートウェイ、アプリケーション、オブジェクトストレージを経由します。サービスはどのように 413 を返し、Retry-After を決定し、重複した副作用なしにクライアントを復旧させるべきですか?

プロンプトと適用範囲

動画のアップロードは、CDN、API ゲートウェイ、アプリケーションサービス、オブジェクトストレージを通過し、それぞれ受け入れ可能なサイズが異なります。413 Content Too Large レスポンス、制限の検出(discovery)、再開可能なアップロード、Retry-After、エラーボディ、およびモニタリングを設計してください。

これはバックエンド API の信頼性に関する質問です。レイヤーの数や動画サイズは前提条件であり、発生頻度に関する主張ではありません。

面接官がテストしていること

  • 恒久的な制限、一時的なキャパシティ、およびボディ検証の失敗を区別できるかどうか。
  • 413 と Retry-After の関係を正確に説明できるかどうか。
  • ボディ全体を再試行するのではなく、再開可能性(resumability)を設計できるかどうか。
  • プロキシの制限、冪等性、および情報漏洩に対処できるかどうか。

行うべき明確化の質問

  1. どのレイヤーが 413 を発行し、そのスコープとリクエスト ID は保持されていますか?
  2. 制限はリクエスト単位、テナント単位、オブジェクト単位、時間枠単位、または残りのクォータ単位ですか?
  3. クライアントはチャンクの使用、再開、およびアップロードセッションの照会ができますか?
  4. 制限は固定の設定ですか、それとも一時的なキャパシティやクォータですか?
  5. 受信したバイトによって、課金、ロック、またはオブジェクトメタデータの副作用が発生する可能性はありますか?

30秒の回答

「413 は、大きすぎるコンテンツの処理をサーバーが拒否したことを意味します。固定の制限に対してクライアントを待機させるべきではありませんが、一時的な状態の場合は Retry-After を含めることができます。エッジは安定したコード、リクエスト ID、公開された制約を用いて早期に拒否すべきであり、一方でアプリケーションは実際のバイト数を検証し続けます。大容量ファイルにはアップロードセッション、チャンク、および冪等な完了処理を使用します。切断後は、再送信する前に状態を照会し、確認済みのチャンクは決して再送信しません。私はレイヤー、テナント、サイズごとに 413 を計測します。」

ステップバイステップの設計

1. 階層化された制限の定義

固定の最大値、テナントクォータ、オブジェクトポリシー、およびランタイムキャパシティには、明確な責任者(オーナー)が必要です。エッジは Content-Length に基づいて拒否できますが、アプリケーションも受信バイト数、展開後のサイズ、およびコンテンツポリシーをチェックしなければなりません。エラーにはリクエスト ID を含め、内部ノード、ディスク容量、または他のテナントのデータを開示してはなりません。

2. Retry-After の正しい使用

RFC 9110 では、413 の状態が一時的である場合にサーバーが Retry-After を生成することを許可しています。値は HTTP 日時または遅延秒数にすることができます。固定の最大値に対しては、待機ではなくリクエストの変更またはチャンク化が必要です。判明しているクォータやメンテナンスの復旧期間に対してこのヘッダーを使用し、クライアントには遅延の上限設定(cap)と検証を行わせます。

http
HTTP/1.1 413 Content Too Large
Retry-After: 120
Content-Type: application/problem+json
X-Request-Id: req-81a

3. エラーを実行可能(actionable)にする

安定したコード、スコープ、許可されたアップロードモード、最大チャンクサイズ、およびアップロードセッションのエントリポイントを返します。ゲートウェイの実装名、スタックトレース、またはデータベースエラーを決して公開しないでください。クライアントはそのコードに基づいて、同じボディを永遠に再試行する代わりに、圧縮、リサイズ、チャンク化、またはクォータの要求を行うことができます。

4. 再開可能なアップロードの提供

最初にアップロードセッションを作成し、その ID、有効期限、チャンクサイズの範囲、および完了したチャンクの照会手段を返します。各チャンクにはダイジェストと冪等性キーが付与され、完了処理は検証済みのチャンクのみを参照します。413 が発生した場合、クライアントは確認済みのデータを再送信することなく、新しいチャンクを小さくするか、新しいセッションを作成できます。

5. 一貫性のないレイヤーへの対処

ゲートウェイはアプリケーションの前に 413 を返す可能性があり、一方でアプリケーションは展開、クォータ、またはポリシーのチェック後に拒否する可能性があります。共通のエラーモデルは、すべてのレイヤーが最終的な制限を知っていると仮定することはできません。セッション作成時に現在の制約を返し、413 の発生元を監視し、あるレイヤーの一時的な値を恒久的なグローバル制限としてキャッシュしないようにします。

6. リトライ、課金、メトリクスの連携

クライアント側で 413 を分類します。固定の制限にはリクエストを変更し、一時的な制限には Retry-After に従い、セッション失敗後はセッション状態を照会します。課金が重複しないように完了処理には冪等性を使用し、放棄されたセッションは期限切れにします。制限のドリフトを検出するために、発生元レイヤー、テナント、リクエストサイズ、アップロード済みバイト数、Retry-After の遵守状況、チャンクの再送信、および最終的な復旧を追跡します。

質の高い模範回答

「私はまず、発行元のレイヤーと制限のタイプを特定します。固定の最大値の場合は、公開された制約またはチャンクのエントリポイントとともに 413 を返し、一時的なクォータまたはキャパシティの場合にのみ Retry-After を返します。大容量ファイルにはダイジェストと冪等性を備えたセッションとチャンクを使用し、切断されたクライアントは確認済みのチャンクを照会します。エッジで早期に拒否する一方で、アプリケーションは実際のバイト数と展開後のバイト数をチェックします。エラーボディには安定したコード、リクエスト ID、および次のステップのみを開示します。発生元、サイズ分布、待機遵守状況、重複完了、および復旧率を計測します。」

よくある間違い

  • すべての 413 に Retry-After を付与する → 固定制限に対して無駄な待機が発生する → 一時的な状態に対してのみ時間を使用する。
  • クライアント側で単一の制限をハードコーディングする → レイヤー間で乖離が生じる → セッション制約を返し、発生元を監視する。
  • ボディ全体を再送信する → 帯域幅と副作用が増大する → チャンク、状態照会、冪等な完了処理を使用する。
  • Content-Length のみをチェックする → 展開後または実際のバイト数が制限を超える可能性がある → 取り込み中および取り込み後に検証する。
  • 内部の制限を公開する → トポロジーやキャパシティが漏洩する → 安定したコードとリクエスト ID を返す。

フォローアップの質問と回答

413 に Retry-After がない場合、クライアントは何をすべきですか?

遅延時間を推測してはいけません。固定または未知の制限として扱い、エラーコードとセッション状態を使用して、より小さなリクエスト、チャンク、または明示的なクォータフローに切り替えます。サーバーが復旧時間を提供した場合にのみ、待機を自動化します。

チャンクもいずれかのレイヤーの制限を超えている場合はどうなりますか?

セッション作成時に現在許可されている範囲を返し、最小の有効制限以下のチャンクを選択します。ポリシーが変更された場合は、古いチャンクを再送信するのではなく、確認済みのチャンクを保持したまま新しいセッションパラメータで続行します。

ゲートウェイが 413 を返したが、アプリケーションには記録がありません。どのようにデバッグしますか?

エッジ、ゲートウェイ、アプリケーション間でリクエスト ID、受信バイト数、レスポンスの発生元を比較します。アプリケーションに記録がない場合は、まずゲートウェイの制限、ルーティング、ボディの転送を調査します。アプリケーションのログが存在しないことは、アプリケーションによる拒否を証明するものではありません。

公開情報ソース

関連する質問