- 10億ページを24時間でクロールした実体験と、現代的なWebクローリングシステム設計の過程を共有
- 最新のハードウェアとクラウド基盤により、数百ドル規模のコストで大規模クローリングを実現し、主なボトルネックがパース処理であることを確認
- JavaScriptは実行せず、HTMLパースのみを行ったが、それでも相当数のWebページにアクセス可能だった
- Redisベースのノードクラスタアーキテクチャを設計し、ドメイン単位のシャーディングとプロセス構成の最適化で効率を最大化
- ネットワークよりもCPU・SSL・メモリが主要なボトルネックとして表れ、大規模ドメインのフロンティア管理が重要な課題だった
問題定義
- 24時間以内に10億ページをクロールするという目標を設定
- 予算は数百ドル(最終的に約462ドル)で、2012年の事例と同程度に合わせた
- HTMLのみを収集し、JavaScriptは実行せず
<a> リンクだけを抽出
- **Politeness(礼儀あるクロール)**を重視し、robots.txtの順守、User Agent情報の明記、要請時のドメイン除外、人気上位100万ドメインのみを対象、同一ドメインに70秒待機などを適用
- 耐障害性を確保し、ノード障害時の再起動や一部データ消失を織り込み済みとするサンプルベースのアプローチを採用
アーキテクチャと設計
- **従来のシステム設計面接スタイル(機能ごとに分散)**とは異なり、各ノードがすべての機能(クロール状態、パース、フェッチ、保存など)を自前で処理する構成を選択
- 12ノードを使用し、各ノードは
i7i.4xlarge(16 vCPU、128GB RAM、10Gbps、3750GBストレージ)インスタンスを採用
- 各ノードは1つのRedis、9つのfetcher、6つのparserプロセスで構成
- Redisにはドメイン別フロンティア、fetch queue、訪問済みURL、Bloom filter、robots.txt、パースキューなどを保存
- Fetcher: ドメインごとにキューから取り出してURLをフェッチし、asyncioで6000〜7000の同時処理を実行、主なボトルネックはCPU
- Parser: 80個のasyncワーカーでHTMLをパースしリンクを抽出、CPU中心の処理
- ストレージ: S3ではなくインスタンスのローカルストレージを選び、大容量ページ保存コストを削減
- シャーディング: ドメイン単位でノードに分配し(クロスコミュニケーションなし)、人気ドメインの偏りを解消するためシャード数を調整
主な代替案と実験
- SQLite、PostgreSQLなどさまざまなストレージを試し、最終的にRedisが最も高性能だった
- 垂直スケーリング(単一の大型インスタンス)も試したが、ソフトウェア上の限界でボトルネックが発生し、最終的に水平スケーリング(複数ノード)構成を採用
- ノード間のクロスコミュニケーションをなくし、単一ノード内で並列処理する方式にした
クローリング過程での主な教訓
パースが最大のボトルネック
- 平均ページサイズは過去(2012年の51KB)より大幅に増加し、平均242KB、中央値138KBになっていた
- lxml から selectolax(Lexborベース) に変更すると、パース速度が大幅に向上
- ページ最大サイズを250KBに切り詰めることで効率を改善
- 結果として、単一parserで毎秒160ページのパースを達成し、最終的にfetcher:parser比率を9:6に調整して約950ページ/秒を処理
Fetching: 容易になった点と難しくなった点
- ネットワーク帯域はむしろボトルネックではなかった(ノードあたり25Gbps中、およそ8Gbpsしか使用していない)
- DNSのボトルネックも、人気ドメインのみを対象にしたため問題にならなかった
- 一方で、SSLハンドシェイクがCPU使用量全体の25%を占め、最大級のボトルネックの一つになった
- ページの大半がHTTPSへ移行したことで、CPUコストが増加した
実運用でのクロール実行と問題点
- 初期実験では単一ノード(
i7i.2xlarge)で数時間だけ試し、本番クロールでは12ノードに拡張
- メモリ問題が発生し、人気ドメインのフロンティア(未訪問URL)が数十GBまで増えて、ノードが繰り返しダウンした
- 人気ドメイン(例: yahoo.com、wikipedia.org)や、異常にリンク数の多いサイトが問題を引き起こした
- 問題のあるドメインは手動で除外し、障害発生時はノード再起動とフロンティアの切り詰めで復旧
理論と実践の比較
- 従来の教科書的手法である「5台のマシンで5日間に100億ページ」という見積もりと比較して、実測値はある程度近かった
- 各ノードの実際のネットワークおよびCPU使用率を踏まえると、最適化次第ではさらに高いスループットも可能
今後の課題と考察
- HTMLパースだけでも相当数のWebページにアクセス可能であることを再確認。ただし大規模プラットフォーム(例: GitHubなど)は意味のある本文がJS内に含まれており、パースできない
- 今後の課題として、JSレンダリングベースの大規模クローリングのコストと手法の探究が必要
- データ分析(実際に収集したページのメタ情報、アクティブ/非アクティブ比率など)も後続テーマとして挙げられている
- 最近はAIと組み合わせた**攻撃的クローリングが増えており、Cloudflareのpay-per-crawl**のような新たな防御策も登場するなど、Webクローリング環境は再び変化している
3件のコメント
すごいですね..パチパチパチ...
興味深いですね。よく読ませていただきました。ありがとうございます
すごいですね……。矛と盾の戦いなんでしょうか(笑)