AI API で使う VPN の選び方は、「Web ページが開けるかどうか」とは別の基準です。Web なら切断されても再読み込みで済みますが、API 呼び出しの切断はビルドの失敗、ストリーミング出力の再生成、原因の分からない CI のエラーにつながります。
本記事はコマンドライン、IDE プラグイン、CI の 3 つのシーンを対象に、まず API 呼び出しがネットワークに求める 4 つの要件を整理し、次に直結・中継・専用線を比較、続いてプロトコル、振り分け、DNS、タイムアウト設定に落とし込み、最後に再現できる自己検証の手順を示します。絶対的な速度の約束は書きません。同じ回線でも都市、キャリア、時間帯によって挙動は大きく変わるため、実用的な結論は自分の環境での再測定から得るべきです。
API 呼び出しとWeb 閲覧の 4 つの違い
API トラフィックと Web 閲覧を同じルールに押し込むことが、多くの問題の出発点になります。両者のネットワーク特性は少なくとも次の 4 点で異なります。
接続の形:短い接続が多く、長い接続は少ない
Web は 1 回の読み込みで数十のリクエストを送り、その後は長時間アイドルになります。API クライアントは逆で、1 つのタスクで数十から数百のリクエストを並行して送り、それぞれが独立して接続を張ります。ストリーミング応答では 1 本の接続が数十秒から数分続きます。回線はこの 2 つを同時に支える必要があります。並行した接続の確立と、長い接続が途中で切られないことです。
出口 IP:固定が必要
サーバー側は IP 単位でホワイトリスト、レート制限、リスク判定を行うことがあります。同じキーが短時間に 2 つの地域からリクエストを送ると、サーバー側のログには出所の異なる 2 件の記録として残ります。クライアント側の自動選択(url-test、fallback)はノードの揺らぎで出口を黙って切り替えるため、API 利用で最も多い失敗要因の 1 つです。
タイムアウト:許容度が低い
ストリーミング応答では、途中で新しいデータが長時間届かないことがあります。長い思考や長い生成の間隔では特に顕著です。プロキシのアイドルタイムアウトや NAT セッションのタイムアウトは、この間に接続を回収してしまいます。Web なら再読み込みで済みますが、SDK は例外を投げ、リトライは呼び出し全体のやり直しを意味します。
可観測性:ログを突き合わせられること
問題を切り分けるとき、開発者はクライアントのログとサーバー側の記録を 1 件ずつ突き合わせる必要があります。出口が固定され、時刻が特定できて初めてこれが成り立ちます。出口が変動していれば、ログの送信元 IP はいつまでも一致せず、問題がコードにあるのか、回線にあるのか、上流サービスにあるのかも判断できません。
回線タイプの比較:直結、中継、専用線
3 つの経路の違いは、突き詰めれば「ローカルから海外データセンターまでの間、誰のネットワークを通るか」です。以下では API 利用で本当に重要な観点から定性的に比較します。
| 比較項目 | 直結 | 中継 | IEPL 専用線 |
|---|---|---|---|
| 経路 | クライアント → 海外ノード、全区間が公衆網 | クライアント → 中国本土の中継入口 → 海外ノード | クライアント → 専用線入口 → 海外ノード、専用チャネル経由 |
| 夜間ピーク時の挙動 | 国際回線の混雑の影響を受け、揺らぎが大きい | 直結より安定。中継入口の品質に依存 | 揺らぎが最小。公衆網の混雑の影響をほぼ受けない |
| 出口 IP | 固定できる | 固定できる | 固定できる |
| 遅延の特性 | 物理距離と強く相関する | 1 ホップ増えるため、通常はやや大きい | 安定しており、変動が小さい |
| 並行処理の許容量 | 公衆網の品質に左右される | 良好 | 最も良い |
| 向いている用途 | デバッグ、低頻度の呼び出し | 日常的な開発、中程度の並行数 | 長い接続のストリーミング、高並行、本番環境 |
| コスト | 低 | 中 | 高 |
API 利用では、ピーク帯域よりもまず揺らぎを見るべきです。1 回のリクエストの所要時間は接続確立、初回バイト待ち、転送の 3 段階で構成され、前の 2 段は往復遅延と揺らぎで決まります。帯域がボトルネックになり得るのは、長いテキストをストリーミング出力するときだけです。夜間ピークには公衆網の直結で揺らぎが増幅され、「昼は問題ないのに夜はタイムアウトする」というよくある原因になります。
結論:本番環境の API 呼び出しでは、出口を固定できる専用線と品質の高い中継を優先します。直結はデバッグと低頻度の呼び出し向けです。第一の指標は帯域ではなく、出口の安定性と揺らぎです。
プロトコルが API トラフィックに与える影響
プロトコルは接続の確立方法と、パケットロス後の待ち方を決めます。API 呼び出しで実際に差が出るのは、搬送方式(TCP か UDP か)と多重化のオン・オフです。次の表では開発者によく使われるプロトコルごとの違いを整理します。
| プロトコル | 搬送方式 | 特徴 | API 利用での意味 |
|---|---|---|---|
| Shadowsocks | TCP / UDP | AEAD 暗号化、実装が軽量 | ハンドシェイクの負荷が小さく、短い接続の並行処理に有利。UDP 転送はサーバー側で有効かどうかに依存 |
| VMess | TCP | V2Ray 系の定番プロトコルで、対応範囲が広い | 互換性が高い。多重化を有効にすると、1 回のパケットロスが同じ接続上のすべてのリクエストを止める |
| VLESS | 通常は TLS 経由 | プロトコルヘッダがより軽量で、内蔵の暗号化は行わない | オーバーヘッドが小さく、TLS との組み合わせに適する |
| Trojan | TLS | 通信の見た目が通常の HTTPS に近い | ネットワーク環境が TLS に寛容な場合は安定 |
| Hysteria2 | QUIC(UDP) | 輻輳制御を内蔵 | ロスの多い回線では再送の待ちが短い。UDP を制限するネットワークもあり、フォールバックが必要 |
| TUIC | QUIC(UDP) | 多重化、0-RTT | 短い接続のハンドシェイクコストが低い。同じく UDP の可用性に依存 |
選び方の順序はこうです。まずローカルネットワークが UDP に寛容か確認します。UDP が使えるなら、QUIC 系プロトコルはロスのある回線で待ち時間を抑えられます。UDP が制限されている、あるいは実行環境が対応していない場合は、TLS 上の TCP プロトコルに戻せば十分です。プロトコル自体に絶対的な優劣はなく、違いはどのような回線で使うかにあります。
多重化はデフォルトで有効にすべき設定ではない
複数の接続を 1 本の TCP にまとめ、ハンドシェイクを節約する代わりにヘッドオブラインブロッキングを抱え込みます。API 呼び出しは短いリクエストが大半で、1 本の TCP が詰まると同じ接続上の数十のリクエストがまとめてタイムアウトします。並行処理では、接続を複数張るほうが安全です。
固定出口の実現方法:振り分けと出口の紐付け
固定出口はクライアントのスイッチ 1 つではなく、ドメインのグループ分け、グループ種別、DNS の経路という 3 つの設定が揃って初めて成立します。以下は構成の一例です。ノード名はお使いのクライアントに実際に表示される名称に合わせてください。
# 構成の一例。ノード名とポートはクライアントの表示に合わせてください
proxy-groups:
- name: AI-API
type: select # url-test / fallback は使わない
proxies:
- IEPL-01
- RELAY-01
rules:
- DOMAIN-SUFFIX,api.openai.com,AI-API
- DOMAIN-SUFFIX,api.anthropic.com,AI-API
- DOMAIN-KEYWORD,openai,AI-API
- GEOIP,CN,DIRECT
- MATCH,DIRECT
使用中のサービスのドメインを 1 つずつルールに追加し、MATCH の 1 行だけで済ませないようにします。ルールは上から順に照合されるため、具体的なドメインほど前に置き、MATCH は常に最後にします。同じマシンで手動デバッグとバッチ処理を併用する場合は、自動化タスク用に別の出口ノードを用意し、2 種類のトラフィックが互いに影響しないようにするのがおすすめです。
見落としやすい 2 つ目のポイントは DNS です。名前解決がローカルキャリアの DNS を通る場合、返る IP が出口の地域と一致しないことがあります。ハンドシェイクが余分に遠回りし、サーバー側から見た地域のシグナルも矛盾しかねません。対策は、DNS をクライアント内のリモート解決(fake-ip モードとリモート DNS の組み合わせなど)に任せ、クエリがシステムから直接送信されずプロキシ経由になっていることをログで確認することです。
- ✅ API のドメインを個別にグループ化し、グループ種別は select で 1 つのノードに固定
- ✅ 出口ノードを決めたら、少なくとも丸 1 営業日は観察し、タスクの途中で切り替えない
- ✅ DNS はクライアントのリモート解決に任せ、解決の経路が出口と一致することを確認する
- ✅ ルールには使用中のサービスのドメインを 1 つずつ列挙し、MATCH はフォールバック専用にする
- ❌ API のドメインを url-test / fallback グループに入れ、クライアントに出口を自動で切り替えさせる
- ❌ セッションの途中で手動でノードを切り替え、前後のログをサーバー側の記録と突き合わせる
- ❌ システム DNS に頼り、解決がプロキシ経由かどうかを一度も確認しない
コマンドライン、IDE、CI のプロキシ設定
クライアントは通常 2 つの方式でトラフィックを扱います。システムプロキシ(環境変数とシステム設定を利用)と TUN(仮想 NIC による全体の引き継ぎ)です。コマンドラインで最も問題になりやすいのは、プログラムが環境変数をまったく読まず、プロキシを通ったつもりが実際は直結していた、というケースです。
# セッション単位:現在のシェルとその子プロセスだけに影響
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5://127.0.0.1:7891
export NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,192.168.0.0/16
これらの変数の読み取り方は実行環境によって異なります。よくあるケースを以下に整理します。
| 実行環境 | 環境変数をデフォルトで読むか | 追加で必要な設定 |
|---|---|---|
| curl / wget | 読む | -x オプションで 1 回のリクエストだけプロキシを指定することもできる |
| Go(net/http) | HTTP_PROXY / HTTPS_PROXY / NO_PROXY を読む | 追加設定は不要 |
| Python(requests / httpx) | デフォルトで読む | proxies パラメータを明示すると環境変数より優先される |
| Node.js(fetch / undici) | デフォルトでは読まない | グローバル dispatcher を設定するか、環境変数に対応したパラメータを使う |
| Docker daemon | シェルの環境変数は読まない | daemon の設定または ~/.docker/config.json で個別に設定する |
| systemd サービス | シェルの環境変数を継承しない | Environment= または EnvironmentFile= で明示的に渡す |
| git | 読む | git config http.proxy で設定に固定することもできる |
CI はまた別の事情があります。ホスト型 runner の出口はプラットフォーム側が決めるため、ローカルのプロキシ設定は持ち込めません。呼び出すサービスが IP ホワイトリストを採用している場合は、セルフホスト runner を用意して固定回線を通す必要があります。workflow ではこれらの変数を明示的に export してください。各 job のシェルは新しく起動し、手元のターミナルの設定を継承しないためです。
サブスクリプションリンクは認証情報として管理する
サブスクリプションリンクはアカウントの認証情報と同じです。コードリポジトリにコミットしたり、issue やスクリーンショットに貼ったりしないでください。CI では secret で注入し、ローテーション後は速やかに更新します。また、TUN モードはすべてのトラフィックを引き継ぐため、有効にする前に社内ネットワークのセグメント、Docker ブリッジ、LAN 上のデバイスをバイパスリストに入れてください。そうしないとローカルサービス間の通信まで遠回りします。
並行接続とストリーミング応答のタイムアウト設定
- 接続の再利用:接続プールを再利用するとハンドシェイクを大幅に削減できます。Python の Session / Client、Node の Agent はいずれもデフォルトで再利用します。同時に並行数の上限も設け、ローカルのポートと回線の接続数を埋め尽くさないようにします。
- 短い接続の並行処理:並行数に 1 回あたりの接続確立コストを掛けたものが総待ち時間になります。低遅延・低揺らぎの回線のほうが、大帯域よりもこの数値を縮められます。
- ストリーミング応答:初回バイト待ちと総時間を分けて設定します。読み取りタイムアウトは平均の出力速度から見積もるのではなく、「最長の無出力間隔」より大きくします。
- keepalive:TCP keepalive を有効にし、中間機器がアイドル接続を回収する確率を下げます。
- HTTP/2:単一接続の多重化はハンドシェイクを節約できますが、1 本の接続でのパケットロスはすべてのストリームに影響します。並行数が非常に多い場合は、接続を複数張るほうが安定します。
- リトライ:指数バックオフを使い、まずリクエストが冪等かどうかを判断します。ストリーミングの途中で切れた場合のリトライは、呼び出し全体のやり直しと同じです。
ある回線の並行処理下での実力を見たいなら、curl の分割計測で十分です。
curl -o /dev/null -s \
-x http://127.0.0.1:7890 \
-w "dns %{time_namelookup}s | connect %{time_connect}s | tls %{time_appconnect}s | ttfb %{time_starttransfer}s | total %{time_total}s\n" \
https://api.example.com/health
出力で最も見るべきは ttfb の平均値ではなく、ばらつきの幅です。平均が良くてもばらつきが大きい回線は、夜間ピークやパケットロスの時間帯に耐えられません。ストリーミングでは、最長の無データ間隔も別途記録します。
クライアントごとの違い:デスクトップ、モバイル、コマンドライン
同じアカウントで複数のプラットフォームを使うなら、同じ出口戦略を使います。まず各端末の違いを把握してから設定しましょう。
- デスクトップ(Windows / macOS):クライアントは通常、システムプロキシと TUN の両方を提供します。システムプロキシは各プログラムが自発的に対応する必要があり、IDE プラグインや CLI では漏れることがあります。TUN は全体を引き継ぎますが管理者権限が必要で、Docker ブリッジ、仮想マシン、LAN アクセスに影響することがあるため、バイパス設定が要ります。
- モバイル(iOS / Android):検証や一時的な切り分けに向いています。OS はバックグラウンドの長い接続を制限するため、長時間のタスクはモバイルで動かさないようにします。
- サーバーとコマンドライン(Linux):常駐サービスとして動かし、設定変更後はホットリロードします。systemd の環境変数と起動順序に注意してください。
- サブスクリプションの読み込み:VPNAY はサブスクリプションリンクを提供しており、読み込むとクライアントがノードとルールを自動生成します。プロトコル対応はクライアントごとに異なり、QUIC 系プロトコルには新しいカーネルが必要です。読み込み後は対象プロトコルが使えることを確認してから、API のグループをそこに向けてください。
- プラットフォームとデバイス:Windows / macOS / iOS / Android / Linux で同じアカウントが使え、デバイス数の制限はありません。開発機、テスト機、CI マシンで 1 つの出口戦略を共有できます。
自己検証の方法:出口と安定性をどう確かめるか
他人の速度測定のスクリーンショットを見るより、次の 6 ステップで自分のネットワークで測ってみてください。特別なツールは不要で、curl と並行実行のコマンドがあれば十分です。
- 出口 IP の確認:出口確認用の API に 3 回続けてリクエストし、3 回の結果が一致するか見ます。同じノードなら数分間は変わらないはずです。
- 解決経路の確認:クライアントのログで API ドメインの DNS クエリを探し、システム DNS から直接送信されず、プロキシ経由になっていることを確認します。
- 分割計測:curl の -w オプションで dns、connect、tls、ttfb、total の 5 段階の所要時間を出力し、ttfb のばらつきに注目します。
- ストリーミング接続の計測:curl -N で長い出力を取得し、最長の無データ間隔と、接続が途中で切れないかを記録します。
- 並行処理の計測:xargs -P や負荷試験ツールで数十のリクエストを並行実行し、平均値だけでなく失敗率とテール側の所要時間を見ます。
- 時間帯を変えた再測定:少なくとも業務時間帯と夜間ピークに 1 回ずつ測り、2 つの結果を並べて見ます。
# 並行実行の例:30 件のリクエストを同時に送り、ステータスコードと合計時間だけを見る
seq 30 | xargs -P 30 -I{} curl -s -o /dev/null \
-x http://127.0.0.1:7890 \
-w "%{http_code} %{time_total}s\n" https://api.example.com/health
2 回の再測定の ttfb のばらつきと失敗率を並べて比べれば、その回線が「十分」か「限界」か判断できます。回線を変える必要があるときは、タイムアウト値を何度も大きくするのではなく、出口の地域や回線タイプを変えるほうが有効です。タイムアウト値は問題を先送りするだけです。
よくある質問
API 呼び出しはすべてのリクエストをプロキシ経由にする必要がありますか?
いいえ。ドメイン単位の振り分けで十分です。使用中のサービスのドメインだけを固定出口に向け、それ以外は直結にします。回線の負荷を減らせるうえ、ローカルサービス、パッケージマネージャー、社内ネットワークへのアクセスが遠回りするのを避けられます。
なぜ昼は問題なく、夜間ピークにタイムアウトが増えるのですか?
公衆網の直結では揺らぎが夜間ピークに増幅され、ttfb のばらつきが大きくなり、長い接続が途中で回収されます。中継や専用線に切り替え、API のドメインを単一ノードに固定すると、多くの場合で明確に改善します。あわせて読み取りタイムアウトを平均値ではなく最長の無出力間隔を基準に設定してください。
複数のサービスで 1 つの出口を共有できますか?
できます。1 つの固定出口を共有する利点は、ログの出所が統一され、切り分けがしやすくなることです。特定のサービスが送信元地域に個別の要件を持つ場合は、そのサービス専用のグループとノードを用意し、同じグループ内で混在させないようにします。
CI でホスト型 runner をそのまま使えますか?
リクエスト自体は通りますが、出口はプラットフォーム側が決めるため固定できず、ローカルのプロキシ設定も持ち込めません。上流サービスが IP ホワイトリストを採用している場合は、セルフホスト runner を用意して固定回線を通す必要があります。そうでなければ、プロキシのパラメータを secret で注入し、出口が固定されない前提を受け入れてください。
設定チェックリスト
- ✅ API のドメインを個別にグループ化し、グループ種別は select で 1 つのノードに固定
- ✅ ルールに使用中のサービスのドメインを 1 つずつ列挙し、MATCH はフォールバック専用にする
- ✅ DNS はクライアントのリモート解決を使い、出口の地域と一致させる
- ✅ 読み取りタイムアウトは最長の無出力間隔を基準にし、初回バイト待ちは別に設定する
- ✅ サブスクリプションリンクは認証情報として管理し、リポジトリやスクリーンショットに残さない
- ❌ url-test や fallback グループで API トラフィックを扱う
- ❌ 平均所要時間だけを見て、ttfb のばらつきとテール側の失敗率を見ない
- ❌ TUN モードでバイパスを設定せず、社内ネットワークやコンテナの通信まで遠回りさせる
結論を一言で:AI API の回線選びは、まず出口を固定し、次に揺らぎを見て、最後に帯域を見ます。ドメインのグループ分け、DNS の経路、タイムアウト設定の 3 つを整え、時間帯を変えた再測定の結果で回線タイプを変えるか判断するほうが、タイムアウト値を何度も大きくするよりはるかに効果的です。
VPNAY は 120+ の国と地域に 250+ の回線を提供し、直結・中継・IEPL 専用線をラインナップ。Windows / macOS / iOS / Android / Linux に対応し、デバイス数の制限はありません。登録にメールアドレスは不要で、ユーザー名とパスワードだけで始められます。API 利用でよく使う固定出口や長い接続向けの回線はクライアントから直接選べます。プランとトラフィックパックは料金ページをご覧ください。