設問と適用される場面
コントロールプレーンAPIは、ヘルスチェック、コントローラーの書き込み、テナントクエリ、長時間実行されるWatchを処理します。トラフィックの急増や1つのノイズの多いテナントによって、すべてのリクエストが遅延する可能性があります。優先度と公平性の制御を設計し、分類、同時実行制限、キュー、タイムアウト、デグラデーションがどのように連携して機能するかを説明してください。
面接官が評価するポイント
- 「重要」という概念を、恒久的なチームの特権ではなく監査可能なリクエストクラスに落とし込めているか。
- 単なるイングレスレートリミッターだけでなく、シート、キュー、クォータによってコントロールプレーンを保護しているか。
- 公平性の粒度、長時間リクエストによる占有、テナント分離、障害時のデグラデーションを説明できているか。
- レイテンシ、拒否率、キュー滞留時間、コントローラーの復旧時間を用いて設計を検証できているか。
回答前に確認すべき明確化のための質問
- 安全性において重要な書き込みとなるリクエストはどれで、遅延が許容される読み取りやWatchはどれですか?
- 公平性はテナント、アイデンティティ、ワークロード、リソースタイプのどれに基づいて計算されますか?緊急用の管理者パスは許可されますか?
- 保護対象はAPIサーバーですか、ダウンストリームのストレージですか、あるいはその両方ですか?
- 長時間リクエストは複数のシートを消費しますか?また、切断時にシートはどのように解放されますか?
- 過負荷時に429を返してもよいですか?それともシステムは最低限の成功率とリトライシグナルを維持する必要がありますか?
30秒の回答フレームワーク
アイデンティティ、メソッド、リソースに基づいてリクエストを制限付きの優先度フローにマッピングし、各フローに同時実行シートと公平なキューを割り当てます。高優先度には制限付きのベースライン容量を与え、低優先度は負荷時にキューイングまたは拒否します。長時間リクエストは個別に分類され、継続的な占有に対して課金されます。すべての拒否には実用的なリトライシグナルを含めます。p99レイテンシ、キュー滞留時間、429率、ダウンストリームの飽和度、および重要コントローラーの復旧時間をロールアウトの判定基準(ゲート)とします。
ステップごとの詳細解説
ステップ 1:説明可能なリクエストクラスを構築する
検証可能なアイデンティティ、HTTPメソッド、ターゲットリソース、長時間実行ステータスから分類します。クライアントが任意の「高優先度」フィールドを送信できないようにします。コントローラーの書き込み、ノードのハートビート、管理者クエリ、一括一覧取得を個別のフローに分割し、一致したルールをログに記録します。
ステップ 2:キャパシティをシートとしてモデル化する
シートは、単なるリクエスト数ではなく、同時処理能力を表します。高速な読み取りは1シートを消費し、低速なクエリやWatchはより多くのシートを必要とする場合があります。完了時またはキャンセル時にシートを解放します。ベースラインの合計が安全なキャパシティを超えないようにグローバルなシート上限を維持しつつ、各優先度に名目上の制限を割り当てます。
ステップ 3:各優先度内で公平なキューイングを適用する
優先度内では、単一のテナントがクラス全体を占有しないよう、テナントまたはフローのアイデンティティをキーとする重み付き公平キュー(weighted fair queue)を使用します。現在の制限を下回っている空でないフローをディスパッチします。エージングによって繰り返し遅延しているリクエストの重みを引き上げることはできますが、グローバルなシート上限をバイパスしてはなりません。
ステップ 4:長時間リクエストと依存関係を処理する
Watchやログの追跡には個別のバジェット、最大期間、ハートビートによるキャンセルを設定します。ストレージ、キャッシュ、外部サービスを独立した同時実行バルクヘッドで囲み、イングレスキューからダウンストリームへ無制限の負荷が伝播しないようにします。リトライ可能な障害のみを対象とし、exponential backoffとjitterを用いてリトライします。
ステップ 5:過負荷時のアクションを定義する
負荷が高まるにつれて、まず優先度の低い新規処理を一時停止し、次に一括一覧取得や高負荷なフィルターを制限し、リクエストをキューイングできない場合は最終的に429を返します。レスポンスには明確な待機時間のヒントを含めますが、クライアント側でもリトライ上限、jitter、デッドラインの実装が必要です。重要な書き込みをドロップできない場合は、耐久性のあるキューに格納し、ステータス照会可能な操作IDを返します。
ステップ 6:平均レイテンシだけでなく公平性を観測する
優先度、テナント、リクエストタイプごとに、p50、p99、キュー滞留時間、シート占有率、429エラー、キャンセル、ダウンストリームエラーを監視します。最大待機時間、重要書き込みの成功率、復旧時間、テナント間のサービス格差についてアラートを設定します。負荷テストには、特定テナントのバースト、長時間リクエストによるシート枯渇、誤分類、コントローラーの復旧を含める必要があります。
ステップ 7:安全に進化させロールバックする
制限を適用する前に、監視専用モードで新しい分類ルールのマッチングを記録します。設定はバージョン管理および監査を行い、制限付きの運用パスを維持します。シートや優先度を変更する際は、API層のメトリクスだけに頼らず、ダウンストリームのキャパシティと履歴キューの分布を比較します。
高品質な回答例
コントロールプレーンのキャパシティをグローバルなシートプールとしてモデル化します。リクエストは、アイデンティティ、メソッド、リソース、長時間実行属性を用いて優先度フローにマッピングされます。コントローラーの書き込みとノードのハートビートにはベースラインシートが与えられますが、ベースラインの合計は安全なキャパシティ未満に維持されます。通常のテナント読み取りは重み付き公平キューを共有します。Watchには個別に課金され、最大期間が設定されます。キャンセルが発生するとシートは即座に解放されます。過負荷時には、一括読み取りを一時停止し、高負荷なフィルターを制限し、処理をキューイングできない場合は待機ヒント付きの429を返します。必ず完了させるべき書き込みは耐久性キューに送られます。制限適用前に分類マッチングとテナントキュー滞留時間を測定し、ロールアウト後は重要書き込み成功率、p99、429、ダウンストリーム飽和度、復旧時間をロールバックの判定基準とします。
よくある間違い
- グローバルなQPS制限のみを設定し、長時間リクエストによる同時実行数の枯渇を許してしまう。
- 管理者や特定テナントに無制限の優先度を与え、監査不可能なリソース枯渇を引き起こす。
- 読み取り、一覧取得、Watchの違いをモデル化せず、リクエスト数だけで課金する。
- すべてのクライアントに429を即座にリトライさせ、同期的なリトライストームを引き起こす。
- 平均レイテンシのみを確認し、低優先度キューの最大待機時間を見落とす。
- カナリアリリース、バージョニング、ロールバックパスなしで制限を変更する。
フォローアップ質問と回答
フォローアップ 1:トークンバケットのみを使用しないのはなぜですか?
トークンバケットは到達率を制限しますが、同時実行コストの違い、長時間リクエストによる占有、テナント間の公平性を表現できません。イングレス層の1つとしては使えますが、シートとキューの仕組みが依然として必要です。
フォローアップ 2:高優先度が低優先度を飢餓状態(starvation)にする可能性はありますか?
はい、高優先度にも制限を設け、システムが予約枠、最大連続処理数、またはエージングを強制しない限り発生します。緊急パスであっても監査対象とし、キャパシティを制限する必要があります。
フォローアップ 3:Watchはいくつのシートを消費すべきですか?
普遍的な定数はありません。接続数、イベントレート、シリアライズコスト、ダウンストリームのクエリ負荷を測定し、控えめなベースラインを選択した上で負荷テストによって調整します。タイムアウトや切断時には必ずシートを解放しなければなりません。
フォローアップ 4:429のリトライ時間は誰が決定しますか?
サーバー側が見込み復旧時間に基づいた最小待機時間のヒントを提供し、クライアント側がexponential backoff、jitter、デッドラインを追加します。ヒントはキャパシティを保証するものではないため、クライアント側での試行回数制限も必要です。
フォローアップ 5:公平性をどのように証明しますか?
優先度内におけるシートシェア、最大キュー滞留時間、完了率など、テナントレベルの目標を定義します。グローバルな平均値のみを報告するのではなく、単一テナントのバースト時や混合負荷時における分布を比較します。
フォローアップ 6:ルールが重要な書き込みを誤って低優先度に分類した場合はどうなりますか?
ルールマッチログを保持して人手によるレビューを行えるようにし、設定はバージョン管理されたアーティファクトとしてリリースします。重要書き込みの成功率が低下した場合は、即座に分類バージョンをロールバックし、キューイングされた処理には制約付きのセーフティパスを使用します。