24時間で420万のrequest。平均response:774ミリ秒。成功率:99.91%。再構築前の7日間の同じワークロードでは、平均2.5秒でした。これは、同じハードウェア、同じターゲットサイト、同じproxyプールにおいて、平均response時間が70%低下したことを意味します。私たちは、知らず知らずのうちに顧客の夜の時間を奪っていたrequestパスの部分を再構築しました。
これは、何が変更されたのか、実際の数値がどのようになっているのか、およびなぜSingleとProxy Finderが異なるのかについてのレポートです。
まずデータについてお断りしておきます。この投稿の数値は本番トラフィックのものであり、特定のターゲットホスト1つを除外しています。そのホストは今週、活発にrate limitを適用し、requestにチャレンジを課しており、すべての指標を歪めています。それを含めると、成功率は約95%に低下します。しかし、その5%のギャップは私たちのインフラストラクチャの障害ではありません。私たちのピッカーがどれほど優れていようとも、1つのサイトがrequestを拒否しているためです。システムが協調的なターゲットに対して実際にどのような動作をするかを確認できるように、これを除外しました。
データが示すもの
過去1週間の本番トラフィックにおける日次平均は以下の通りです。

4月22日から4月27日:平均2,318ミリ秒〜3,116ミリ秒、トラフィックは1日あたり280万〜770万request。4月25日は770万requestで3,116ミリ秒と際立っていますが、これは土曜日のピークです(週末のボリュームは著しく増加し、平均を押し上げます)。4月28日:380万requestで672ミリ秒。4月29日(一部の日、UTC 09:00まで):これまでに170万requestで880ミリ秒。
同じアーキテクチャ。同じproxy。同じターゲットサイト。異なるrequestパス。
パーセンタイルの状況は平均よりも明確です。平均値は最悪のテールを隠すことができますが、パーセンタイルは隠せません。

このチャートは、再構築後の24時間と再構築前の24時間を比較したものです。p50はほとんど動いていません(4%上昇していますが、これは正直なデータです。高速パスはすでに良好であり、新しいピッカーはテールでの大幅な節約のために、事前処理に少しだけ多くの労力を費やしています)。この期間で平均は48%低下しました。p95は8.5秒から3.9秒へと54%削減されました。p99は20秒から7.8秒へと61%削減されました。ここが痛みの原因であり、スクレイパーが最も遅い5% of requestの返信を待っているときに実際に感じる遅さです。再構築前の7日間(平均が約2.5秒で推移していた期間)と比較すると、本日の平均774ミリ秒は70%の低下となります。
成功率も向上しました。同じ期間で98.85%から99.91%に上昇しました。特にProxy Finderでは、成功率が99.89%に達しました。Singleでは99.96%でした。これは私たちが最も誇りに思っている数字です。なぜなら、リトライすることなく、最初の試行でどれだけ頻繁に有用なデータを返せているかを示しているからです。
2つの製品、2つのレイテンシプロファイル
私たちはSingleとProxy Finderを比較しません。これらは異なる課題を解決し、異なるレイテンシバジェットを持っています。一方を使用しながら他方の数値を見ているなら、見るべきスコアボードを間違えています。

