简短回答
控制台日志的「用时」和你客户端的超时,量的不是同一段时间。
- 日志的用时记到网关处理结束为止;
- 你的客户端要等到响应体最后一个字节收完、且连接给出收尾信号才算拿到结果。
日志的「用时」到底记了哪一段
一次调用的完整耗时可以拆成五段:
控制台日志与日志查询 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]
