同時接続
負荷が小さいときは安定して動くプロキシも、ワーカーやプログラムを同時に増やすとエラーを返し始めることがあります。考えられる原因の1つが、許可された同時接続数の超過です。
これはプロキシの利用上限の1つです。何を制限し、なぜ上限に達するのかを理解するために、まずネットワーク接続とは何か、プロキシを介してどう動くかを説明します。
接続とは何か、どう動くか
ネットワーク接続は、2つのプログラムがデータを交換するために確立する通信経路です。たとえば、ブラウザーはウェブサーバーに接続し、ページを要求して内容を受け取ります。接続がその交換の経路を提供し、リクエストとレスポンスはその上で送られるメッセージです。
一般的なTCP接続を考えてみましょう。アプリケーションはサーバーのIPアドレスと、必要なサービスのポートに接続します。双方が制御メッセージを交換して接続を確立し、その後、データはパケットと呼ばれる小さな単位で移動します。TCPは配送状況を追跡し、失われたデータを再送し、正しい順序で受信側へ渡します。接続が続く間、双方は通信に関する情報を保持します。
通常のTCPプロキシでは、アプリケーションが最初にプロキシサーバーへ接続します。プロキシは接続先サイトへ別の接続を確立し、2つの接続間で双方向にデータを渡します。つまり、クライアントと接続先の両方との通信を維持します。
アプリケーションはリクエストを送り、レスポンスを受け取り、確立済みの接続で次の通信を行えます。たとえば、ページを受信しても接続が閉じるとは限らず、ブラウザーはサーバーへの追加リクエスト用に接続を残すことがあります。不要になれば一方が閉じますが、エラーやタイムアウトで終了することもあります。閉じるまでは、データを常に転送していなくても接続は存在できます。
プログラムは、ある接続でデータを受信し、別の接続で応答を待ち、さらに別の接続を後のリクエスト用に待機させるなど、複数の接続を同時に維持できます。これが同時接続です。その数は、プログラム起動以来のリクエスト総数ではなく、その時点で開いている通信経路の数を示します。
上限は何を数えるか
開いている接続は、対応する枠を1つ占有します。接続が閉じ、サービスが集計から外すと、その枠を再び利用できます。これは現在の活動への上限なので、到達しても月間の接続残高を使い切ったことにはなりません。
接続を利用者の枠にどう計上するかは、別のサービス規則です。プロキシの両側に2本のネットワーク接続があるからといって、必ず2枠を消費するわけではありません。
開いた接続は、転送データが少なくてもサーバー資源を使うため、事業者は上限を設けます。応答待ちの接続も維持する必要があります。数を管理することで、引き受けた負荷を処理する容量を確保しやすくなります。
同じサービスに、次のような別々の上限が適用される場合があります。
| 上限 | 制限するもの |
|---|---|
| 同時接続 | 同時に開いたままにできる接続数 |
| 同時リクエスト | 同時に処理中にできるリクエスト数 |
| 1秒あたりのリクエスト数 | リクエストを送信・処理できる頻度 |
| 転送速度 | 1秒あたりに移動できるデータ量 |
| 通信量の枠 | 課金期間中に転送できるデータ量 |
したがって、通信量無制限というだけでは同時接続数は分かりません。新しい接続を開く速さにも、別の上限がある場合があります。常時開いている接続が少なくても、開閉を高速に繰り返すとその上限に達することがあります。
スレッド数と接続数が一致しない理由
アプリケーションのスレッド数やワーカー数は、作業をどう構成するかを示すものであり、プロキシが数える接続数を正確には示しません。1つの作業が複数のサーバーに接続することも、非同期スクリプトが操作ごとにOSのスレッドを作らずに多数のネットワーク操作を管理することもあります。
HTTPリクエストのたびに新規接続が必要なわけでもありません。クライアントは既存の接続を再利用でき、HTTP/2は1つの接続で複数のリクエストを同時に運べます。そのため、リクエスト数と接続数は異なります。
事業者の用語も重要です。「スレッド」や「セッション」と表示された上限が、開いている接続や処理中のリクエストを指す場合があります。関連するリクエストで同じプロキシIPを保つスティッキーセッションも、必ずしも1つのネットワーク接続に対応しません。役立つのは、サービスが実際に何を数えるかという定義です。
どのプログラムが枠を共有するか
上限は、アカウント、購入したパッケージ、個々のプロキシIP、特定のゲートウェイに設定される場合があります。アカウントやパッケージの上限なら、同じ枠を使う全プログラム・端末の接続を合計します。IPリストを複数のコンピューターに分けても、それぞれに独立した枠ができるわけではありません。
IPごとの上限では配分が異なり、忙しいアドレスが上限に達しても、別のアドレスには空きが残ることがあります。より低い共有上限が併設されていなければ、一部の処理を2つ目のアドレスへ移すことで改善できます。パッケージ全体の枠と、利用者やクライアントIPごとの小さな割り当てが併存する場合もあります。
認証を許可するクライアントIPの数は、別の設定です。これはプロキシにアクセスできるネットワークを決めるもので、開ける接続数ではありません。1つのパブリックIPの背後にある複数の端末が、そのアクセス規則と、そのIPに紐づく接続枠を共有することもあります。
ウェブサイトから見えるプロキシIPを変えても、アカウント全体の接続枠はリセットされません。同様に、スティッキーセッション名やプロトコルを変えても、容量が自動的に増えるわけではありません。上限は、事業者が計数に使うアカウント、パッケージ、エンドポイントに紐づいたままです。
接続がたまる理由
既存の接続が閉じるより速く新規接続が開くと、接続がたまります。ページの読み込み、ファイルのダウンロード、ほかのネットワーク処理の並列実行でも起こります。一部の接続がまだ転送中や応答待ちの間に、アプリケーションが追加接続を開くためです。それらが同時に枠を使い、合計でプロキシの接続数上限を使い切ることがあります。
応答が遅いと接続の占有時間が延びます。プログラムが同じペースで新しい処理を起動し続けると、未完了の作業がたまります。一方、並列動作の量を一定に保つなら、サイトが遅くなるほど通常は1分あたりの完了数が減ります。どちらも、プロキシのパッケージが変わらなくても起こります。
長いダウンロードや、タイムアウトを待つ接続も同様です。したがって、多数の接続が開いていても、転送速度は低い場合があります。データを動かすより、待っている時間が長いためです。
リクエストの合間に意図的に開いたままにする接続もあります。通常、keep-aliveと呼びます。毎回の新規接続を省けますが、開いている接続をサービスが数えるなら、待機中も枠を占有する場合があります。アプリケーションのプールに戻った接続は再利用可能になったのであって、プロキシ側でも閉じられたとは限りません。
別の問題として、接続の後処理の不備があります。自作スクリプトだけでなく、市販・既製のソフトウェアでも起こります。たとえば、レスポンスを読み始めてエラーが起き、前のレスポンスを読み終えるか閉じるかせずに、次のリクエストを始める場合です。古い接続が占有されたまま新規接続を開き続けると、有用な処理を増やさずに枠を使い切ります。成功時だけでなく、エラーやキャンセル後の後処理も確認する必要があります。
正しい後処理により、クライアントは適切な接続を再利用し、不要な接続を閉じられます。タイムアウトは、放棄された操作が無期限に待つのを防ぎます。再利用を全面的に無効化するのは一般的な解決策ではありません。接続確立の作業が増え、新規接続の発生頻度も上がる可能性があります。目標は再利用できる接続数を管理し、不要なものを正しく解放または閉じることです。
動いたり止まったりするように見える理由
負荷がかかると断続的に失敗する場合は、早い段階で接続数の上限を確認してください。一部のプロキシアドレスは動くのに別のものは失敗し、少し後にはその組み合わせが変わることがあります。アプリケーションからは、リスト内の異なる部分が次々にオフラインになるように見えます。
考えられる説明の1つは、共有枠が埋まっていることです。既存の接続は続いても、追加接続は拒否されたり待たされたりします。先に開いた接続が閉じると一部の新しい試行が通り、再び枠が埋まるとほかの試行が失敗します。結果が変わるのは、壊れたIPの固定グループがあるためではなく、同じ枠を取り合うためです。
この動作がスロットリングと呼ばれることもあります。ここで制限されるのは新規接続の受け入れであり、確立済みの接続すべての速度が下がるとは限りません。具体的な応答はサービス次第で、明確な上限メッセージ、接続拒否、クライアント側のタイムアウトなどがあります。待機キューが用意されるとは限りません。
この説明を確かめるには、失敗と接続数を比較し、枠を共有するプログラム全体の並列動作を一時的に減らします。上限以下になると失敗が止まり、埋まると再発するなら、接続数上限が有力な原因です。ただし、接続先サイトやネットワークも似た中断を起こします。タイムアウトやHTTP 429、502、503だけで、プロキシの接続数上限に達したと断定はできません。エラーの発生元と文面が重要です。
上限内で有用な処理を進める方法
ソフトウェアが実際に必要とするサイトと操作から始めてください。並列動作を徐々に増やし、成功結果、応答時間、接続数のピークを観察します。速いページへの短いテストでは、ログイン、大きなレスポンス、遅いエンドポイントを含む全体の実行を代表できない場合があります。
- 全プログラムで共通の接続予算を設定します。ほかの動作や短いピークのために余裕を残してください。同じパッケージを複数のプロセスが使う場合、それぞれにパッケージ全体の枠を設定すると、同時実行時に過負荷になることがあります。
- 作業数と接続数の両方を管理します。接続プールは再利用のために接続を保持します。サイズ設定が厳密な上限なのか、処理後に保持する数だけなのかを確認してください。待機モードを有効にしないと追加接続を開くクライアントもあります。失敗時も含め、レスポンスの後処理とタイムアウトを維持します。
- 起動と再試行の時刻を分散します。全ブラウザーを一斉に起動したり、失敗を即座にすべて再試行したりすると、新たなピークになります。再試行は回数を制限し、待ち時間を徐々に長くして、同じ負荷予算に含めてください。タイムアウトしても送信した操作の失敗が証明されたわけではないため、購入や更新の再実行には注意が必要です。
- 完了した処理を測定します。ワーカーを増やす価値があるのは、成功する処理量が増える間だけです。待ちやエラーばかり増えるなら、設定を下げた方が同じ作業を早く終えられる場合があります。ダッシュボードが時間平均を表示する場合、短いピークはアプリケーションのエラー時刻ほど明確に見えないことがあります。
ブラウザーの作業では、不要なダウンロードを避けることでネットワーク動作を減らせます。画像や動画が不要な作業ならブロックが役立つ場合がありますが、スクリプトを止めると操作自体が壊れることもあります。目的の作業が正しく完了するかで判断してください。
上限の引き上げが役立つ場合
接続を正しく管理していても、必要な負荷が継続的に事業者の上限に達するなら、接続容量の追加が役立ちます。小さな共通枠を奪い合わずに、より多くの作業を同時実行できるようになります。
購入によって、実際に達している上限が増える必要があります。IPごとの制限なら、追加IPへ処理を分散すると改善する場合があります。パッケージの共有上限なら、新しいパッケージや追加オプションがその共有枠を引き上げなければなりません。IP数が増えるだけでは、接続枠も増えるとは分かりません。
ほかの上限もあります。クライアントのプールが小さい、コンピューターのネットワーク資源が不足する、接続先がリクエストを制限するといった場合です。1本のモバイル回線にも、許可されたプロキシ接続数とは別に利用可能な帯域幅があります。同時接続枠を買い足しても、これらの制約はなくならず、接続リークを続けるスクリプトも直りません。
実用上の目標は、失敗を少なく保ちながら、通常のピークを処理できる余裕を確保することです。それを確認した後なら、追加の接続枠は、アプリケーションの修正を先延ばしにする手段ではなく、有用な容量増強になります。
