前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9654
  • Safari 空白页如何卡住 MCP 权限校验
  • 会议录音应用的说话人识别与检索踩坑
  • 给 AI 产品文档加一道事实校验关
  • 防止 Agent 靠修改测试制造假通过
  • 故意破坏代码,揭穿回归检查的假绿灯
  • 模型版本变了,评测分差就不能直接比较
  • JetBrains 版 Copilot 增强模型与 MCP 管理
  • 点选界面元素,把修改需求送到对应 Agent
  • 跨公司 Agent 协商,用代码落实数据契约
  • 代码送入远程模型前先做数据分级
  • 把 Agent 权限约束落实到执行层
  • 模型评测暴露环境破坏与联网绕限制行为
  • 微软Decision-1主攻低延迟分类与路由
  • 腾讯元器停服,智能体业务需限期迁移
  • Anthropic暂停全部内部评测联网
  • 模型单价相同,任务成本仍可差近一倍
  • 测 LLM 接口延迟,别只报平均数
  • 用 TypeScript 拦住格式正确的错误数据
  • 微软在 Foundry 推出 Qwen 决策模型
  • 大模型故障切换也要守住能力边界
  • 弱网下如何保住大模型流式响应
  • 用 CI 硬约束控制 AI 代码膨胀
  • Agent 上线前,先验证工具权限边界
  • steadysdk 降低接口客户端再生成风险
  • 生产 Agent 的权限不能照搬人类账号
  • 递归生成可验证的终端 Agent 难题
  • 用缺陷风险排序分配代码审查预算
  • 用真实几何验证模型修复代码的能力
  • 用 Hooks 强制执行 AI 编码质量检查
  • TeamAI 用 Git 同步团队 Agent 配置
  • 为编码助手补充 SwiftUI 开发规范
  • LiteLLM 统一多家模型接口与调用治理
  • 20 个编程智能体并行,构建缓存成关键
  • 按用途配置 AI 爬虫访问规则
  • TFD-Bench 用多轮测试反馈评估编程智能体
  • Clef-omni用单次调用完成多模态决策
  • 让AI先复现故障,再用证据定位根因
  • 微软推出面向Agent控制的概率评分模型
  • Stepfork 将智能体故障变成回归测试
  • Claude 托管智能体支持千路并行协作
  • 用程序校验揭穿Agent评测假成功
  • 用小型本地模型压测桌面编程 Agent
  • Drex 1.5 开源,以单次推理为选项评分
  • 双栏论文解析错序,先用版面几何修复
  • ML Drift统一多平台端侧GPU计算
  • 单台虚拟机搭建 Claude 多代理工作流
  • 用父提交对照区分测试波动与回归
  • Saluki 将 27B 智能体模型压至 7.89GB
  • 通义图像 Turbo 将去噪压至 8 步
  • OpenAI 新 API 面向概率与评分输出
  • AI 编程提速为何卡在人工审查
  • 已加载 51 / 9654
8.0
热点
AI SCORE
技术实践2026-10-10 19:51

弱网下如何保住大模型流式响应

dev.to · AI#流式响应#SSE#弱网
Editor brief · 编辑速览

将模型生成直接绑定 HTTP 断连取消,会让短暂网络故障终止已付费的生成,并在重连时重新发起请求。文章建议拆分生成启动与 SSE 订阅,通过流 ID 管理任务,并由清理机制处理长期无人订阅的生成。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

你的聊天 UI 在办公室 Wi-Fi 下看起来一切正常。可一旦有人在火车上使用,SSE 连接在一句话说到一半时断开,回答就可能从头开始,或者模型继续消耗 token,却已经没人接收。同一个功能,换个网络,表现就完全不同。

我花了一段时间,把一个“演示时能用”的流式功能改造成能够应对断线重连的实现。完整的可运行项目放在 Tech Skill Builder,包含 ASP.NET Core 10、TypedResults.ServerSentEvents 和测试。这篇文章是一份简短的检查清单:我反复看到的五个错误,以及对应的解决方案。

错误 1:把生成过程绑定到 HTTP 请求

花五分钟搭出来的版本,通常会把 GetStreamingResponseAsync 绑定到 HttpContext.RequestAborted。关闭标签页,模型调用就停止了。这看起来挺省钱,直到你发现不稳定的代理也会触发同样的行为:每一次短暂断线,都会取消你已经付费执行的工作,而重连又会发起一个新的 prompt。

解决办法:把启动生成和订阅拆开。

POST /api/chat/streams 在 registry 中启动生成,返回 202,以及 streamId、eventsUrl、cancelUrl。

GET /api/chat/streams/{id}/events 用于订阅 SSE。

即使订阅者断开连接,生成仍会继续运行,直到 sweeper 判定已经没人关心这个回答。

// POST /api/chat/streams
var stream = registry.TryStart(messages, owner);
return TypedResults.Accepted(
    $"/api/chat/streams/{stream.Id}/events",
    new StreamStarted(stream.Id, eventsUrl, cancelUrl));