Singleは、私たちのインフラストラクチャを経由するワンショットのHTTP requestです。URLを指定すると、実際の運用コールの約99%において、すでに動作することがわかっているproxy idが使用されます。私たちはそのproxyを経由してURLを取得し、ユーザーはresponseを受け取ります。ローテーションロジック、リトライの連鎖、proxyの頻繁な入れ替えはありません。過去24時間:p50は100ミリ秒、p95は371ミリ秒、p99は581ミリ秒。ほとんどのコールは5分の1秒未満で完了します。最も悪い1%であっても、600ミリ秒未満で戻ってきます。
Proxy Finderは検出レイヤーです。公開proxyのプール全体でrequestをローテーションし、各候補を検証し、失敗した場合はリトライし、実際に動作した最初のresponseと、それを実行したproxyのidを返します。p50は445ミリ秒、p95は5.4秒、p99は10.2秒。遅いのは、そうである必要があるからです。重要なのは、スクレイパーがターゲットサイトにアクセスするIPがローテーションされ、使い捨て可能であるということです。ブロックリストやrate limitに対する耐性を得るために、数秒のオーバーヘッドをトレードオフにしています。
Singleがこれほど高速なのは魔法ではありません。Singleは、Proxy Finderが検出する必要があった情報を信頼しているからです。Proxy Finderを一度呼び出して「このproxyが動作しました、idはこれです」と返されると、Singleを介した同じターゲットに対するその後のフェッチでは、検出ステップ全体がスキップされます。すでに検証に合格したproxyに直接アクセスします。
チームがこれらを組み合わせて使用する方法
ターゲットに頻繁にアクセスするほとんどのチームは、2ステップのパターンに従います。最初のコールは探索的であり、残りは確定的なものです。
最初のコールはProxy Finderに送られます。プール内をローテーションし、承認ルールに照らして各候補を検証し、動作したproxyのidとともにresponseを返します。そのidは、同じターゲットにアクセスする今後のすべてのコールのハンドルになります。
それ以降のすべてのコールは、proxy idを付加してSingleに送られます。検出、検証、リトライの連鎖はありません。指定されたproxyを経由してrequestをルーティングし、responseをストリーミングで返します。これが、p50で100ミリ秒を達成するパスです。
昨日動作していたproxyが今日ブロックされた場合、Proxy Finderにフォールバックして1回コールして再検出し、新しいidでSingleのフェッチを再開します。私たちは古くなった情報を誤魔化しません。渡されたproxy idが機能していない場合、ローテーションできるように迅速に通知します。
99対1の比率(ボリュームの大部分を占めるSingleと、検出を担うProxy Finder)が、Singleの数値がこのようになっている理由です。Singleが本質的に高速な製品であるからではありません。Singleが定常状態であり、Proxy Finderがキャリブレーションステップだからです。ほとんどのワークロードは、大半が定常状態です。
タスクが「呼び出し元を気にしないクリーンなパブリックAPIからこのJSONを取得する」ことである場合は、proxyを完全にスキップしてSingleを単独で使用してください。タスクが「フラグを立てられることなく、使い捨てIPのプールからこの保護されたページにアクセスする」ことである場合は、これらを組み合わせてください。これらは代替手段ではありません。同じワークフローの段階です。
変更した内容
成果の大部分は、proxyローテーションパスにおける3つの要素を再構築したことによるものです。いずれも新しいアイデアではありません。単に私たちが後回しにしていたことでした。
プールが不正なデータを信頼するのをやめました。 再構築前、proxyディレクトリはエントリを必要以上に長く保持していました。それらのエントリの一部はすでに到達不可能でした。それらを選択すると、到達不能であることを痛感するまでに15〜30秒を費やすことになります。私たちは、プールが実際に稼働しているものをほぼリアルタイムで反映し、ピッカーが最近成功した実績のあるIPを優先するモデルに移行しました。
稼働の有無だけでなく、proxyごとの品質スコアを導入しました。 以前は、最終的に成功する限り、responseに5秒かかるproxyも300ミリ秒かかるものと同じように扱われていました。現在、ピッカーはレイテンシも追跡します。動作はするが遅いproxyはキューの下位に押し下げられます。高速なものは、アクティブなうちに再利用されます。これは思った以上に重要です。なぜなら、レイテンシ分布のロングテールは、古いピッカーが選択し続けていた「動作はするが遅いproxy」が大部分を占めていたからです。
ターゲットごとの品質スコア。 あるドメインで信頼できるproxyが、別のドメインでは不安定になることがあります。あるサイトに対してクリーンに動作するIPが、別のサイトではブロックされたりrate limitをかけられたりします。私たちのピッカーは、グローバルだけでなく、ターゲットホストごとに成功率とレイテンシを追跡するようになりました。特定のドメインに対するフェッチを要求された場合、最近そのドメインで実際に良好なパフォーマンスを示したproxyから選択します。グローバルに優れたproxyも候補に残りますが、特定のターゲットで強力な実績を持つproxyが、全体的に強力な実績を持つものよりも優先されます。
よりスマートなリトライのエスカレーション。 requestが失敗したとき、以前はすぐに並行して試行を展開していました。これは無駄であり、さらに悪いことに、1つの不良なproxyが次々と失敗する後続処理の連鎖を引き起こす可能性がありました。現在、リトライは試行間の短いバックオフを伴って順次エスカレートするため、失敗は失敗、リトライはリトライであり、増幅器にはなりません。
ユーザーからは見えにくいものの、言及する価値のある2つ目の変更カテゴリがあります。
再起動への耐性。 以前は、requestインフラストラクチャを再デプロイすると、proxy品質スコアマップをゼロから再構築する必要がある5〜15分のウィンドウが発生していました。そのウィンドウの間、ピッカーは本質的に推測を行っていました。顧客には、デプロイ直後のレイテンシスパイクとして見えていました。現在、この品質マップは再起動をまたいで永続化されます。システムはウォーム状態で起動します。本日より、レイテンシスパイクを引き起こすことなく、日中にインフラストラクチャの変更をデプロイできるようになりました。今朝実施した再起動テストでは、15秒の接続の瞬断が発生したのみで、その後の回復時間はゼロでした。これは、デプロイ頻度における地味ながらも重要な変化です。ユーザーのトラフィックに合わせて再デプロイのスケジュールを組む必要はもうありません。
より明確な障害シグナル。 私たちのインフラストラクチャ内部で問題が発生した場合、ユーザーのリトライロジックは、対処すべき適切なHTTPステータスコードを受け取るようになりました。一時的に利用できないバックエンドは503を返します。不正な形式のJSONを返したバックエンドは502を返します。純粋な内部エラーは500を返します。以前は、これら3つすべてが500のように見えていたため、リトライロジックは「待機して再試行」と「破損しているためエスカレーション」を区別できませんでした。現在は区別できます。
ユーザーにとっての意味
ローテーションされたproxyに対してスクレイパーを実行している場合、実質的な変化として、p95とp99がそれぞれ1週間前からほぼ半分に削減されます。平均request時間は低下します。動作はするが遅いproxyによるリトライが減少します。1,000requestのジョブが20分ではなく1時間かかる原因となるテールレイテンシも、それに伴って低下します。
Singleを実行している場合、ピッカーの成果は主にテールで実感できます。p99が600ミリ秒未満に低下したため、不運な1%のrequestであっても迅速に戻るようになりました。Singleはすでに高速でしたが、一貫性が備わりました。
正直な制限事項
すべてを解決したわけではありません。現在も適用されるいくつかの具体的な制限事項は以下の通りです。
Proxy Finderのp99は依然として約10秒です。 半分に削減したものの、ロングテールは現実に存在します。その一部は私たちの責任(プールの深さ、稀なターゲットにおけるピッカーのノイズ)です。しかし、多くはそうではありません。ターゲットサイト自体が遅い、特定のルートにrate limitを適用している、検査に時間のかかるチャレンジページを表示している、あるいは単にタイムアウトしている可能性があります。私たちのインフラストラクチャは利用可能な最良のIPを選択できますが、応答するかどうかを判断しているターゲットサーバーを高速化することはできません。すべてのrequestが5秒未満で戻ることに依存するジョブの場合は、許容範囲に合わせたrequestごとのタイムアウトを設定し、リトライレイヤーを信頼してください。
一部のターゲットは敵対的であり、それは数値に現れます。 冒頭で述べたように、99.91%の成功率には、今週活発にチャレンジを課してきている1つのホストを除外しています。それを含めると、成功率は約95%に低下します。そのホストは特異なものではありません。公開ウェブデータを扱うアグリゲーターであれば、誰もがこれを目にします。ターゲットは週ごとに変化します。ピッカーの再構築により、システムは敵対的なターゲットを回避してルーティングする能力が大幅に向上しましたが、トラフィックを完全に拒否すると決定したサイトを覆すことはできません。私たちの仕事は、協調的なケースにおいて可能な限りクリーンなデータを提供し、敵対的なケースにおいては迅速に失敗させることです。
同日比較にはノイズが含まれます。 パーセンタイルチャートに示されている24時間のウィンドウは、昨日と一昨日を比較したものです。曜日による影響、ターゲットサイトの変動、プールの構成はすべて、任意の2つのウィンドウ間で変化します。方向性には自信を持っていますが(7日間のチャートは4月28日に明確な変曲点を示しています)、ご自身のワークロードでベンチマークを行う場合は、少なくとも1週間にわたって比較を実行してください。
今後の展望
ピッカーの書き換えは基盤にすぎません。その後に控えているいくつかの計画は以下の通りです。
インスタンス間で共有される品質スコアマップ。これにより、独立したマップを構築するのではなく、相互に学習できるようになります。現在は、各インスタンスがどのproxyが優れているかについて独自の全体像を持っています。これは機能しますが、無駄です。すべてのインスタンスが並行して同じ学習コストを支払っています。
信頼度に基づく選択。推測しているものではなく、過去数分間に実際にテストしたproxyを優先します。トラフィック自体がピッカーをウォーム状態に保つのに十分でない、低ボリュームの顧客に有用です。
そして長期的な展望:より多くの決定をピッカーに委ねることで、ターゲットごとの品質スコアを多くのシグナル(ターゲットのレイテンシプロファイル、時間帯のパターン、プールセグメントの健全性)の1つにします。ホットパスを遅くすることなくこれを実行するためのインフラストラクチャが、現在存在しています。
最もコストのかからないrequestは、リトライする必要のなかったものです。ピッカーの再構築は、選択する瞬間のより優れたデータが、事後のより多くの試行に勝るという賭けです。最初の24時間の証拠は、それが正しい賭けであることを示しています。