Claude API 超时:哪些超时该改代码,哪些该改配置

超时分三种,先确定断在哪一层

连接超时:TCP 都没握上手

典型报错是 requests.exceptions.ConnectTimeout 或者 httpx.ConnectTimeout。含义是域名解析或者三次握手没在设定时间内完成,问题在网络层,常见原因是本机 DNS 出错、代理设置有问题、或者出口被限速。这种超时跟你调用的模型、用的参数完全无关。

读超时:连上了,但等不到响应

典型报错是这样的:

requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='xyuapi.top', port=443): Read timed out. (read timeout=60)

用 OpenAI 兼容 SDK 时是 openai.APITimeoutError: Request timed out.,用 Node 的 undici 时是 UND_ERR_HEADERS_TIMEOUT。这一类占了实际问题的九成:连接已经建立,服务端也在算,只是算完之前你的客户端先放弃了。

网关超时:504 是别人先放弃了

返回 504 Gateway Time-out 或者 nginx 的 upstream timed out,说明请求在你和上游之间某一段被掐断了。可能是你自己的反向代理,也可能是链路上的其他环节。这两种情况要改的位置不一样:读超时改客户端,504 改中间层配置。

现象典型报错原文断在哪先改哪里
连接超时ConnectTimeoutTCP 握手本机网络、DNS、出口
读超时Read timed out. (read timeout=60)等响应体客户端超时值、流式
SDK 超时openai.APITimeoutError等响应头SDK 的 timeout 参数
网关超时504 Gateway Time-out中间层代理的读等待时间

为什么 Claude 的长回答特别容易超时

带思考的模型先想再写

claude-sonnet-4-5-thinkingclaude-opus-4-5-thinking 这类模型会先输出一段推理过程,再输出正式答案。这段时间里 HTTP 连接是安静挂着的,一个字节都不返回。客户端如果设了 60 秒读超时,正好卡在这个空窗期上。

max_tokens 决定最坏情况下的时长

max_tokens 是输出上限,模型写满就是最长的生成时间。设成 8192 意味着最坏情况要生成 8192 个 token,非流式请求必须等它全部生成完才返回第一个字节。把上限从 8192 降到 2048,等待时间大致按比例缩短,是最直接的降超时手段。

非流式请求天然更容易超时

非流式是把整段回答攒齐了一次性返回。回答越长,攒的时间越长,超时风险越高。流式是生成一个片段就吐一个片段,客户端一直在收数据,读超时被不断重置,同一个请求用流式几乎不会超时。所以顺序应该是先开流式,再考虑调大超时值。

代码里的超时参数要分维度设

requests 用元组区分连接和读取

import requests

# (连接超时, 读取超时)
resp = requests.post(
    "https://xyuapi.top/v1/chat/completions",
    headers={"Authorization": "Bearer " + key},
    json={"model": "claude-opus-4-5-thinking",
          "max_tokens": 4096,
          "messages": [{"role": "user", "content": "写一段 800 字的产品说明"}]},
    timeout=(10, 600),
)

连接超时设 10 秒,读超时设 600 秒,是长文本场景比较稳的一组值。写成单个数字 timeout=600 会让连接阶段也等 600 秒,网络有问题时要干等十分钟才知道。

OpenAI 兼容 SDK 用 httpx 的超时对象

import httpx
from openai import OpenAI

client = OpenAI(
    base_url="https://xyuapi.top/v1",
    api_key=key,
    timeout=httpx.Timeout(connect=10.0, read=600.0, write=30.0, pool=10.0),
    max_retries=1,
)

SDK 默认会自己重试。长文本场景下把 max_retries 调到 1 或者 0,避免一次超时变成三次串行等待,总耗时反而翻三倍。

流式请求的超时含义变了

开了流式以后,读超时不再覆盖整段生成时间,只覆盖「两次数据之间的间隔」。所以流式下 600 秒可以降到 120 秒,甚至 60 秒也够用,因为数据在持续到达。这个区别很多人没意识到,于是把流式的超时也设成 600 秒,白白放大了故障时的等待时间。

网关侧的 60 秒默认值

nginx 默认读等待就是 60 秒

自己搭了反向代理的话,默认的 proxy_read_timeout 是 60 秒,和很多客户端的默认值撞在一起。哪怕你的代码设了 600 秒,代理也会在 60 秒时先断,客户端拿到的变成 504。三处都要放开:

location /v1/ {
    proxy_pass http://gateway;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
}

proxy_buffering off 这一行对流式特别关键。缓冲开着的时候,代理会把内容攒起来再转发,客户端看不到持续的数据流,流式的意义就没了。

CDN 和防火墙也会掐连接

有些边缘节点的空闲连接超时是 30 秒到 100 秒,流式请求在思考阶段长时间没有数据,会被判定为空闲而断开。判断方法:直连和经过 CDN 各测一次同一个长请求,看耗时和断点位置是否不同。

云函数的执行时限

Serverless 环境通常有硬性执行上限,短的是 30 秒。跑长文本生成时,函数还没拿到结果就被平台杀掉了。这种只能改用流式加前端直连,或者换成常驻进程。

自己的代理和公共链路分开测

在服务器上直接请求本机端口测一次,再走公网域名测一次,两次数值对比。自己代理这一段的问题会在这两个数之间暴露:本机快、域名慢,改代理配置;两边都慢,问题在别处,别在代理上浪费时间。

