1 秒間で 100 万件のリクエストに対応するクライアントサイドの負荷分散

2026/07/01 20:35

1 秒間で 100 万件のリクエストに対応するクライアントサイドの負荷分散

RSS: https://news.ycombinator.com/rss

要約

Japanese 訳:

Zalando は、共有 Skipper ingress ロードバランサー上で発生した内部の高容量ファンアウトトラフィックによる重要なパフォーマンスのボトルネックを解消するために、Product Read API(PRAPI)の大規模なリファクタを実行しました。これらのリクエストを新規のクライアントサイドロードバランシング(CSLB)スタンドアロン JVM モジュールへ移行することで、キャッシュのパリティは同一のxxHash64アルゴリズムを使用して維持しつつ、速度とコストの大幅な改善を達成しました。アーキテクチャの変更では、ポーリングを廃止し 2 秒のdebounce を適用したウォッチベースの Kubernetes informerを採用することで、コントロールプレーンの枯渇を防ぎました。安全なリリースを確保するため、チームはパーセンテージベースの段階的導入戦略、アラームバッファ、ビルドキャッシングによるデプロイパイプラインの最適化、「N-ring fade-in」機構を導入しました。「N-ring fade-in」機構はスケーリングアップに伴う遅延に対応すると同時に読み込みバーストを引き起こさないように設計されています。追加の最適化として、HPA ロードシグナルをリクエストスループットから**占有度(occupancy)**へ切り替え、ポッド総数を 25% 以上削減し、日常運用コストを 450 ドルから約 110 ドル(および追加の 1,000 ドル以上)へと削減しました。さらなる強化策には、リトライポリシーの厳格化、過負荷保護のための FIFO バッファの追加、デスチネイションポッド IP のログ記録が含まれます。本プロジェクトは、アルゴリズム的な調整単独よりも、詳細なルーティングテlemetry を所有する方が価値が高く、共有リソースによって以前には隠蔽されていた潜在的インフラストラクチャの不具合を明らかにすることを示しました。

本文

高負荷 API の「共有エッジロードバランサー」からの脱却:クライアントサイドロードバランシング(CSLB)への移行と最適化

Zalando の主要サービスである Product Read API (PRAPI) では、毎秒数百万件のリクエストを処理し、ミリ秒単位のレイテンシーを実現しています。しかし、共有インフラとして利用していた Skipper を介した内部トラフィックにより、重大なパフォーマンス問題が発生していました。この記事では、共有ロードバランサーからの移行と、自社工場で開発した最適化手法について解説します。


1. 課題:共有エッジロードバランサー「Skipper」の罠

サービス開始当初、PRAPI は Skipper という Kubernetes エンゲレスコントローラー(HTTP ルーター)を Edge ロードバランサーとして使用していました。

  • 目的: キャッシュ locality を高めるため、同じ製品 ID を同じポッド群へルーティングする「一貫性ハッシュルーティング」を実装。
  • 問題点: Skipper はバッチ処理エンドポイント(1 リクエストで最大 100 ポッドへの呼び出し)において以下の弱点を露呈しました。
    • 「くしゃみと風邪」: Skipper が数マイクロ秒の遅延を起こすと、直下流の PRAPI がその影響を大きく受けてレイテンシーが跳ね上がりました。
    • 原因不明: レイテンピークの原因が「Skipper 自身」なのか「自社のコード」なのか判断できず、デバッグに時間を要しました。
    • 共有インフラのリスク: Skipper を直接管理できないため、振る舞いを分離することが困難でした。

解決策:ファンアウトパスの移行

共有 Skipper を経由する内部トラフィックは、プロセス内で実行する**クライアントサイドロードバランシング(CSLB)**へ移行することを決断しました。

  • 移行方針:
    • Edge ロードバランサーとしての Skipper は維持する。
    • 高ファンアウトの内部トラフィックのみを CSLB にシフトさせる(Skipper の置換ではなく、パスの分岐)。

2. アプローチ:「同じハッシュリング」の実装

移行において最も重要な制約は**ハッシュの平行性(Hash Parity)**でした。

  • 要件: Skipper と自社 CSLB が、常に同じ製品ポッドプールのいずれかをリクエストへ割り当てる必要があります。
  • リスク: ハッシュリングが合致しなければ、キャッシュ分断が発生し、DynamoDB への読み込み負荷が 2 倍になります。

実装の鍵:Skipper と同一のアルゴリズム

