Cloudflareがセキュリティスキャンを10倍に拡大、Kafkaを壊さずに実現
CloudflareはSecurity Insightsのスキャンパイプラインを再設計し、10倍のスループットを実現。Kafkaの先頭ブロッキング、大陸間データベースレイテンシ、スパイク状のスケジューラといった課題に取り組んだ。

CloudflareのSecurity Insights機能は、すべての顧客アカウント、ゾーン、DNSレコードに対して自動スキャンを実行し、設定ミスを検出する。問題は?スキャンは1〜2週間に1回しか実行されず、多くの無料アカウントはまったくスキャンされていなかった。このギャップを埋めるため、チームは毎秒10スキャンから100スキャンへの10倍の増加を達成する必要があった。既存のシステムはすでにタイムアウト、プロセスクラッシュ、数百万件のイベントのバックログで機能不全に陥っていた。
Kafka:キューではないが、ほぼそれに近い
スキャンパイプラインは、Apache Kafkaにメッセージを発行するスケジューラによってトリガーされる。専用のGoマイクロサービス(チェッカー)がこれらのメッセージを消費し、内部APIを介してPostgresデータベースに結果を書き込む。Kafkaのパーティションモデルでは、コンシューマグループごとに1つのパーティションに1つのコンシューマしか割り当てられず、メッセージはパーティション内で順序どおりに処理されなければならない。これにより2つのボトルネックが生じる:遅いメッセージがコンシューマをブロックし、コンシューマの数はパーティションの数によって制限される。
パーティションを追加する(共有Kafkaブローカーに負荷がかかる)代わりに、チームは並列処理を導入した。チェッカーはメッセージをバッチで消費し、各メッセージを個別のgoroutineで処理する。トレードオフ(クラッシュ時に再実行する作業が増え、メモリがわずかに増加する)は許容範囲だった。
高速レーン、低速レーン
一部のスキャンは数分から数時間かかる(数千のアセットを持つアカウント)が、ほとんどのスキャンはミリ秒単位で完了する。先頭ブロッキングを回避するため、チームは各チェッカーを2つのコンシューマグループに分割した:「高速レーン」と「低速レーン」である。高速レーンは負荷が高そうなメッセージをスキップし、低速レーンは専用リソースでそれらを処理する。シンプルで効果的だ。
データベース書き込み:50万回のラウンドトリップからミリ秒へ
元のコードは、各インサイトを個別のSQL INSERT ... ON CONFLICT DO UPDATEで挿入していた — API呼び出しあたり最大50万回のラウンドトリップ。チームは一時テーブルへのPostgres COPYを試みたが、システムテーブルの肥大化を引き起こした。ハイブリッドソリューション:小規模バッチにはUNNEST、大規模バッチにはCOPYを使用。結果:大規模セットでは数秒かかっていた挿入が、小規模ではミリ秒に短縮された。
スループットを殺したレイテンシ
プライマリデータベースはオレゴン州ポートランドにあったが、APIはポートランドとアムステルダムでアクティブ-アクティブで動作していた。光速でも、アムステルダムとポートランド間のラウンドトリップには約50msかかった。それほどひどくは聞こえないが、リクエスト量が多いと、アムステルダムのコネクションプールがすぐに枯渇し、タイムアウトが発生した。さらに悪いことに、アムステルダム向けのコンシューマプロセスに割り当てられたKafkaパーティションは深刻に遅延した — ちょうど半分のパーティションが遅れをとった。修正:APIをアクティブ-パッシブに切り替え、すべてのトラフィックをポートランドインスタンスにルーティング。レイテンシは約3秒から約10msに低下した。
スケジューラ:スタンピードを止めろ
元のスケジューラは、last_scheduled_at + frequency <= nowのアカウントをループしていた。多くのアカウントが同じlast_scheduled_atを共有していたため、スキャンは巨大なスパイクとして到着した。多数のゾーンを持つ大規模アカウントは、連鎖的な洪水を引き起こした。チームは3つの変更を行った:ゾーンを個別にスケジュール(各ゾーンに独自のlast_scheduled_atを設定)、既存のアカウントとゾーンの初期タイムスタンプをランダム化、スケジューリングに適応型レート制限を追加。スキャンは時間的に均一に分散されるようになった。
結果:10倍のスループット向上、数百万のアカウントで自動スキャンが有効化、全員のスキャン頻度が2倍に。新しいパーティションも新しいハードウェアも不要 — 注意深いエンジニアリングだけだ。
ディスカッション
0 件のコメント
最初のコメントを投稿しましょう。