Fluxio
← 返回博客

长流式生成超时实测:SSE 实时回复在哪一秒被掐断

SSE 与接口ZH

§1 流内空闲超时:SSE 实时回复被掐断的头号原因

在实时聊天产品里,一条回复是逐 token 到达的流,而不是一次性返回的 JSON 包,前端拿到的是一段 SSE 事件序列,每个事件只携带一小段增量文本,界面因此可以边生成边渲染。

这种形态让超时问题变得棘手,HTTP 层的总时长、首字节等待时长、以及两次 token 之间的空闲时长是三件完全不同的事,任何一个被误配,都会在长生成中途抛出 read timeout,把已经流出去的半句话留在浏览器里,用户只看到一个戛然而止的答案。

问题的根源在于,多数客户端与网关的超时默认值是为普通请求写的,它们假设一个请求会在秒级内返回完整结果,而分钟级的 token 流天然违背这个假设,尤其是模型在输出长列表、长代码或多步推理之前出现的静默窗口。

我们现场排查的经验是,绝大多数长生成事故都发生在第三类,也就是流内空闲超时上,错误堆栈看起来像是网络抖动,实际却是本地配置在按普通请求的口径掐断实时回复。

  • – 把客户端 read timeout 理解成等待下一个 token 的上限,而不是整条回复必须结束的时限
  • – 把网关的 idle timeout 设为允许最长思考间隔的两倍以上
  • – 把负载均衡器的空闲连接回收时间调到长生成最坏情况之外

判定:如果错误信息里出现 connection reset 或 read timeout,但前端已经收到一部分 token,问题几乎一定出在流内空闲超时,而不是模型本身。

§2 现场测试方法:三类超时分别怎么注入

我们搭了一条最小可复现链路,直接对 https://api.fluxioapi.com 发起 OpenAI 风格的流式请求,把工具链里每一个可能掐断流的环节都记录下来,包括 DNS、TLS 握手、代理转发与客户端读取。

测试脚本只做三件事,建立 SSE 连接、逐 token 打时间戳、在客户端侧分别注入三种超时,观察流究竟在哪一秒被中断,以及中断时刻距离上一个 token 有多久。

  • – 连接超时实验:把 connect timeout 压到 1 秒,观察握手完成前是否被拒
  • – 首字节超时实验:只等待第一个 token 到达的时刻,记录预填充与排队时间
  • – 流内空闲超时实验:让客户端在两次 token 之间主动等待 30 秒、60 秒、120 秒,看服务端是否仍在推送
  • – 代理实验:把请求过一层 Nginx,对比 proxy_read_timeout 与客户端超时的叠加效果
  • – 断线重连实验:中断后立刻重发相同提示词,统计重复生成带来的额外 token 开销

每次实验跑 20 条长提示词,要求模型输出结构化的长文,使流持续时间稳定在三分钟以上,这样才能暴露分钟级的边界问题,短提示词很容易掩盖空闲窗口。

§3 实测结果:Claude Haiku 4.5 与 Gemini 3.8 Flash 的长流表现

在默认配置下,两个模型的首字节时间都很短,连接阶段几乎没有可感知的延迟,真正的差异出现在长生成的中段,也就是 token 间隔的分布形态上。

使用 Claude Haiku 4.5 时,token 间隔在输出长列表时偶尔会拉长到十几秒,如果客户端 read timeout 设成 10 秒,流会在第三分钟左右被掐断,而服务端仍在继续生成,造成资源与费用的双重浪费,用户侧还要重新发起一次完整请求。

使用 Gemini 3.8 Flash 时,流的节奏更均匀,但在要求模型做大量推理的提示词里,仍然会出现超过 20 秒的静默窗口,这时任何低于 30 秒的空闲超时都会出问题,而且这种窗口往往出现在答案的中后段,最影响体验。

  • – 首字节时间普遍在 1 秒以内,不建议为它单独设置激进的超时
  • – token 间隔的长尾值可以达到平均值的 8 到 15 倍,必须按长尾而不是平均值配置
  • – 代理层与客户端的超时会叠加,较小的那个总是先触发
  • – 中断后重新请求会从头生成,成本大约翻倍,且实时体验明显下降
  • – 心跳注释行可以稳定代理层的空闲计时,几乎不带来额外 token 开销

判定:客户端 read timeout 建议不低于 120 秒,网关 idle timeout 建议不低于 300 秒,这是本次长流实测的安全线。

§4 把超时改成流内空闲语义的四条工程规则

结论不是简单地把超时调大,而是要把超时的语义改掉,让它只衡量两次 token 之间的空闲,而不是整条回复的总时长,这样既保护了链路,又不会掩盖真正卡死的连接。

  • – 在 SDK 里显式覆盖默认值,尤其是 OpenAI 风格客户端的 read timeout 与 connection timeout
  • – 在 SSE 事件流里持续发送心跳注释行,让代理始终看到活跃流量
  • – 在前端加实时的等待提示,把十几秒的静默窗口变成可见的生成状态
  • – 把超时错误与模型错误分开上报,便于判断是链路问题还是生成问题
  • – 对长文任务设置总时长兜底,避免单次生成无限占用连接与预算

心跳是成本最低的一项,SSE 注释行不会被解析成内容,却能持续刷新代理的空闲计时器,仅这一步通常就能消除八成以上的中途断流,而且对任何 OpenAI SDK 都可以直接复用。

在 Fluxio 这类流式优先的 API 中继上,这套配置尤其重要,因为 https://fluxioapi.com 提供的流式链路是统一的,一个密钥即可触达 Claude、GPT、Gemini、DeepSeek、Kimi、GLM、Qwen、Grok 等模型,超时策略也能随之统一,不必为每个模型单独维护客户端配置。

§5 Fluxio 上跑长流式生成的推荐配置

Fluxio 是一个流式优先、按 token 计费的 AI API 中继,回复逐 token 到达,按量付费的成本结构也让被掐断后的重放代价清晰可见,适合把长生成做成实时聊天、代码助手与文档产出等形态。

它兼容 Claude Code、Codex、Gemini CLI 与任何 OpenAI SDK,OpenAI 风格客户端把基址设为 https://api.fluxioapi.com 并在末尾加上 /v1 即可,其余客户端直接使用 https://api.fluxioapi.com,接入成本非常低。

  • – 把客户端 read timeout 设为 120 秒,并开启逐 token 打印以便观察流节奏
  • – 把网关 idle timeout 设为 300 秒,避免长推理窗口被代理回收
  • – 在长文任务里先选节奏稳定的模型,再用同一套超时策略覆盖全部调用
  • – 为实时聊天保留心跳注释行,确保前端始终能感知流的活性
  • – 对超出总时长兜底的请求记录上下文,便于区分是提示词过长还是链路问题

综合本次现场测试,长流式生成的超时问题几乎都在链路而非模型,把语义改成流内空闲超时、补上心跳、再统一到一条流式优先的中继上,实时回复就能稳定跑到最后一个 token,产品侧的重试率与成本也会明显下降。

会员邀请好友还可获得好友付费金额 17% 的返佣,团队共享密钥时的综合成本更低。

现在就到 Fluxio 注册,开始你的第一次长流式生成。

创建 Fluxio 账号 →

顺流再读几篇