Skipper が使用する仕組みを完全に複製しました。

  • ハッシュ関数:
    xxHash64
    を使用。
  • リング構造:
    • 64 ビットのハッシュリング上に、各エンドポイントを 100 の位置に配置。
    • 時計回り方向の最も近いエンドポイントを探す。
  • 安定性の保証:
    • ユニットテストで Banc(銀行)により、両者のリングが同一であることを断言。
    • 毎回のビルドで実行し、「静かなずけ(Silent Drift)」を防ぐ。

Kubernetes Discovery:ポーリングから Watch へ移行

Kubernetes API を頻繁にポーリングするアプローチは、コントロールプレーンを停止させるインシデントを引き起こすリスクがありました。これに対処するため、以下の**Informer(リスト + ウォッチ)**方式へ変更しました。

  • 起動時: 現在の
    EndpointSlices
    リストを参照しリングを初期化。
  • 以後: リアルタイムの変更点をストリーミングする Watch を保持。
  • デボーン処理: スケールアップ時の急激な変化を単一のリング更新に統合(約 2 秒)。

informer (リスト + ウォッチ)

  • 起動時: 現在の EndpointSlices をリストアップし、リングを初期化
  • その後ストリーミングで追加/更新/削除イベントを受け取る
    • 各イベントあたり:
      • ローカルパー・スライスキャッシュを更新
      • 2 秒デボーン付きの applyLocalState() をスケジュール
        • デボーンにより、ロールアウト中のチャンジョールを単一のリング更新に統合

3. パイプラインの修復:高速かつ安全なデプロイ

最適化の実施には、信頼できるデプロイメントパイプラインが必要です。過去の課題は以下の通りでした。

  • ビルド時間: 21 分 → 手動ステップが多い。
  • ロールアウト: 1 つの機能変更でも数日間(中央値で 4 時間 49 分)かかり、大規模なバビーシティングが必要だった。

改善策

以下の 3 つの PR でパイプラインを劇的に改善しました。

  • ビルドキャッシングの導入: ビルド時間を 12 分に短縮。
  • CI/CD の統合: 40 に及ぶ手動ステップを自動化。
  • 承認ゲートの廃止: 小規模なリージョン(eu-0, eu-1)でロールアウトし、安定後に全展開(eu-2)へ移行するアプローチへ変更。

結果:

  • 中央値デプロイメント時間:289 分 → 128 分へ減少。
  • CI/CD パイプライン実行時間の最悪ケース:ほぼ 5 日 → 1〜2 時間へ短縮。
  • 影響: チームがパイプラインを信頼するようになり、実験コストが低下しました。

安全なロールアウト戦略

段階的な切り替えを行うためのトグル(切り替えスイッチ)を実装しました。

トグル名機能
CSLB_ENABLED
CSLB のオン/オフ制御
CSLB_PERCENTAGE
0〜100 のトラフィックランプ(CSLB と Skipper バックアップ経路の比率)
暗黙的な Skipper バックアップクライアントサイド経由で失敗時や未ルーティング時のフォールバックパス
  • ロールアウト手順:
    1. Canary マーケットグループで 1% から開始。
    2. 段階的に 10%, 50% と増加。
    3. 全市場グループで 100% に到達。
  • 監視指標: レイテンシー、エラー率、キャッシュヒット率の即時比較。

成果:

  • Skipper を経由するトラフィックはピーク時にほぼゼロに収束。
  • 日次 Skipper ノードグループのコスト:約 $450 → 約 $110 へ削減。
  • Skipper フリート(50 ポッド以上)を8 ポッドまで削減し、コストプロジェクトから運用性向上プロジェクトへ転換。

4. スケールアップスプライクの排除:N-Ring フェードイン

Skipper から除去したことで残った問題として、「新ポッド追加時の冷キャッシュ」と「スケールアップスプライク」がありました。

N-Ring フェードイン手法

従来の確率的プリフィルタでは、フェード完了後に製品がサービスできない状態が残るリスクがありました。これに対し、N-Ring手法を導入しました。

  • 仕組み: 各スケールイベントで、既存リングのスーパーセット(新リング)を作成。新リングのみを独立してフェードインさせます。
  • カーブ: 緩やかなスタート、急激な完了を制御(例:30 秒で完了)。

