AI API 線路推薦的核心不是「哪條線路最快」,而是「哪條線路能讓請求穩定地落在同一個出口上」。網頁端斷一次重新整理即可,腳本裡一次逾時可能讓整批任務重跑,還會帶來重複計費。下面把固定出口、併發連線、逾時重試三件事拆開來講,最後給一份可以直接照著做的排錯步驟。

AI API 呼叫與網頁端的差別

同一個訂閱,瀏覽器裡能開啟的服務,腳本裡未必跑得通。差別不在頻寬,而在請求形態和失敗代價。

  • 連線時長不同。網頁端一次頁面載入由幾十個短請求組成,單一請求很快就結束;API 的串流回應會讓一條連線持續幾十秒甚至幾分鐘,中途任何一次抖動都直接反映在輸出上。
  • 失敗代價不同。網頁端失敗重試一次;批次任務失敗要重跑,消耗的是配額和費用,還可能因為重複提交產生重複結果。
  • 出口敏感度不同。不少 API 服務按「帳號 + 出口 IP」做風控。出口在同一天裡反覆變化,容易觸發二次驗證、臨時限流,嚴重的會直接拒絕。
  • 併發模型不同。瀏覽器最多幾個分頁;腳本可以同時開幾十條連線,壓力落在用戶端連線池和出口的 NAT 連線表上。

把這四點放在一起看,選線路的順序就清楚了:先確保出口穩定,再談線路類型,最後才是調逾時參數。

固定出口:為什麼比最快更重要

固定出口指的是同一個帳號的請求,長期從同一個或同一小組出口 IP 出去。它解決的是「伺服器認不認得你」的問題,而不是「跑得快不快」的問題。

出口漂移會造成什麼問題

  • 工作階段與 Token 綁定 IP 時,重連換 IP 會讓既有工作階段失效,需要重新驗證。
  • 設定了 IP 白名單的介面,出口一變就直接回傳 403。
  • 風控系統看到同一帳號短時間內從多個地區登入,會提高驗證等級。
  • 排查問題時,日誌裡的出口 IP 每次都不一樣,很難判斷是線路問題還是程式碼問題。

共用出口不等於線路差

很多人把「晚高峰變慢」歸因於線路品質,實際原因常常是出口被共用:同一個出口 IP 上有很多使用者,目標服務看到的是這個 IP 的高頻請求,於是觸發限流。判斷方法是看錯誤類型——如果是 429 或連線被重置,而頻寬測試正常,基本上就是出口側的問題。

怎麼驗證出口是否固定

準備一個能回傳請求來源 IP 的回顯位址,在代理開啟的狀態下連續請求,記錄每次結果;斷開重連後再測一輪;隔幾個小時再測一次。三輪結果一致,才算固定。

export ECHO_URL="你的回顯位址"

# 連續請求,觀察出口 IP 是否漂移
for i in 1 2 3 4 5; do
  curl -s --max-time 10 "$ECHO_URL"
  printf '\n'
  sleep 2
done
結論:如果只能記住一件事,記出口 IP 的穩定性。它決定了驗證、風控和排錯能不能收斂,而速度可以在穩定之後再最佳化。

併發連線與線路類型的搭配

併發上限由四段共同決定:本機連線池、代理用戶端的多工設定、線路頻寬與出口 NAT 連線表、目標服務的帳號層級限流。任何一段打滿,表現都是逾時或連線被拒,只看其中一段會誤判。

三種線路類型的差別

線路類型 路徑特徵 出口表現 適合的呼叫形態 需要注意
IEPL 專線 走電信業者專線出境,不經過公共網際網路的國際出口 出口相對固定,抖動小 長連線、串流回應、批次任務 成本較高,可選地區比直連少
中轉 先連到就近的中轉節點,再由中轉節點出境 出口由落地節點決定 日常呼叫、對成本敏感的場景 多一跳,中轉節點壅塞時整體變慢
直連 本機直接連境外節點 出口隨節點變化 輕量請求、臨時除錯 國際出口壅塞時波動明顯

選哪一種取決於呼叫形態,不是取決於價格。串流回應和批次任務優先選專線,臨時除錯用直連就夠,中轉適合把兩者分開:除錯走一條,正式環境走另一條。

協定層要看的兩點

Shadowsocks、VMess、Trojan、VLESS 走 TCP,Hysteria2、TUIC 基於 QUIC 走 UDP。對 API 呼叫來說,協定選擇影響的是兩件事:

  • 時間校驗。VMess 依賴用戶端與伺服器的時間一致性,系統時間偏差過大會直接握手失敗。這類失敗看起來像線路不通,實際上同步一次時間就好。
  • UDP 可用性。Hysteria2 和 TUIC 在封包遺失的鏈路上表現更穩,但依賴網路不限制 UDP。部分辦公網路與公共網路會限制 UDP,這時只能退回 TCP 類協定。
串流回應被「攢著一起回傳」,多半不是線路問題,而是用戶端或中間層做了緩衝。排查時先看首位元組到達時間,再看後續輸出是否逐段到達。

逾時與重試:用戶端側的最小設定

逾時不是設一個總數就沒事。一次請求要分成四段看:建立連線、TLS 握手、首位元組回傳,以及串流輸出過程中的閒置間隔。四段混在一起設,排錯時無法定位是哪一段出的問題。

  • 連線逾時設短一些,連不上就換線路,不要掛著等。
  • 首位元組逾時涵蓋 TLS 與請求送出到第一個位元組回傳,可以比連線逾時寬鬆。
  • 閒置讀取逾時針對串流回應,只計算兩段輸出之間的間隔,不計算總時長。
  • 總時長對串流請求不要設,否則長回答會被自己的用戶端截斷。