客户端里改超时在哪

Chatbox 和 Cherry Studio

这两个客户端一般不需要手动改超时,它们对长回答的处理比较宽松。真正卡住时,先看是不是用了不带流式的自定义模型配置,把流式开关打开。

编辑器插件

Cline、Cursor 这类插件调用时往往带一大段上下文,生成时间更长。插件设置里有请求超时的选项,把它调到 300 秒以上,同时把单次任务的最大迭代次数压下来,避免一个任务串行发几十次请求。

网页前端直连

浏览器 fetch 本身没有默认超时,但服务端和中间层有。前端做流式渲染时要用 TextDecoder 的流式模式,否则中文会被拆成半个字显示乱码,看起来像超时后残缺的响应。

移动端后台会冻结连接

手机应用切到后台时,系统会冻结网络连接,回到前台时流式连接已经断了,看起来像超时。移动端做长回答要在回到前台后检查连接状态,必要时重新发起,并且把已收到的内容保留在界面上。

超时之后该不该重试

先判断服务端是不是已经算完

读超时只说明你的客户端不等了,服务端可能已经把结果算完并发了出来。这种情况下重试会造成第二次生成,按次计费的话就是付两次钱。

按次计费下的成本很直观

模型单次价格
gemini-2.5-pro0.031 元/次
deepseek-v3.2-thinking0.049 元/次
claude-sonnet-4-5-thinking0.09 元/次
claude-opus-4-5-thinking0.12 元/次

单次价格固定,输入长短不影响价格,所以超时重试的代价是可预期的。但这不等于可以无脑重试:一次 600 秒超时加一次重试,用户要等二十分钟。

三种情况不重试

已经收到部分流式内容的不重试,把已有内容留下;400、401、403 这类明确错误不重试,重试结果一样;同一个请求连续两次超时的不再第三次,说明参数设置本身有问题,先把 max_tokens 和流式开关检查一遍。

把超时参数做成可配置项

连接超时和读超时不要写死在代码里,放到配置文件或者环境变量里。换模型、换场景时只改配置不改代码。排查超时时最耽误时间的往往不是找原因,而是每次都要改代码重启一次。

一套快速定位超时的办法

用 curl 给每个阶段计时

curl -s -o /dev/null -w "dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n" \
  --max-time 300 \
  https://xyuapi.top/v1/chat/completions \
  -H "Authorization: Bearer sk-你的Key" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-4-5-thinking","max_tokens":2048,"messages":[{"role":"user","content":"写一段300字说明"}]}'

几个数字的用法:time_namelookup 大说明 DNS 慢;time_connect 大说明网络到网关这段慢;time_starttransfer 是首字节时间,它大而总时间也大,就是生成时间长,属于正常的长文本代价;total 接近 --max-time 就是被掐断。

在代码里打时间点

每次请求记录三个时刻:发出前、收到响应头、收到完整响应体。三个数字一摆,超时发生在哪一段立刻清楚。日志里同时记下模型名和 max_tokens,方便对比不同参数下的耗时。

看是不是所有模型都超时

gemini-2.5-pro 发同样的请求。如果它正常,说明问题在长文本生成这一侧,不是网络;如果它也超时,说明是本机网络或者网关配置的问题。这一步能把排查范围砍掉一半。

先分清是超时还是本来就这么慢

用不同的输出上限跑三次

拿同一个提问,把 max_tokens 分别设成 512、2048、8192 各跑一次,记录耗时。如果耗时随上限明显增长,说明时间花在生成上,这是长文本的正常代价,要改的是超时值而不是网络。如果三次都很短却仍然报超时,问题在链路上,去看中间层的等待时间设置。

换一个短问题做对照

把提问换成一句「你好」。如果它秒回,说明连接和鉴权都正常,超时只出现在需要长时间生成的任务上。如果它也要等很久,说明链路上存在固定延迟,跟模型和参数都没有关系。

把首字节时间单独记下来

首字节时间反映服务端多久开始回应,总耗时反映生成用了多久。两个数字一起记,责任一次分清:首字节大是链路问题,总耗时大是生成时长问题。很多人把这两个数混成一个总耗时,于是永远分不清该改哪里。

重试要能认出重复请求

超时后重试时带上原请求的标记,同一分钟内出现多次相同请求时只保留一份结果,避免把重复生成的答案轮流展示给用户。在没有请求 ID 的场景下,退而求其次的做法是用提问内容的哈希值做标记,同样能挡住大部分重复。

接入地址和推荐参数

一个 Key 调全系列模型

小鱼API 是 AI API 接入平台,走 OpenAI 兼容协议,主入口 https://xyuapi.top/v1,备用 https://xyuai.cc/v1。Chatbox、Cherry Studio、NextChat、Cline 填上地址和令牌即可使用,一个 Key 调全系列模型,按次计费。

使用场景连接超时读超时是否流式
短问答10 秒60 秒可不开
长文生成10 秒600 秒建议开
带思考的模型10 秒600 秒建议开
前端直连流式10 秒120 秒必须开
批量离线任务10 秒900 秒建议开

超时问题的解法顺序是固定的:先开流式,再按维度设超时,最后才去调中间层。顺序反过来,会在配置里绕很久还得不到结果。

相关阅读

🚀 想要立即使用?来小鱼API体验全系列AI模型

查看全部产品

支持Gemini / Claude / GPT / Grok / DeepSeek · 国内直连 · 支付宝/微信