N-Ring フェードインの効果:

  • 正しい製品 ID を持つポッドのみをウォームアップ可能。
  • キャッシュエントリーの無駄やエビジョンチャンジョールを排除。
  • ポッド追加時、各リングでの位置は同一のため、定常状態に近いトラフィック分担を実現。
経過時間進行度トラフィックシェア
3 秒10%0.3%
9 秒30%4.9%
15 秒50%17.7%
21 秒70%41.0%
27 秒90%76.8%
30 秒100%100%

注:最初のフェードイン完了中に第 2 のスケールイベントが発生した場合、各イベントは独立したウィンドウを持ち、重ならないように制御されます。


5. ポッド占有度の制御とバウンデッドロード

定常状態において一部のポッドが過熱し、他のポッドがアイドル状態という不均一性を解消するため、「ポッド占有度(Occupancy)」を指標として採用しました。

なぜ「In-flight」ではダメか?

  • In-flight(進行中)のリクエスト数は、高速なキャッシュヒットと低速な DynamoDB ミスを見分けることができないため、不正確な指標でした。
  • シンプルにリクエスト数で判定すると、苦しんでいるポッドを早期にスケールアウトする必要が出てき、余剰容量が浪費されます。

正しい信号:Occupancy(占有度)

  • 定義: 「1 秒あたりの作業時間」。
  • 計算式:
    occupancy = total_occupied_time / window_duration
    • パルス間のカウントがゼロになっても、作業時間に基づいて負荷を正確に評価。