重試要滿足三個條件:請求可重試、錯誤可重試、次數有上限。連線失敗、讀取逾時、429 和 5xx 可以重試;400、401、403 這類參數或驗證錯誤重試多少次都一樣,只會放大問題。

import random
import time

import httpx

API_URL = "https://api.example.com/v1/chat"

# 四段逾時分開設:連線 5s,閒置讀取 60s
timeout = httpx.Timeout(connect=5.0, read=60.0, write=10.0, pool=5.0)
# 連線池上限決定本機併發上限
limits = httpx.Limits(max_connections=16, max_keepalive_connections=8)

with httpx.Client(timeout=timeout, limits=limits) as client:
    for attempt in range(4):
        try:
            with client.stream("POST", API_URL, json={"stream": True}) as resp:
                if resp.status_code in (429, 500, 502, 503, 504):
                    raise httpx.HTTPStatusError(
                        "retryable", request=resp.request, response=resp
                    )
                resp.raise_for_status()
                for line in resp.iter_lines():
                    handle(line)  # 逐行處理,不要先攢進清單
            break
        except (httpx.ConnectError, httpx.ReadTimeout, httpx.HTTPStatusError):
            if attempt == 3:
                raise
            # 指數退避加抖動,避免多個任務同時重試
            time.sleep(min(2 ** attempt, 8) + random.uniform(0, 0.5))
已經在串流回應裡輸出過內容再重試,會造成重複輸出和重複計費。正確做法是記錄已輸出的位置,或者把重試判斷放在請求送出之前。

DNS 與分流規則怎麼搭配

DNS 洩漏指的是網域名稱交給本機 DNS 解析,拿到的是「離你最近」的節點,而不是「離出口最近」的節點。對多數 API 來說,伺服器用統一入口,影響有限;但對按區域回傳不同結果的服務,解析結果會直接決定請求打到哪個區域,驗證也可能跟著失敗。

分流比全域更省事

把 API 網域固定走一條線路群組,其餘流量走預設群組,好處有三點:出口穩定、除錯時能單獨切換、一條線路出問題不影響其他任務。規則按網域後綴寫比按 IP 寫更穩,因為 API 的入口 IP 會變,網域不會。

檢查順序

  1. 在代理開啟的狀態下解析目標網域,記錄結果。
  2. 關閉代理再解析一次,比對兩次結果是否落在同一區域。
  3. 用回顯位址確認最終出口 IP,而不是只看解析結果。
  4. 如果解析結果和出口地區不一致,檢查用戶端的 DNS 設定與分流規則優先順序。

選線路時的自查清單

把上面幾節濃縮成一份清單,選線路時逐條對照,比看參數表有用。下面四個數字是訂閱側能直接確認的條件,不是測速結果。

  • 120+ 國家與地區可選出口
  • 150+ 線路,可按網域分流
  • 不限 裝置台數,瓶頸在出口側
  • 7 天 無理由退款,夠跑一輪觀察
  • ✅ 出口 IP 是否固定,斷開重連後是否維持不變。
  • ✅ 能否指定出口地區,是否有多條線路可切換。
  • ✅ 是否支援長連線與串流回應,用戶端會不會做緩衝。
  • ✅ 單一帳號併發是否受限,限制在本機還是出口側。
  • ✅ 是否支援按網域分流,規則能不能單獨調整。
  • ✅ 計費方式是否匹配呼叫量:月付按開通日重置,流量包用完為止、不過期。
  • ❌ 只看標稱頻寬,不看出口穩定性。
  • ❌ 把除錯、正式環境、批次任務放在同一個出口上。
  • ❌ 用單次請求的結果判斷一條線路的好壞。

排錯步驟:從出口 IP 到併發

出問題時不要從改參數開始,按下面的順序走,每一步都有明確的判斷依據。

  1. 確認代理是否生效。請求回顯位址,看出口 IP 是否為目標地區。IP 沒變,後面都不用查。
  2. 確認 DNS。比對代理內外的解析結果,判斷是否發生洩漏。
  3. 確認系統時間。VMess 等協定依賴時間校驗,偏差過大會握手失敗。
  4. 確認 TLS。憑證錯誤、SNI 不符、中間設備攔截,表現都是連線被重置。
  5. 確認串流輸出。看首位元組時間與逐行到達情況,判斷是否被緩衝。
  6. 確認併發。從低併發逐步加壓,記錄錯誤類型分布,而不是只看平均值。
  7. 確認線路切換。換一條線路重現:能重現說明是用戶端或程式碼問題,不能重現說明是線路問題。
順序很重要:出口 IP 決定請求能不能被正確辨識,DNS 決定請求打到哪個區域,逾時與重試決定失敗之後會不會放大。按這個順序排查,比反覆換線路省時間。

一週觀察記錄與結論

單次請求的結果說明不了什麼。跨境線路的表現按時段波動,平日白天、晚高峰、凌晨是三種狀態。建議用一週時間記錄同一組請求,每次記錄五個欄位:

  • 時間與線路名稱
  • 出口 IP
  • 首位元組時間
  • HTTP 狀態碼或錯誤類型
  • 是否觸發重試

一週之後看的是分布,不是平均值:錯誤集中在哪個時段、哪條線路、哪類錯誤。如果 429 集中在晚高峰,說明出口被共用;如果連線逾時集中在某條線路,說明那條線路的入口壅塞;如果 TLS 錯誤零散出現,優先查用戶端與中間設備。

結論:AI API 呼叫的線路選擇,順序是固定出口優先、線路類型其次、逾時與重試最後。出口穩定之後,併發和逾時才有調校的意義;出口不穩定,調什麼參數都只是把失敗往後延。