推理服务用 httpx 0.27 调上游,connect 和 read 都设了 30 秒,输出 1500 字以上的回答有 12% 在 30 秒处被切断,客户端收到半截 JSON,日志里是 ReadTimeout。

一开始怀疑是「网关侧另有一层 30 秒超时,只改客户端没有用」,查了一圈,方向不对。

排查方向其实有限,先把可能性排一排。read timeout 指的是两次数据块之间的间隔,不是整段耗时。少数情况下是上游开了流式但网关没走 chunked,整段只算一次读。

少数情况下是重试把被截断的请求又发了一遍,账单跟着翻倍。

先确认是首包慢还是尾包慢

curl -w '%{time_starttransfer} %{time_total}\n' -o /dev/null -s https://api.example.com/v1/chat/completions

然后按流式场景把 read 超时调到 120 秒

python -c "import httpx;print(httpx.Timeout(connect=10,read=120,write=30,pool=10))"

随后用脚本按 chunk 打印到达间隔定位卡顿点

python stream_probe.py --url https://api.example.com/v1/chat/completions --n 20

等前面都确认过,再把网关的读超时一并放大后重载

nginx -T | grep proxy_read_timeout

别只看报错消失,验证要多做一步。1500 到 3000 字的回答不再出现 ReadTimeout,首包中位数 0.8 秒,整段耗时 22 秒,客户端拿到的 JSON 都能完整解析。

容易忽略的是,read timeout 管的是两次读之间的空档,长生成要另设整段上限,否则把 read 改大之后,卡死的连接会一直挂着不释放。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189