スループットミスの修正とリトルの法則(Little's Law)

初期実装ではスループット(1 秒間のリクエスト数)を使用しましたが、これではキャッシュヒット率の高い短時間リクエストが過大評価されました。

  • 解決策: キューイング理論に基づくリトルの法則適用。 [ L = \lambda W ] (平均同時並行数 = 到着率 × 平均サービス時間)
  • 実装: スライディング時間ウィンドウ内で「継続時間を蓄積」し、時間で割ることで負荷を正しく測定。

信号の比較:

信号報告負荷理由付け
In-flight0パルス間サンプリングで何もしない場合
Throughput1,000 req/s継続時間に関係なくカウント
Occupancy~1.01,000 x 1ms = 1.0 秒分の作業/秒

バウンデッドロードの最適化

  • 基本動作: ポッド負荷が平均を超えると、リングを時計回りに探索(ウォーク)して負荷が少ない候補を探す。
  • 有効負荷の計算: レイテンシーも考慮した重み付けを実装。 [ effectiveLoad = max(inflight, occupancy) \times min(podLatency / globalLatency, 5) ]
    • スローなポッド(高いレイテンシ)を適切に重み付けし、トラフィックから迂回させる。
  • ウォークの上限: 最悪の場合、リング全体を探索するのを防ぎ、キャッシュヒット率低下を防ぐため、10 ホップに制限。

インパクト

  • 占有度バンド: 0.4〜1.3 の広がり → 0.6〜0.9の緊密な帯へ収束。
  • バウンデッドロード係数: 慎重な 1.10 から、余剰容量を活かせるように緩和された 1.25へ。
  • Horizontal Pod Autoscaler 閾値: CPU 65%(以前は 50%)へ引き上げ。
  • 結果: ポッド数 25% 以上減少し、コスト削減が日額 $1,000 を超えるように。

6. AZ-Aware(リージョン意識型)ルーティングの挑戦

最後に残ったフロンティアは、利用可能なゾーン(AZ)間でのルーティングでした。

  • 課題: Skipper を経由すると約 2/3 のホップが AZ 境界を跨ぎ、データ転送コストとレイテンシが発生します。
  • リスク: 局所ゾーンに十分なポッドがない場合、キャッシュフラグメンテーション(分断)を引き起こす可能性があります。

慎重なフェードイン

  • ランダムにゾーンアフィニティを ON にせず、初期には全ゾーン待機期間中に局所キャッシュをウォームアップ。
  • レイテンシーヘルス係数を監視し、局所レイテンシが設定マージン(35%)以上ドリフトすると、自動的に 1% のプローブフロアへ抑制。

バウンデッドロードの再計算

フェードイン中に、局所ポッドは両リング(局所分・全域分)からのトラフィックを受け持つため、単純なクラスター平均では過負荷に見えました。

  • 解決策: 各ポッドが実際に受け持つ負荷に基づいた動的閾値を計算。 [ threshold = (loadPerLocalPod + loadPerGlobalPod) \times balanceFactor ]
  • これにより、フェードイン中の非対称性を無視せず、真の外れ値のみでトリガーされるよう調整。

2 つのフェードインの衝突

  • 問題: ポッド追加時の N-Ring フェードイン と、ゾーン切り替えのフェードアウトが同時に発生する際のエッジケース。
  • 現状: アルゴリズムと Safeguards(安全装置)は整備済みですが、長時間稼働させるには On-Call チームによる監視が必要となり、現在は一時停止状態です。

7. ファンアウトパスのハードニング

CSLB を導入したことで、再試行やタイムアウトなどの制御権が自社に戻り、より強力なレイテンシ保護が可能になりました。

フェイルセーフとファウルオーバー

  • 再試行ポリシー: 緊密なバックオフを持つ単一の高速再試行へ。トランスポート障害や 5xx に対してのみ発火。
  • FIFO バッファ: 過負荷フィルターにより、キャップを超えた入力却下を防止し、キュー自体が自己排水(完了待機)。
  • ログの強化: 失敗時に「呼び出し先のポッド IP」および「ノード」を記録。これにより、ネットワークレイヤーやノードレベルでのフリーズを検知可能に。

結果:PRAPI の高可用性

  • フリーズ中のノードは、他の健康なポッドへの自動迂回により影響が限定されます(1 ノード上の数ポッドのみ)。
  • システム全体としては「3 時のページコール」から「グラフの微細な揺らぎ」へと変化。
  • インパクト: PRAPI は共有インフラからの依存性を脱却し、独自の失敗面を掌握しました。

8. レッスンと結論

得られた学び

  1. キャッシュローカリティ vs コスト削減のトレードオフ: AZ アフィニティはコスト削減に寄与しますが、キャッシュ分断リスクがあります。各パーティションがホット製品をカバーできるか確認が必要です。
  2. パイプラインの重要性: スローなデプロイメントはリスクを高めます。小規模なインクリメンタルな変更と自動アラームバッファを持つパイプラインが安全です。
  3. 所有即責任: ルーティング決定を所有すると、テレメトリも同時におさえます。共有インフラに隠れていた障害(例:特定のノードのフリーズ)が見えるようになります。
  4. コスト削減の総額: Skipper フリート削減 + 占有度ベースの最適化により、日額 $1,000 超のコスト削減を実現しました。

次に何をすべきか?

現在は AZ-Aware ルーティングが唯一の未完了スレッドです。

  • エコノミーとトレードオフを慎重に検証中。
  • 高トラフィック時にはホットセットをカバーするだけのポッドを持ち、大規模な節約につながる可能性があります。

自作すべきか?

一般的には「やらない」のが賢明です。成熟したプロキシ(Skipper, Envoy など)が標準機能を提供します。しかし、共有インフラの暴露面積が過大になりやすい場合や、極めて高いパフォーマンス要件がある場合には、自社でリングを実装し、詳細な可視性を確保することが有効であることが証明されました。


参考: Zalando の SPP Product Data Serving チームによる実装事例に基づく.

同じ日のほかのニュース

一覧に戻る →

2026/07/03 6:03

バージニア州、地理的位置データ販売を禁止

## Japanese Translation: 提供されたテキストは、一貫した記事ではなく二進データ、符号化文字、および読み取れない内容のみから構成されているため、要約することができません。事実や日付、製品名を含む標準的な記事とは異なり、この源資料には有意義な分析に必要な理解可能性を欠いています。その解読不可能な性質から、特定の文脈、出来事、または背景情報は導き出すことができません。テキストを処理できないというこの状況のため、有益な洞察や関連する事実を引き出すことは不可能です。源入力を人間が読み取れる言語に変換されるまで、有効な要約を作成することは不可能です。その間もなお、中央テーマ、主要な論点、または具体的な物語を特定しようとするのは無駄であり、データには識別可能なストーリーが存在しないためです。最も重要な点は、この入力が混乱した非構造化形式のため、標準的な読解タスクに根本的に使用できないということです。

2026/07/03 3:41

エキスパンクス(2018)

## Japanese Translation: EXAPUNKS プロジェクトは、プレイヤーが現実的なハッキング活動に取り組み、「EXas」と呼ばれる自律エージェントを管理し、複雑なデジタルタスクを実行できるサンドボックス環境を提供します。従来のシミュレーションとは異なり、このエコシステムではユーザーが現実世界の物体を操作したり、実際のネットワークを侵害したりし、その侵害された状態の中でゲーム世界内で安全に行動することができます。体験の中核には、秘密のヒント、コメント、チュートリアル、EXas をプログラミングしてファイルを破棄させたり、自己複製したり、他のエージェントを停止させたり、痕跡を残さずに姿を消させたりするための詳細を提供する公式 *TRASH WORLD NEWS* ズィンがあります。プレイヤーは銀行、大学、工場、テレビ局、高速道路の標識、ゲームコンソール、政府システム、さらには自身の肉体など幅広い対象を対象とし、その後「ПАСЬЯНС」(パシアンズ)、地域ロックをハッキングした後の「HACK*MATCH」、あるいは TEC Redshift 用のホームブロー開発などの代替ミニゲームにアクセスできます。物理的なデラックス版のズィンセットは、2020 年 4 月に Lulu でのオンデマンド印刷を通じて復活し、7 ドルプラス送料で提供されましたが、両方の号への注文が必要でした。開発者向けには、2018 年 7 月 16 日に詳細とともにリリースされた「Axiom VirtualNetwork+」があり、ホスト、ファイル、レジスタ、ゴール、そしてその API を通じた完全なパズル仕様機能を利用して、ホストスクリプトを記述した JavaScript ベースの「バーチャルネットワーク」を作成することでカスタムパズルの作成が可能になります。2018 年と 2020 年のこれらのリリース以降、専用のコミュニティが栄え、標準的な商業制約を超えたサイバーセキュリティの探求やイノベーションを促進し続けます。

2026/06/28 8:36

現実には驚くほど多くの詳細が存在する (2017)

## Japanese Translation: 私たちが単純なものとして扱っている多くのタスク—地下室の階段を築くことや水を沸かすことなど—is、実行前に深い調査が必要となる重要な細部を隠しています。著者の父は 18 歳でコロンビアから北米へ移住し、実地作業を通じて建築を教えてくれました(フェンスの取り替え、塹壕の掘削、床および小屋の築造など)。著者はフェンスの手すりを取り替える際、床を敷設し、地下室の階段を築く際にこの教訓を実際の経験として学びました。 二つの 2×12 に角度ブラケットを用いて作られた階段は一見単純に見えますが、複数の副次的タスクを含んでいます:切り取り角度を計算またはトラACING し、U ブラケットを取り付けること、および板材を固定することです。木材は乾燥するにつれて歪むため、2x12 を正しい角度に切り取ることは容易ではありません。視覚的な対齐も失敗するため、三角関数を使用するか、円鋸用ガイドを雇用するか、または計算だけよりも木目追跡の方法を好む必要があります。ブラケットを引かれた線上に合わせてからネジを取り付けた場合でも、最初にもうけホールを掘らないとネジが斜めに取り付けられてしまいます;ブラケットを数インチ移動して再 drilling することでより良い結果が得られます。2 インチより長いネジを使用すると、階段の踏み面から突き抜け足に刺さるリスクがあるため、短いネジが不可欠です。 同様に、沸騰は単に「100°C の水」ではありません。真の沸騰の前に小さな気泡が発生します。ガラス鍋はより高い温度を耐え、硫酸で清掃されたガラス容器では水を過加熱することができ、攪拌によって爆発的に飛び散ります。二つの液体の間にわずか一滴の水を挟むだけでも、沸騰せずに約 300°C に加熱でき、一般的な主張と矛盾します。これらのリスクは、充填ベッドとロケット軌道計画を必要とする工業プロセスにも広がっており、見えない力は正確なスロットル制御と使い回し可能なロケットのための慎重な重量管理を要求します。 歴史もこれらの教訓に反響しています:アルコール熱計は 18 世紀にジャン=アンドレ・デュリュがその非線形性を明らかにするまで標準的なものでした。重要な細部が見えないままにされる時、知的な行き詰まりが生じます—例えば、「すべてのデータは「偽造されている」と主張し気候変動を否定する代わりに、見落とした過ちを注意すること—。一度見えなかった細部が出会うと透明化し、進捗はそれを見無視する場合のみ停滞します(例:三角関数 versus トラACING を巡る家族の議論)。究極的に言えば、住宅修理、大規模なエンジニアリング、科学的探究における成功は、予期しない変数を積極的に探し求め、詳細な観察を受け入れ、表面的な仮説への依存を拒むことにかかっています。

1 秒間で 100 万件のリクエストに対応するクライアントサイドの負荷分散 | そっか~ニュース