簡短回答
控制台日誌的「用時」和你客戶端的超時,量的不是同一段時間。
- 日誌的用時記到閘道處理結束為止;
- 你的客戶端要等到響應體最後一個位元組收完、且連線給出收尾訊號才算拿到結果。
日誌的「用時」到底記了哪一段
一次呼叫的完整耗時可以拆成五段:
控制台日誌與日誌查詢 API 裡可用的欄位:
duration_for_view(本次呼叫耗時,單位秒)、is_stream(是否流式)、request_id(報障時提供這個)。
第一步:用一條 curl 把差值定位到具體環節
這是整個排查的入口,先跑這一條,再決定往下看哪一節。判讀表
拿上面的數字對號入座,這張表決定你接下來該做什麼:第二步:怎麼把「資料到齊但沒收尾」量出來
如果判讀表指向第三行,需要更細的觀測:逐塊讀響應,記錄每一塊的到達時間和塊間停頓。關鍵是要能回答一個問題——最後一個位元組到齊之後,連線還空轉了多久。- Python
- Node.js
tail_99 超過 30 秒,或 max_gap 超過 30 秒,就記一次「尾部扣留」。典型形態是 max_gap 出現在位元組數已達 100% 的位置——也就是資料一個不少地到齊了,之後才開始空等。
第三步:兩臺伺服器之間怎麼測速
你自己的兩臺機器之間
用iperf3 直接打真實吞吐,這是最準的:
你的伺服器到我們介面
這一段沒法用 iperf3——我們不提供 iperf 服務端。改用真實呼叫測出來的有效速率:算一下你的頻寬夠不夠
出圖的響應體是一整塊 base64,實測體積量級:
base64 編碼本身還會讓體積膨脹約 33%。獨佔頻寬時的下行耗時:
關鍵在於這張表是獨佔頻寬的理想值。 實際上:
第四步:打點日誌該記哪些欄位
要把現象說清楚(無論是自己定位還是發給我們),每次呼叫至少記這些:
最後一列經常被漏掉,但它往往是結論本身:把速率和併發數畫在一起,如果速率隨併發上升而成比例下降,頻寬就是瓶頸,不用再往別處找。
怎麼用這張表:把它和控制台日誌的
duration_for_view 並排比——
- 兩者接近 → 問題在下行傳輸,看頻寬和併發;
- 差得很遠 → 問題在收尾訊號或客戶端側。
能立刻降低風險的四件事
1
改用 URL 輸出,這是收益最大的一招
gpt-image-2-vip 和 gpt-image-2-all 支援 response_format: "url",返回圖片連結而不是 base64。響應體從約 2.6 MB 降到約 0.3 KB——下行傳輸和收尾訊號兩類問題會同時消失(小響應帶 Content-Length,客戶端自己就知道讀完了)。強依賴 URL 輸出的業務,把令牌分組切到 image2_OSS:確定性輸出 URL、不會在資源緊張時降級為 base64,而且是 1x 倍率不加價。2
把響應體壓小
仍需 base64 時:用
output_format=jpeg 配合 output_compression,比 PNG 體積小一半以上;按實際用途降低 size 與 quality,不要預設拉滿 4K。輸入參考圖也壓到 1.5MB 以內,上行同樣受益。3
把併發控制在頻寬能承受的範圍
用上一節的公式反推:
可接受的下行耗時 × 出口頻寬 ÷ 單張體積 就是併發上限。超過這個數,加併發只會讓每個請求都變慢,總吞吐不漲。各模型的併發限制見 API 可以開多少併發。4
超時分三段設,並在資料到齊時主動收尾
按前面的表分別設定等首位元組、塊間停頓、收尾寬限三個超時。資料已經到齊卻等不到收尾訊號時,主動把手裡的響應交給業務——完整的相容程式碼見出圖請求收尾卡住。
常見疑問
沒拿到結果,為什麼還照常扣費?
沒拿到結果,為什麼還照常扣費?
因為計費發生在閘道處理結束時,而這時上游確實已經把結果生成並返回了。客戶端後續能不能收到,不改變這次呼叫已經產生的成本。實測對照:客戶端在 5 秒時主動斷開,與完整跑完的扣費完全相同。反過來用,這條是最強的判據:有計費記錄,說明請求確實跑到了上游併成功了,問題一定在「閘道處理結束之後」或「請求真正發出之前」,不用再懷疑上游。圖片介面沒有非同步任務 ID,斷開就拿不回結果,這一點見圖片生成有非同步介面嗎。
把 timeout 從 600 秒再調大到 1200 秒,有用嗎?
把 timeout 從 600 秒再調大到 1200 秒,有用嗎?
分情況,這也是為什麼必須先測一次再動手:
- 下行慢(速率低、位元組還在持續增長):有用,調大就能拿到結果。
- 收尾訊號沒來(位元組早已收齊、末尾長時間零新增):沒用。實測這種狀態下持續等待 330 秒,一個新位元組都不會再來,調大超時只是把故障暴露得更晚。這種情況要在客戶端主動收尾。
這到底是我這邊的問題,還是你們閘道的問題?
這到底是我這邊的問題,還是你們閘道的問題?
兩邊都可能,所以才要先測。我們把兩邊的判據都擺出來:
- 偏你這邊:
speed_download明顯偏低、速率隨併發上升而下降、mtr看到丟包、或 curl 正常而只有業務程式碼超時。 - 偏我們這邊:位元組早已收齊、末尾長時間零新增資料。閘道側確實存在過「收尾訊號推遲」的問題(根因是出圖路徑的記賬阻塞了請求處理),已隨上游版本於 2026 年 8 月 13 日修復並驗證。即便在完全健康的時段,仍有約 4% 的請求要多等 10~79 秒才收到收尾訊號——這些請求的資料其實早就傳完了。
有非同步介面嗎?不想一直掛著連線
有非同步介面嗎?不想一直掛著連線
目前圖片生成均為同步呼叫,沒有任務 ID 查詢介面。非同步方式在規劃中,上線後會另行公告。在此之前,推薦在自己這一側包一層非同步外殼(提交即返回本地任務 ID,後臺 worker 跑同步呼叫),做法見自建非同步佇列。
換個接入地址或者換臺機器能繞開嗎?
換個接入地址或者換臺機器能繞開嗎?
看是哪一類。頻寬不足是你的出口決定的,換我們的入口地址沒用,要麼擴頻寬、要麼降體積、要麼降併發。收尾訊號那一類在故障窗內是多個落點同時出現、又同時恢復的,換域名同樣繞不開。唯一要避開的是 CDN 節點:
api-cf.apiyi.com 走 Cloudflare,約 100 秒會返回 524,不適合跑出圖這類長請求。客戶端側最容易被忽略的三條
如果 curl 測下來一切正常,只有業務程式碼超時,往這三個方向查:- 超時語義不是你以為的那個。600 秒到底是總超時,還是隻是讀超時?Node 的
undici有headersTimeout/bodyTimeout/connect.timeout三個獨立超時,預設值遠小於你在外層設的那個數,只改外層不生效。 - 連線池排隊。連線池被佔滿時,請求還沒真正發出去就已經開始計時了。這段等待在我們這邊完全看不見——後臺日誌里根本沒有這條請求,直到它真正發出。判斷方法:日誌裡查不到對應記錄,基本就是這一類。
- 中間還有一層。自建 nginx 的
proxy_read_timeout預設 60 秒,負載均衡、API 閘道、Serverless 平臺各自都有超時上限。把鏈路上每一跳的超時都列出來,取最小值才是你的真實超時。
上報時請提供
自查之後仍需要我們協助,請把這些一起發過來,可以少來回好幾輪:- 請求 ID(幾條即可,不用全量)
- 分段計時:首位元組耗時 / 末位元組時間 / 總耗時 / 響應體位元組數
- 發生時間,標註時區(如
2026-08-13 15:57 (UTC+8)) - 當時的併發數和出口頻寬
- 用的是哪個模型和令牌分組
相關文件
如何避免介面超時?
各場景該設多少 timeout,以及節點選擇
出圖請求收尾卡住
資料已到齊但連線不結束時的客戶端相容程式碼
圖片 API 連線中斷排查
ECONNRESET、SSL EOF 一類下行斷連的定位
API 可以開多少併發?
各類模型的併發限制與配額申請
圖片 API 呼叫須知與最佳實踐
各圖片模型的 timeout 速查表與輸出格式對照
怎麼看懂日誌裡的計費金額?
後臺日誌各列的含義與計費口徑
聯絡我們
企業微信客服
郵件諮詢
客服郵箱:[email protected]商務合作:[email protected]
