ほとんどのスクレイピングシステムが行き着くアーキテクチャは、クラウドプロバイダー上のコンテナで、キューの深さに応じてスケールし、ステートレスで使い捨てというものだ。これはコンピュートにとっては正しい設計だ。しかしエグレスにとっては最悪の設計になる。なぜなら、そうしたコンテナが取得するアドレスこそが、防御されたサイトが最初にチェックする項目だからだ。
クラウドプロバイダーのIPレンジは公開されている。誰でも列挙できるし、ほとんどのアンチボットベンダーは実際にそうしている。そこからのトラフィックがブロックされるのは、それが何をしたかによってではなく、最初のリクエストが完了する前に、どこから来たかによってスコアリングされるからだ。解決策はワーカーを増やすことでも、ヘッダーを改善することでもない。コードが動く場所と、トラフィックが出ていく場所を分離することだ。
エグレス層は別個の関心事である
有用なメンタルモデルは、ワーカーはコンピュートであり、アドレスはアイデンティティであって、それぞれ独立してスケールすべきだというものだ。
一時的なワーカーは良いものだ。50個起動し、キューを片付け、停止する。しかし一時的なアイデンティティは通常好ましくない。新しいクラウドアドレスから到着する新しいワーカーはそれぞれ、見慣れないトラフィックの流れになる。求められているのは、ワーカーの世代交代をまたいで永続する、安定したエグレスアドレスの集合だ。そうすれば、オートスケーラーが反応するたびにターゲット側が見るアイデンティティが入れ替わることがなくなる。
ISPプロキシがその役割にまさに適しているのは、固定されているからだ。各アドレスはプランの期間中アカウント専用で割り当てられ、クラウドブロックではなく実際のISPに登録されており、ローテーションしない。ワーカーは出たり入ったりするが、アドレスは変わらない。
2つの認証モード、そしてその選択はアーキテクチャに関わる
プラン内のすべてのアドレスは同じポート(1337)を使用し、認証方法は2種類ある。クラウドデプロイメントでは、これは好みの問題ではなく、あなたのネットワーキングの構成によって決まる。
認証済み送信元IP。 パネルであなたのインフラの公開アドレスをホワイトリストに登録し、認証情報なしで接続する。
185.199.108.153:1337これはエグレスが予測可能な場合、つまり実際にはワーカーの手前にNATゲートウェイなど安定したアドレスを持つ仕組みがある場合に機能する。これが当てはまる状況では、コンテナ内に認証情報が一切存在しないため、よりクリーンな選択肢になる。
ユーザー名とパスワード。 どこからでも動作し、ホワイトリストは不要。
185.199.108.153:1337:USERNAME:PASSWORDこれはワーカーが本当に一時的で、送信元アドレスが変わり続ける場合や、複数リージョンに分散している場合、あるいは送信元アドレスを制御できない環境で動作している場合に求められる方式だ。サーバーレス関数やマルチリージョンデプロイメントはここに該当する。
罠になるのは、実際には送信元アドレスが固定されていない環境で送信元IP認証を選んでしまうことだ。1つのサブネットからのテスト中はうまく動くが、プラットフォームが別の場所にアドレスを割り当てるようになると、本番環境で断続的に失敗し始める。エグレスアドレスを確信を持って明言できないなら、認証情報を使うべきだ。
ワーカー間でのアドレス配分
N個のアドレスと可変数のワーカーがある以上、何かがそれらを対応付けなければならない。
うまく機能するアプローチは、各ワーカーに勝手に選ばせるのではなく、アドレスリストを明示的なリースを伴う共有リソースとして扱うことだ。ワーカーは調整レイヤーからアドレスを取得し、ジョブの期間中保持し、返却する。重要な性質は2つある。2つのワーカーが同時に1つのアドレスを使うことで見かけ上のリクエストレートが倍増しないこと、そしてワーカーのクラッシュがアドレスを流通から永久に取り除いてしまわないことだ。
単純な代替案、つまりワーカーのIDをインデックスにハッシュする方法は、ワーカー数が変わった瞬間に破綻する。オートスケールされたデプロイメントではこれは常時起こる。スケールアップ時には衝突が起き、スケールダウン時にはアイドルなアドレスが発生する。
ここで実際の予算となるのは、アドレスごとのリクエストレートだ。ISPプランの帯域幅は無制限なので、制約はギガバイト数ではなく、1つの固定アドレスがどれだけのトラフィックをもっともらしく生成できるかだ。この数値がデプロイメントに必要なアドレス数を決定する。だからこそ、データ量ではなくスループットに基づいてサイジングすることが正しいやり方なのだ。
ヘルスチェックはプールに組み込むべき
アドレスは均一に失敗するわけではない。特定のターゲットから1つのアドレスがチャレンジを受け始める一方で、他はすべて問題ないということが起こりうる。そのアドレスを受け取ったワーカーは、何かが気づくまでゴミデータを生成し続けることになる。
集計ではなくアドレスごとに結果を追跡すべきだ。複数のターゲットから収集している場合はターゲットごとに、ローリングウィンドウでのアドレスごとの成功率を見れば、プール全体を止めることなく1つのアドレスを隔離できる。集計指標では5%の低下しか見えず、実際には1つのアドレスが完全に失敗していることが隠れてしまう。
隔離は一時的かつ自動であるべきで、回復すればアドレスを戻すプローブを備える。そもそも「正常」とはどのような状態かを確立する方法については、プロキシの速度、成功率、位置精度のテスト方法で解説している。
購入前に地域構成を計画する
クラウドチームが引っかかりやすい点が1つある。ISPプランでは国別分布を、アドレスがプロビジョニングされる前に一度だけ選択し、その後は変更できない。利用可能な国は7カ国だ。
これは、安価に方針を変更することに慣れているクラウドデプロイメントの他のほぼすべての要素とは異なる。実際に収集対象としているターゲットに対して分布を決定し、2つの市場のどちらか迷う場合は、推測するのではなく、確信の持てる方のプランを購入し、後から追加するようにすべきだ。
ISPが誤った選択となる場合
固定アドレスはローテーションの一般的な代替にはならない。しかしクラウドインフラは運用モデルがはるかに単純であるがゆえに、そうであるかのように錯覚させてしまう。
多数のターゲットにわたる大量収集がワークロードである場合、コストが問題になるずっと前にアドレスごとのリクエストレートが非現実的になる。その兆候はエラーではなく、データの劣化として現れる。そうした作業はローテーティングするレジデンシャルプロキシ向きだ。そこでは設計上、リクエストごとに異なるアドレスから送信できる。このトレードオフについてはISPプロキシ対データセンタープロキシとレジデンシャルプロキシで詳しく述べている。
固定エグレス層が本当に適しているワークロードは以下のとおりだ。長期にわたるセッション、認証を伴うあらゆる処理、あなたのアドレスをアローリストに登録しているターゲット、既知の送信元を期待するパートナーAPI、そしてボリュームよりも一貫性が重要な安定した収集。永続的な作業にはISPアドレスを、大量処理にはローテーティングゲートウェイを使うという混合アーキテクチャは一般的であり、正しいアプローチだ。
運用上の注意点
アドレスリストはイメージではなく設定に保持する。 プールを変更するためだけにコンテナを再ビルドするのは避けられる作業だ。起動時にシークレットストアや設定サービスから読み込むこと。
認証情報付きのURLをログに出力しない。 自然なデバッグログの1行として接続文字列全体を出力してしまうため、これがプロキシの認証情報がログ集約システムに漏れる最も一般的な経路になる。
並行数はグローバルだけでなく、アドレスごとに制限する。 グローバルな制限を小さなプールに不均等に分散させると、割り当てロジックが好むアドレスに負荷が集中する。関連する仕組みについてはレート制限とリクエストスロットリングで解説している。
デプロイメント内部からテストする。 ノートPCからの接続確認は、認証情報が動作することを証明するに過ぎない。タスク定義が環境変数を正しく渡しているかどうかについては何も証明しない。だが実際にはこれこそがほとんどの失敗の原因だ。
FAQ
サーバーレス関数からISPプロキシを使えますか?
はい、認証情報による認証を使えば可能だ。送信元IPホワイトリストは、そこでは送信元アドレスを自分で固定できないため実用的ではない。
オートスケールされたデプロイメントには何個のアドレスが必要ですか?
ワーカー数ではなく、ピーク時の同時ジョブ数と控えめに見積もったアドレスごとのリクエストレートに基づいてサイジングすべきだ。ワーカーはアイドルになってもよいが、ピーク時に不足すべきものはアドレスであってはならない。
プロキシ層がボトルネックになりますか?
ISPアドレスはギガビット速度のデータセンターインフラ上で動作するため、アドレスごとのスループットが制限になることはめったにない。通常は並行数のポリシーが先に制約となる。
サービスごとに専用のアドレスを用意すべきですか?
トラフィックパターンが大きく異なるならそうすべきだ。安定した低レートのサービスとバースト性の高いサービスを同じアドレスで混在させると、両方の扱われ方をバースト性の高い方が決めてしまうことになる。
まとめ
クラウドスクレイピングインフラがブロックされるのは、コードの品質とは無関係な理由による。アドレスがクラウドアドレスとして公開されているからだ。一時的なワーカーの手前に固定のISPエグレス層を置くことで、アイデンティティとコンピュートを分離できる。これはこのアーキテクチャがそもそも必要としていた分離だ。
アドレスは明示的にリースし、ヘルスはアドレスごとに追跡し、帯域幅ではなくリクエストレートでサイジングし、地域構成は購入前に決定すること。なぜならその選択は変更できないからだ。プランはISPプロキシの料金ページにある。