网络与超时问题
网络问题通常表现为域名无法解析、连接被拒绝、TLS 证书错误、连接重置或超时。与 400、401、403 等 API 错误不同,这类问题可能在客户端收到完整 HTTP 响应之前就已经发生。
先判断问题发生在哪一层
| 现象 | 问题通常发生在 | 优先检查 |
|---|---|---|
域名无法解析、NameResolutionError、ENOTFOUND | DNS | 域名、DNS 服务、网络和代理配置 |
Connection refused | TCP 连接 | 地址、端口、代理或防火墙 |
| 证书校验失败、TLS handshake failed | TLS | 系统时间、证书链、HTTPS 检查代理 |
ConnectTimeout | 建立连接前 | 网络、代理、防火墙、连接超时设置 |
ReadTimeout | 已连接但未及时收到数据 | 模型生成耗时、读取超时、上游负载 |
504 Gateway Timeout | 已收到网关的 HTTP 响应 | 上游模型未在网关时限内完成 |
| 流式输出到一半断开 | 持续传输阶段 | 网络波动、代理空闲超时、上游中断 |
返回 401、403、404 | API 已经收到请求 | 密钥、权限、Base URL、路径或模型 |
只要已经收到明确的 HTTP 状态码和 JSON 错误体,通常说明 DNS、TCP 和 TLS 已经基本完成,应先根据常见错误码排查 API 配置。
使用 Python 检查连接
先安装 requests:
python -m pip install requests
创建并运行下面的脚本。它会请求模型列表,同时分别设置连接超时和读取超时:
import time
import requests
url = "https://www.bita-api.com/v1/models"
api_key = "YOUR_BITA_API_KEY"
started_at = time.perf_counter()
try:
response = requests.get(
url,
headers={"Authorization": f"Bearer {api_key}"},
timeout=(10, 60),
)
elapsed = time.perf_counter() - started_at
print("HTTP 状态码:", response.status_code)
print("响应耗时:", f"{elapsed:.2f} 秒")
print("Content-Type:", response.headers.get("content-type"))
print("响应内容:", response.text[:500])
except requests.exceptions.ConnectTimeout:
print("连接超时:未能在 10 秒内建立连接")
except requests.exceptions.ReadTimeout:
print("读取超时:已建立连接,但 60 秒内没有收到响应数据")
except requests.exceptions.SSLError as error:
print("TLS 证书错误:", error)
except requests.exceptions.ConnectionError as error:
print("网络连接错误:", error)
将 YOUR_BITA_API_KEY 替换为完整密钥。模型列表请求通常比生成请求简单,适合先判断域名、HTTPS、密钥和基础 API 路径是否可用。
结果可以这样理解:
- 返回
200:基础连接正常,继续排查具体模型、生成端点或客户端配置。 - 返回
401或403:网络已经连通,继续检查密钥和权限。 - 返回
404:网络已经连通,检查请求地址和路径。 - 抛出 DNS、TLS、连接超时或连接错误:请求可能还没有到达 Bita API。
连接超时和读取超时有什么区别?
Python requests 可以用二元组分别设置两种超时:
timeout=(10, 300)
其中:
10秒是连接超时,限制 DNS、TCP 和 TLS 连接阶段的等待时间。300秒是读取超时,限制连接建立后,两次收到响应数据之间允许等待的时间。
读取超时不是整个请求的固定总时长。流式响应只要持续收到数据,单次请求的总时间可以超过该值;如果连续很久没有任何数据,才会触发读取超时。
可以从下面的范围开始,再根据模型和业务调整:
| 请求类型 | 连接超时 | 读取超时 |
|---|---|---|
| 模型列表、余额等轻量请求 | 10 秒 | 30~60 秒 |
| 普通非流式生成 | 10~20 秒 | 120~300 秒 |
| 长回答或推理模型 | 10~20 秒 | 300 秒或更长 |
| 流式生成 | 10~20 秒 | 按允许的最大无数据间隔设置 |
不要完全取消超时。应用还应设置单次任务的总时限,避免异常请求永久占用连接和工作线程。
为什么模型列表正常,生成请求却超时?
模型列表只需要读取少量平台数据,而生成请求还需要等待上游模型处理输入并生成输出。继续检查:
- 目标模型当前是否可用,端点类型是否匹配。
- 输入上下文、图片或文件是否过大。
max_tokens、max_output_tokens等最大输出设置是否过高。- 是否启用了复杂工具调用、深度推理或多轮代理任务。
- 客户端的读取超时是否仍使用较短的默认值。
- 同一时间是否发起了过多并发请求。
可以先用短提示和较小输出发送最小请求。最小请求成功后,再逐步恢复历史消息、工具、图片和输出长度。
首段内容很慢怎么办?
首段内容出现前的等待时间通常受以下因素影响:
- 模型本身的推理方式。
- 输入上下文长度和多模态内容大小。
- 上游模型负载和请求排队时间。
- 工具定义、结构化输出约束和提示词复杂度。
- 客户端到 Bita API 以及 Bita API 到上游之间的网络延迟。
如果只是不希望界面长时间没有反馈,可以使用流式响应。流式响应能更早展示已生成的内容,但不会缩短模型开始生成前的处理时间。
流式响应为什么会中途断开?
常见原因包括本地网络切换、VPN 或代理重连、反向代理空闲超时、上游模型中断,以及客户端没有持续读取 SSE 数据。
Python 请求必须同时启用接口流式模式和客户端流式读取:
response = requests.post(
"https://www.bita-api.com/v1/chat/completions",
headers={"Authorization": "Bearer YOUR_BITA_API_KEY"},
json={
"model": "YOUR_MODEL_ID",
"messages": [{"role": "user", "content": "请用三点解释流式响应。"}],
"stream": True,
},
stream=True,
timeout=(10, 300),
)
response.raise_for_status()
for line in response.iter_lines():
if line:
print(line.decode("utf-8"))
如果响应总是在相近时间断开,应检查客户端、VPN、公司代理和网关是否设置了固定的 30 秒、60 秒或其他空闲超时。若第三方工具没有暴露超时设置,可先用上面的 Python 请求对比,判断问题来自 Bita API 还是该工具自身。
流式请求中断后,本次文本可能不完整。重新请求应视为一次新的生成,不要把两次输出直接拼接成一个完整结果。
504 Gateway Timeout 应该怎么处理?
504 表示客户端已经连接到网关,但网关等待上游模型超时。可以:
- 等待数秒后有限重试。
- 缩短输入上下文或减少最大输出长度。
- 关闭不必要的工具、图片和复杂结构化输出。
- 测试同分组中的另一个可用模型。
- 查看使用日志,确认问题是否只发生在一个模型或特定时间段。
单纯提高客户端读取超时不能消除服务端返回的 504。客户端超时决定“客户端愿意等多久”,504 则表示“网关已经停止等待上游”。
客户端超时后,是否可以立即重试?
客户端超时不代表服务端一定取消了请求。请求可能已经到达模型并继续生成,也可能已经产生用量记录。
重试前建议:
- 在使用日志中按发生时间和模型查找原请求。
- 判断任务是否会执行工具、写入数据或产生其他副作用。
- 对纯文本生成进行有限重试。
- 对有副作用的任务使用业务请求 ID 或其他幂等机制,避免重复执行。
不要在超时后立即并发发送大量相同请求,这可能增加重复费用和上游负载。
DNS 解析失败
出现 NameResolutionError、getaddrinfo failed、ENOTFOUND 或“无法解析主机”时:
- 确认域名拼写为
www.bita-api.com。 - 用浏览器访问
https://www.bita-api.com,判断当前网络能否访问站点。 - 临时关闭或更换 VPN、系统代理后重试。
- 检查公司、校园或公共网络是否限制了该域名。
- 更换到其他网络,对比是否仍然失败。
- 修改 DNS 后,完全重启应用和终端再测试。
不要把 Base URL 改成 DNS 解析出的 IP 地址。HTTPS 证书和请求路由依赖正确域名,直接使用 IP 可能产生证书错误或访问到错误的站点。
TLS 或证书错误
出现 CERTIFICATE_VERIFY_FAILED、SSLError 或 TLS handshake 错误时,检查:
- 设备日期、时间和时区是否正确。
- 操作系统、Python、Node.js 或客户端的根证书是否过旧。
- 公司代理、防病毒软件或网关是否正在替换 HTTPS 证书。
- 是否错误地通过 HTTP 代理访问 HTTPS 地址。
- 容器或精简 Linux 镜像中是否缺少 CA 证书包。
不要把 verify=False、关闭证书校验或忽略浏览器证书警告作为长期解决方案。应更新 CA 证书,或按组织要求安装可信的代理根证书。
代理或 VPN 导致失败
同一台设备上,浏览器、终端、编辑器和桌面客户端可能使用不同的代理设置,因此“网页可以打开”不代表 SDK 一定使用相同网络路径。
排查时可以:
- 确认客户端是否启用了单独的代理设置。
- 检查系统代理、VPN、开发工具代理和运行环境是否互相覆盖。
- 分别在启用和停用代理时运行最小 Python 请求。
- 如果只有公司网络失败,联系网络管理员确认 HTTPS、SSE 和长连接是否被限制。
- 修改代理后完全重启客户端,避免旧连接继续复用。
Python requests 默认可能读取系统环境中的 HTTP_PROXY 和 HTTPS_PROXY。如果脚本行为与浏览器不同,应同时检查运行进程实际继承的代理配置。
怎样设置重试?
适合有限重试的情况包括:
- 连接重置或临时连接失败。
- 读取超时。
- 限流类
429。 500、502、503、504。
不应原样重试 400、401、403 和持续的 404。这些错误通常需要先修改请求、密钥、权限、地址或模型。
建议使用带随机抖动的指数退避,例如等待约 1、2、4、8 秒,并限制最大次数。收到 Retry-After 时优先按该响应头等待。生产应用还应设置总重试时限,并记录最后一次错误。
为什么控制台没有对应日志?
如果客户端报错,但控制台使用日志中没有相同时间的记录,请优先检查:
- DNS、TLS 或连接阶段是否已经失败。
- 请求是否发送到了错误域名或本地代理。
- 第三方工具是否仍在使用旧 Base URL。
- 日志筛选的时间范围、模型或 API 密钥是否正确。
- 设备时区与控制台显示时间是否不同。
没有日志通常说明请求未进入正常的模型调用流程,但不能仅凭这一点确定具体失败位置。
反馈问题时提供什么?
请提供以下信息:
- 发生时间和时区。
- 使用的客户端、SDK 及版本。
- Base URL、接口路径和模型 ID。
- 是否使用代理、VPN、容器或公司网络。
- 错误类型、HTTP 状态码和完整错误消息。
- 连接超时与读取超时的设置值。
- 是否为流式请求,以及断开前是否收到过内容。
- 使用日志中是否存在对应记录。
- 一个可以复现问题的最小请求示例。
相关排查页面:常见错误码、Base URL 与 /v1 路径问题、余额、额度与限流问题。