流式输出(SSE)在中转站上的六种异常,以及每一类的定位方法

教程 发布于 2026-10-01 36 次阅读 API指南针
流式输出是最容易看出中转站质量的地方。本文列出六类可观察的异常表现,每类给出定位方法与判断结论。

为什么流式是「照妖镜」

中转站在非流式模式下只需要把上游的响应体整段转发,实现简单、不容易出错。而流式模式下,它必须逐块解析上游的 SSE、再逐块重新封装。任何格式理解上的偏差都会立刻暴露在输出里。

所以:评估一家中转站的技术实现水平,看非流式不如看流式。

异常一:输出出现重复 token

表现:同一段文字里个别字词重复出现,如「我们可以我们可以用一个」。

成因:增量计算错误。上游某些实现返回的是累计文本而不是增量 delta,网关如果按「差量」处理,就会把已输出过的内容再输出一次;反之则会丢字。

定位方法:

  1. 用同一个 prompt 分别走流式和非流式,比对最终文本是否一致;
  2. 非流式正确、流式重复 → 确认是网关的分块处理问题;
  3. 换一个上游模型测试 → 若只有某个模型出问题,说明是「该上游的格式适配」没做对。

结论:这是网关实现缺陷,不是模型问题。同一家站的其他模型可能正常,可以只避开出问题的那个。

异常二:中文或 emoji 被切坏(出现乱码或问号)

表现:输出里出现 ?、�(替换字符),或中文被拆成两半。

成因:字节边界与字符边界不对齐。SSE 的分块是按字节来的,一个 UTF-8 汉字占 3 字节、emoji 占 4 字节,完全可能被切在两个 chunk 之间。如果网关在拼接时用了按字节切分的逻辑(或者在中途做了 substr),就会切断多字节字符。

定位方法:

  1. 让模型输出一段中文 + emoji + 代码块的混合内容;
  2. 观察是否只在特定位置出现乱码(切坏的地方通常是固定的几个位置,因为分块策略是确定的);
  3. 用 curl --no-buffer 直接看原始 SSE 流,确认是网关输出就已损坏,还是你的客户端解析有问题。

结论:网关的多字节处理 bug。这类问题属于低级实现错误,出现它说明该站的流式适配没有认真测试过。

异常三:缺少结束标记或缺少 [DONE]

表现:客户端一直等待,不结束;或客户端报「流意外结束」。

成因:两种 —— 网关只转发了 data: 行而丢掉了 data: [DONE];或上游用了不同的事件结束方式(Anthropic 是 message_stop 事件),网关没有把它转换成客户端的 [DONE]。

定位方法:curl -N 抓原始流,看最后一个 chunk 是什么。以 OpenAI 协议为例,正常流必须以 data: [DONE] 结束。

结论:协议转换不完整。如果你的客户端依赖结束标记来做后续处理(比如自动保存),这个问题会直接破坏功能。

异常四:首字延迟(TTFT)远高于非流式的平均延迟

表现:流式反而比非流式更慢,第一个字要等很久。

成因:网关可能在做请求缓冲(先收完上游响应再转发),或者在做前置的鉴权 / 计费 / 路由查询且这些查询很慢。

定位方法:

  1. 分别测流式与非流式的首字时间;
  2. 流式首字 ≈ 非流式总耗时 → 基本可以确定它在缓冲,说明「流式」只是接口形态,没有真正流式转发。

结论:这属于功能性缺失。对交互式场景(编程补全、对话)影响很大。可以用本站监测页的延迟数据配合判断,但注意本站测的是首页可达性,不等于生成首字延迟。

异常五:中途静默中断

表现:输出到一半停止,没有报错,连接关闭。

成因:常见三种:

  • 上游超时(网关的连接超时设置比上游的生成时间短);
  • 网关有单请求时长上限,到点断开;
  • 长输出触发了网关的缓冲区限制。

定位方法:

  1. 用「要求输出 3000 字以上」的长任务测试;
  2. 记录断开时已经输出了多久 —— 如果是固定时长(如恰好 60s),基本可以确定是网关的超时配置;
  3. 检查你的客户端自己的读超时(很多 HTTP 客户端默认 30s)。

结论:先排除自己的客户端超时,再看是不是网关的时长上限。长输出场景(生成报告、批量代码)对这项敏感。

异常六:声明支持流式,实际返回非流式格式

表现:请求里带了 "stream": true,返回的却是一个完整的 JSON 对象。

成因:网关忽略了这个参数,或者它只是把它透传给了一个不支持流式的上游。

定位方法:看响应的 Content-Type —— 流式应为 text/event-stream,非流式是 application/json。再配合超时行为判断。

结论:属于参数静默丢弃,是最需要警惕的一类 —— 它不报错,只让表现变差,容易长期不被发现。

一份 5 分钟的流式体检

按顺序做,一次覆盖上面六类:

# 1) 抓原始流,看格式与结束标记
curl -N -s https://<base_url>/v1/chat/completions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"model":"<model>","stream":true,
       "messages":[{"role":"user",
       "content":"输出一段包含中文、emoji 😀 和一段 python 代码的示例,不少于 800 字"}]}'

看四件事:

  1. 每个 chunk 是否是合法的 data: {...};
  2. 是否以 data: [DONE] 结束;
  3. 中文与 emoji 是否完整;
  4. 输出长度与连续性(有无重复或跳跃)。

再和非流式跑一遍同一个 prompt,比最终文本是否一致。

小结

流式的六类异常里,只有一类(异常四的部分情况)可能与上游有关,其余基本都是网关实现问题。所以:如果一家站的流式表现有问题,直接判定它的实现水平不足,不必再花时间找原因。

反过来说,流式表现良好是一个相当强的正面信号 —— 它说明这家站至少认真测试过自己的协议转换层。

这篇文章对你有帮助吗?如果你在实际使用中发现了文中没提到的情况,欢迎 提交纠错或补充,我们会核验后更新到正文里。

相关文章

视频生成接口进中转:三种形态、四个计量陷阱,以及一份验收清单

2026-10-19

MCP 经中转站:哪些能通、哪些一定不通,以及怎么在十分钟内测出来

2026-10-19

中转站选型决策树:从你的场景倒推到站点

2026-10-07

日志与对账:把 token 消耗算到项目维度

2026-10-06

灰度切换供应商:不中断业务地换掉一家 API 站

2026-10-06

自建探针:二十行脚本监控你的 API 供应商

2026-10-06

顺着看下去:本站收录的部分中转站

本文没有指向特定模型系列,下面是本站收录站点中综合评分靠前的几家,供你顺着看下去。排序依据是评分与可用率,不构成推荐。

完整清单见 中转站导航,或按 模型系列 浏览。