// GET /api/chat/streams/{id}/events
// Last-Event-ID header (or ?lastEventId=) → replay missed events
return TypedResults.ServerSentEvents(
    StreamSubscriber.ReadAsync(stream, after, options, time, http.RequestAborted));
// full implementation in the complete project

EventSource 只支持 GET。仅这一点,就足以推动你采用这种拆分方式:重连时,你无法通过 POST 发送请求体。

错误 2:没有序列 ID,重连就意味着“从头再来”

如果每个 SSE 事件都没有 id:,浏览器就没有可放进 Last-Event-ID 的值。你的客户端要么重复显示 token,要么要求服务端重新生成。

解决办法:为每个回答维护一个只追加的 StreamLog。每个事件都分配一个序列号。订阅时,解析 Last-Event-ID,然后只重放错过的事件。缓冲区要有容量上限;如果客户端回来得太晚,就发送一个包含当前全部文本的快照,而不是逐条发送那些已经被清除的增量事件。

public long Append(ChatStreamEvent e)
{
    // assign next sequence, store event, wake waiters
    // if over capacity → trim oldest; keep aggregated text for snapshots
    // full implementation in the complete project
}

如果流已经结束,客户端也已经接收完全部事件呢?返回 204 No Content。这是 SSE 规范规定的做法,可以阻止 EventSource 无休止地重连。

错误 3:把服务端事件命名为 error

遇到连接问题时,浏览器会触发 EventSource 自身的 error。如果你的消息也使用 event: error,这两种错误就会被混为一谈,而且往往还会进入同一个处理函数。你会花上比预期更多的时间排查:“到底是模型出问题了,还是 Wi-Fi 出问题了?”

解决办法:使用一组精简、朴素的事件名称。

把失败事件命名为 failed,而不是 error。在消息中放入一条适合展示给用户的提示,以及一个 errorId。已经生成的部分文本继续保留在屏幕上。

错误 4:流长时间没有消息,也没有停止按钮

代理和负载均衡器很容易处理掉空闲连接。当模型在思考,或者工具正在执行时,你的 SSE 可能长时间没有消息,最终被断开。另一方面,用户点击“停止”,也会期待计费随之停止。如果取消操作只是关闭浏览器这一侧的连接,服务端可能还在继续生成。

工作进行期间,定时发送 heartbeat,例如每 15 秒一次。

提供 POST /api/chat/streams/{id}/cancel,取消模型调用,并以 done / finishReason: cancelled 结束。

发送 X-Accel-Buffering: no,避免 nginx 把整个流缓冲成一大块数据后才发出去。

// Cancel endpoint shape
if (registry.Find(id) is not { } stream || stream.Owner != owner)
    return TypedResults.NotFound();
return stream.RequestCancel()
    ? TypedResults.Accepted((string?)null)
    : TypedResults.Conflict(); // already finished
// full implementation in the complete project

错误 5:把“快速搭建”的流式实现直接用于生产环境

用 TypedResults.ServerSentEvents 包装一个原始的 token 循环,很适合做可行性验证。但它还算不上产品级 API。你没有断点续传,没有归属校验,没有对活跃流数量的限流,也没有支持多实例部署的方案。

在宣布完成之前,检查以下事项:

  • [ ] POST 启动 + GET 订阅,兼容 EventSource
  • [ ] 序列 ID + Last-Event-ID 重放
  • [ ] 生成过程不随请求结束;由 sweeper 清理无人订阅的流
  • [ ] 事件名称避免与 EventSource 冲突,使用 failed,而不是 error
  • [ ] heartbeat + 取消端点
  • [ ] 绑定所属用户,使用 cookie 身份验证或签名 URL;EventSource 无法设置 Authorization
  • [ ] 横向扩容时,使用粘性会话或共享日志,例如 Redis Streams
  • [ ] 优先使用 HTTP/2 或 HTTP/3;在 HTTP/1.1 下,浏览器通常将每个域名的 SSE 连接数限制在约 6 个

这里有意省略的内容

完整项目包含 coalescer,用于批量合并细小的 token 片段;还包含 sweeper 的时间配置、无需密钥即可用于演示的离线流式模型,以及完整的测试套件。这篇文章提供的是地图,完整实现还需要你亲自走一遍。

如果你想获取可运行的源码和更深入的配套文章,可以到 Tech Skill Builder 获取。会员可获得完整的、支持断点续传的流式解决方案,直接通过 dotnet test 和 dotnet run 就能测试和运行。产品页面上提供限时会员价格;如果你正在开发任何向浏览器流式发送 token 的功能,这部分就是你应该在下一次网络不稳定的演示之前完成的工作。

网络不稳定并不是罕见情况。把断点续传当作功能的一部分,而不是收到第一张支持工单后才补上的修复。

如果还需要采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
大模型故障切换也要守住能力边界
下一篇
用 CI 硬约束控制 AI 代码膨胀