容量に関する質問の多くは、順序が逆になった状態で寄せられる。何スレッド動かすべきか、どれだけの帯域幅を購入すべきかと尋ねられても、実際の要件、たとえば「毎日更新される5万件の商品レコードを、08:00までに準備する」といった内容を翻訳しない限り、そのどちらも分かりようがない。この一文の中に必要なものはすべて含まれている。ここでは、それをリクエスト量、同時実行数、プランのサイズへと変換する方法と、制約が実際にどこで効いてくるのかを説明する。
リクエストではなくレコードから始める
最初に行う変換は、多くの人が省略してしまうものであり、そこで見積もりが何倍にもずれる。
1レコードが1リクエストに等しくなることはめったにない。商品レコード1件に対して、一覧ページと詳細ページが必要になるかもしれず、その場合は2リクエストになる。一覧ページがページネーションされていて、すべての項目が必要な場合は、そのページネーション用のリクエストを、それによって得られるレコード数で按分して加算する。詳細ページが2回目の呼び出しでデータを読み込む場合は、それがさらに1つ増える。そして、データエンドポイントを取得するのではなく、ブラウザでページをレンダリングする場合、論理的には1つのリクエストが数十件のアセット取得へと変わる。これは論理的なカウントを変えないとしても、帯域幅にとっては非常に大きな意味を持つ。
したがって、これは明示的に書き出しておく。
requests_per_record = detail_pages + (listing_pages / records_per_listing) + extra_calls
たとえば5万件のレコードに対して、1件あたり1.2リクエストとすると、1回の実行で60,000リクエストになる。ここに失敗分の余裕を加える必要がある。検証済みの成功率は100%ではないからだ。成功率90%であれば、60,000件の成功を得るためにはおよそ67,000回の試行が必要であり、一時的な失敗を再試行する場合、実際の数字はさらに少し高くなる。試行回数ではなく成功回数を基準に計画を立てないことが、2番目によくある見積もりの誤りである。
同時実行数はレート・レイテンシから導かれる
次に、多くの人が意外に思う点がある。同時実行数は自由に選べる数値ではなく、どれだけ速く進める必要があるか、そして各リクエストにどれだけ時間がかかるかから導かれるものだ。
4時間の枠内で67,000リクエストを完了させる必要があるなら、それは持続的に毎秒約4.7リクエストということになる。レジデンシャルリクエストは直接のリクエストより遅いため、エンドツーエンドで平均2秒とする。必要な同時進行中の件数は、単純にレートとレイテンシを掛け合わせたものになる。
concurrency = requests_per_second x average_latency_seconds
= 4.7 x 2
~ 10 concurrent requests
この関係は身につけておく価値がある。なぜなら、これは2つのことを同時に説明してくれるからだ。ターゲットが遅くなるほど、同じスループットを得るためにより多くの同時実行数が必要になる。これが、静かに劣化していくターゲットが、エラーを一つも出さないままスケジュールを枯渇させ得る理由である。そして、ターゲットの側が処理を遅くしている原因である場合、同時実行数を上げてもスループットは上がらず、待機中のリクエスト数が増えるだけである。
これは逆方向にも当てはめてみるとよい。同時実行数を10に上限設定していて、レイテンシが2秒から5秒にずれた場合、スループットは毎秒5リクエストから2リクエストへと落ち、4時間のジョブが10時間のジョブになる。限界ぎりぎりではなく余裕を持たせてスケジュールを組むことが、レイテンシのずれが締め切りの未達に変わるのを防ぐ。
制約となるのは自分のマシンではなくターゲットである
ここで計画は現実と向き合うことになる。インフラが維持できる同時実行数が、実質的な上限になることはほとんどない。上限を決めるのは、ターゲットが許容できる量である。
レート制限はIPごとに、そしてますます、ターゲットごとの合計量に対して強制されるようになっている。プールを使えばIPごとの負荷は分散できるが、1つの発信元に到達する合計量は依然として可視化されるため、計画の基準にすべきなのはワーカーが送出できる量ではなく、そのサイトが受け入れる量である。ペーシングの仕組みについてはレート制限とリクエストスロットリングにまとめてあり、これに続く分散の問題、つまり自分の量にどれだけの分散が必要かについては、実際に必要なプロキシIP数で詳しく扱っている。
実務的には、これはグローバルな1つの設定ではなく、ターゲットごとの同時実行数の上限とターゲットごとのレートを計画に持たせるべきということを意味する。それぞれ控えめな同時実行数の50個のターゲットは、同じ合計量を1つのサイトに向けた場合とはまったく異なる話であり、ブロックされるのは後者だけである。
帯域幅こそが実際に購入する数値
レジデンシャルプロキシは転送データ量に基づいて課金されるため、プランのサイズはリクエスト数やアドレス数ではなく、バイト数から導かれる。
monthly_bandwidth = attempts_per_run x runs_per_month x average_bytes_per_response
支配的な変数は最後の項であり、これは完全に自分でコントロールできるものである。JSONレスポンスや軽量なHTMLページは数十キロバイトだが、画像、フォント、サードパーティのスクリプトを含む完全にレンダリングされたページは数メガバイトになる。毎日60,000リクエストの場合、50 KBのレスポンスであれば月あたり約90 GBになるが、2 MBのレンダリング済みページであれば同じ論理的なワークロードから約3.6 TBになる。これが控えめなプランとエンタープライズ向けプランの違いであり、データを取得するのかページをレンダリングするのかによって決まる。詳細はヘッドレスブラウザが必要になるタイミングと帯域幅コストの削減を参照のこと。
プランのサイズを決める前にこの最適化を行うべきである。それによってプランが1段階下がることが頻繁にあるからだ。より詳しい見積もり方法は月間帯域幅の見積もりにあり、製品レベルの選択については適切なプランの選び方にある。
スケジューリング:バーストより分散
1日あたりの量が同じであっても、実行するタイミングによって2つのジョブの挙動はまったく異なるものになりうる。
すべてを1時間の枠に圧縮すると、すべてのターゲットに対して瞬間的なレートを何倍にも増幅させることになり、これはまさに防御機構をトリガーする形である。同じ作業を利用可能な枠全体に分散させれば、ターゲットごとのレートは無償で下がり、失敗した処理を実行の終盤で山積みにするのではなく、後から再試行する余地も生まれる。
鮮度の要件が制約を決める。データが08:00時点で最新である必要があるなら、それより前に収集を終える必要があるが、それは07:00に開始せよという指示ではなく、締め切りにすぎない。スケジュールが許す限り、枠全体に分散させ、最も変動しやすいソースを早めに優先する方が明確に優れている。
コミットする前にパイロットで検証する
上記のすべての数値は、想定していた2つの変数、実際のターゲットに対してレジデンシャル出口経由での本当の平均レイテンシと、取得戦略を確定させた後の1レスポンスあたりの実際のバイト数を測定するまでは仮説にすぎない。どちらも小規模な実行で容易に測定でき、どちらもプランを大きく動かす。
意図した量の5%程度でパイロットを実行し、検証済みの成功率、レイテンシのパーセンタイル、ターゲットごとの1リクエストあたりのバイト数を記録し、そこから再計算する。答えが見積もりとは両方向にずれることを見込んでおくとよい。測定方法は速度、成功率、位置精度のテストにあり、これらと同じ数値の継続的なバージョンがプロキシKPIにおける指標である。
具体例のまとめ
要件:毎日50,000件のレコード、08:00までに準備完了、収集枠は04:00から08:00。
レコードあたりのリクエスト数1.2、これにより60,000件の成功が得られる。検証済み成功率90%で、約67,000回の試行。4時間で毎秒4.7リクエスト。平均レイテンシ2秒で、同時進行数はおよそ10であり、それを1つのターゲットに向けるのではなく、複数のターゲットに分割する。1レスポンスあたり平均80 KBで、1回の実行あたり約5.4 GB、月あたり約160 GB。同時実行数と帯域幅の両方に余裕を持たせておく。レイテンシはずれ、成功率は下がることがあるためであり、パイロットの後で再導出する。
結論
計画は逆算する:レコードからリクエストへ、リクエストから失敗分の余裕を加えた試行数へ、枠内での試行数からレートへ、レートとレイテンシから同時実行数へ、そして試行数とレスポンスサイズから帯域幅へ。同時実行数とレートは、グローバルにではなくターゲットごとに上限を設けるべきである。なぜなら、実質的な制約となるのはインフラが生成できる量ではなく、各サイトが許容する量だからである。プランのサイズを決める前に、何を取得するかを最適化すべきである。レンダリングするかデータを取得するかによって、帯域幅の答えが2桁も変わり得るからだ。作業はバーストさせるのではなく、利用可能な枠全体に分散させる。そして、パイロットを実行すること。レイテンシと1レスポンスあたりのバイト数は、プランにコミットする前に測定値へと置き換える価値のある、2つの仮定だからである。
その容量そのものはレジデンシャルプロキシから得られるものであり、そこでは同時実行数がプランのサイズを決める制約とはならず、GBあたりの料金設定により、導き出した帯域幅の数値がそのまま実際に購入する数値となる。