首页/新闻资讯/正文详情

FastAPI SSE 流式推送完整指南:从 AI 逐字输出到断线自动续传

发布时间:2026/11/13 12:09:33 来源:云帆数科 栏目:资讯中心
FastAPI SSE 流式推送完整指南:从 AI 逐字输出到断线自动续传
FastAPI SSE 流式推送完整指南从 AI 逐字输出到断线自动续传【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi让 AI 的回答像打字机一样逐字蹦出来而不是让用户盯着转圈 30 秒后砰地弹出一整块文字——这是 SSEServer-Sent Events流式推送最直观的用法。FastAPI 0.135.0 内置了EventSourceResponse配合yield就能把任意接口改造成text/event-stream实时流。下面按先跑通 → 接前端 → 生产加固 → 避坑的工程路径走一遍。先跑通最小 SSE 端点 3 步搭好想象一家餐厅SSE 的思路是做好一道上一道而不是等所有菜做完再一次性端上桌。数据在循环里现算现发客户端边收边渲染。一个把回答逐 token 吐出去的最小端点只有三件事要做声明response_class、在端点里yield、给返回类型加上标注。from collections.abc import AsyncIterable from fastapi import FastAPI from fastapi.sse import EventSourceResponse from pydantic import BaseModel app FastAPI() class Token(BaseModel): text: str finish: bool False app.get(/chat/stream, response_classEventSourceResponse) async def stream_answer() - AsyncIterable[Token]: for ch in SSE 让 AI 回答逐字送达: yield Token(textch) yield Token(text, finishTrue)三步拆解response_classEventSourceResponse从fastapi.sse导入。路由层检测到生成器端点 这个响应类的组合后会把端点标记为 SSE 流判断逻辑在 fastapi/routing.py响应头自动带上Content-Type: text/event-stream。yield每一项每个产出项都会被编码成 SSE 报文的data:字段发出去。标注AsyncIterable[Token]这是收益最大的一步。返回类型标注带来三个好处Pydantic 逐项校验不符合Token结构的产出会在校验阶段直接报ResponseValidationError而不是带病上线类型化序列化走model_dump_json快速路径比兜底编码更快OpenAPI 文档完整/docs里能看到该端点的text/event-stream媒体类型与单项 schemaitemSchema前端同学可以直接照着写消费代码。另外两种写法端点写法返回标注说明async defyieldAsyncIterable[Token]推荐写法校验 文档全开同步defyieldIterable[Token]端点被放进线程池迭代不会阻塞事件循环收益相同省略返回标注无每项走jsonable_encoder兜底编码不逐项校验也不进 OpenAPI 单项 schema还有一个偷懒选项FastAPI(default_response_classEventSourceResponse)可以把 SSE 设为整个应用或某个APIRouter的默认响应类路由下所有生成器端点默认按 SSE 输出。完整可运行的示例在 docs_src/server_sent_events/。前端接流EventSource 开箱即用服务端发完浏览器端用原生EventSource就能接住不需要任何第三方协议库const es new EventSource(/chat/stream); es.onmessage (event) { // data 字段里是 JSON字符串会带引号所以先 parse const token JSON.parse(event.data); document.getElementById(answer).textContent token.text; if (token.finish) es.close(); }; es.onerror () { // 连接断开后浏览器会按 retry 间隔自动重连 // 且自动携带 Last-Event-ID 请求头见后文 };两个要点端点没指定event字段时浏览器统一派发到message事件即onmessage指定了event字段则要改用addEventListener下一节马上用到event.data里是 JSON 文本哪怕是纯字符串也带引号记得JSON.parse。到这里服务端发、前端收的闭环已经成立。精控事件event / id / retry / comment普通对象yield出去只会落在data:字段里。想控制 SSE 报文的其余字段就改为yield一个ServerSentEvent对象同样从fastapi.sse导入。以订单状态流转推送为例每次状态变化发一个带类型、带编号的事件并把重连等待时间设为 5 秒。from fastapi.sse import EventSourceResponse, ServerSentEvent class OrderStatus(BaseModel): order_id: str state: str app.get(/orders/{order_id}/events, response_classEventSourceResponse) async def stream_order_events(order_id: str) - AsyncIterable[ServerSentEvent]: for i, state in enumerate([paid, picking, shipped]): yield ServerSentEvent( dataOrderStatus(order_idorder_id, statestate), eventstatus_change, idstr(i 1), retry5000, )网络上传输的报文长这样事件之间以空行分隔event: status_change data: {order_id: SO-10086, state: paid} id: 1 retry: 5000 event: status_change data: {order_id: SO-10086, state: picking} id: 2 retry: 5000前端对应地按类型订阅es.addEventListener(status_change, (event) { const status JSON.parse(event.data); updateOrderBadge(status.order_id, status.state); });各字段速查模型定义见 fastapi/sse.py字段约束作用data任意可 JSON 序列化值事件负载总是JSON 编码——datahello线上是data: helloraw_data字符串原样写入data:字段、不做 JSON 编码与data互斥event单行事件类型名浏览器端对应addEventListener(event, ...)缺省则派发messageid单行、不含\0事件编号浏览器自动重连时以Last-Event-ID头回传retry非负整数毫秒告知浏览器断线后等多久再重连comment单行注释行线上以:开头客户端忽略常用作心跳注意这些约束是构造期校验event里塞换行、id里带\0、retry给负数或浮点数ServerSentEvent(...)那一行就会直接抛ValueError问题在写代码时暴露而不是在流到一半时。相关测试见 tests/test_sse.py。原样文本raw_data 与 [DONE] 哨兵值data的永远 JSON 编码是特性也是麻烦当你想发日志行、HTML 片段、CSV 行这类本来就是文本的东西时被加上 JSON 引号反而碍事。这时用raw_dataapp.get(/deploy/logs, response_classEventSourceResponse) async def stream_deploy_logs() - AsyncIterable[ServerSentEvent]: for line in [ [09:41:02] build image ok, [09:41:05] migrate db ok, [09:41:08] rolling update finished, ]: yield ServerSentEvent(raw_dataline)浏览器收到的是与原文一致的data: [09:41:02] build image ok没有多余引号。另一个高频用法是哨兵值流式 AI 接口常以data[DONE]作为本次生成结束的标记客户端收到该标记后停止等待。用raw_data[DONE]一行就能实现前端解析时先判断哨兵、再JSON.parse不会出错。记住一条红线data与raw_data互斥同一个事件两者都设会在构造时抛ValueError不存在同时发两份的可能。断线续传Last-Event-ID 怎么接EventSource的杀手锏是自动重连断线后浏览器按retry间隔重新请求并且把收到的最后一个id放进Last-Event-ID请求头。服务端只要读这个头就能从断点接着发而不是从头重播。以实时指标流为例给每个样本编上序号重连时跳过已发的部分from typing import Annotated from fastapi import Header app.get(/metrics/stream, response_classEventSourceResponse) async def stream_metrics( last_event_id: Annotated[int | None, Header()] None, ) - AsyncIterable[ServerSentEvent]: start last_event_id 1 if last_event_id is not None else 0 for i in range(100): if i start: continue yield ServerSentEvent( dataPoint(tsi * 5, cpu0.4 (i % 7) / 10), idstr(i), )三个关键点FastAPI 的Header()会把参数名last_event_id自动映射到请求头Last-Event-ID下划线转连字符不用手写request.headers每条事件必须带id浏览器才有值可回传生产环境里跳过已发项通常意味着按start游标查数据库或日志系统而不是靠内存列表——但协议层面就是上面这几行。配合前端零代码的自动重连你就得到一条断线自动补发、不重不漏的推送通道。生产加固心跳、缓存与代理缓冲三件套SSE 是长连接连接一直开着但没数据是最危险的状态。FastAPI 路由层已内置三个开箱即用的处理实现见 fastapi/routing.py 的 SSE 响应构建部分机制具体行为为什么需要空闲心跳生成器超过 15 秒无产出时自动插入注释报文: ping\n\n常量KEEPALIVE_COMMENT、间隔_PING_INTERVAL定义在 fastapi/sse.py代理和负载均衡器会掐断看起来死了的长连接心跳保活Cache-Control: no-cache显式写入响应头防止中间缓存对实时流做缓存导致客户端拿到旧数据X-Accel-Buffering: no显式写入响应头关闭 Nginx 等反向代理对该流的缓冲数据即时透传实现上路由层用anyio内存对象流把生成器迭代和心跳插入拆成两个任务生产任务从生成器拉取并序列化事件转发任务用超时包裹接收操作一旦空闲超时就把心跳注释插进字节流——这样即使同步def端点在跑线程池心跳也不会被阻塞的__next__卡住。生产产出足够快时不会误发心跳这套行为在 tests/test_sse.py 里有专门的测试覆盖。你不需要写任何代码来获得这三个保障只需要在部署后验证一下用curl -i看到这三个头都在就算合格。进阶SSE over POST 与 MCPSSE 不挑 HTTP 方法——EventSourceResponse对GET、POST等都生效。这一点在对接 MCP 这类协议时尤其重要它们正是通过POST承载 SSE 流的。一个接收 Prompt、按词回吐 token、末尾发结束标记的 POST 流式接口class Prompt(BaseModel): text: str app.post(/chat/stream, response_classEventSourceResponse) async def stream_chat(prompt: Prompt) - AsyncIterable[ServerSentEvent]: for word in prompt.text.split(): yield ServerSentEvent(dataword, eventtoken) yield ServerSentEvent(raw_data[DONE], eventdone)注意前端的限制浏览器原生EventSource只支持GET且不能带自定义请求头。因此 POST 场景以及需要携带鉴权头的场景要换用基于fetch的 SSE 客户端库逐行解析text/event-stream——这也是 MCP 客户端的做法。另外类型化 SSE 端点在 OpenAPI 文档里会完整呈现text/event-stream媒体类型与单项 schema配合客户端生成工具可以直接产出带流式解析的调用代码。避坑与调试清单上线前把这几条过一遍能省下大量排查时间用curl -N观测流-N等价于--no-buffer关闭 curl 自身的输出缓冲否则你会看到数据攒一堆才吐误以为是服务端问题。加-i可以顺便核对Cache-Control与X-Accel-Buffering两个头。curl -i -N http://127.0.0.1:8000/metrics/stream数据一次性吐出几乎总是代理缓冲。先确认X-Accel-Buffering: no在响应头里若还有 CDN/网关层需要在其配置中显式关闭缓冲或放行text/event-stream。收到的字符串带引号这不是 bug是data字段的 JSON 编码行为要原文就用raw_data。构造期报错retry-1、多行event、含\0的id都会在ServerSentEvent(...)处立即抛ValueError——这是设计如此别去修它修数据。Swagger UI 里看不到流/docs的测试面板不适合观测长流curl或浏览器控制台new EventSource(...)才是标准姿势。EventSource无法带鉴权头原生 API 发不了自定义Authorization用 Cookie、query 参数或 POST fetch客户端绕过。同步def端点里的阻塞调用心跳注入不依赖线程池但阻塞会拖慢数据产出长时间卡在一次yield之间只会看到心跳、看不到数据。选型与延伸阅读一张表划清边界需求选型服务器 → 浏览器单向文本流要自动重连SSEEventSourceResponse浏览器与服务器双向实时通信聊天输入、协作编辑WebSocket服务到服务的逐行 JSON 文本流Stream JSON Lines流式传输任意/二进制数据音视频Stream Data 进阶指南延伸阅读均在当前仓库内核心实现fastapi/sse.pyServerSentEvent模型、format_sse_event线上格式拼装、心跳常量路由层序列化与心跳注入fastapi/routing.py全部可运行示例docs_src/server_sent_events/行为测试tests/test_sse.py通用编码兜底jsonable_encoderencoder 教程把最小端点 前端 EventSource当作骨架ServerSentEvent各字段当作精细调节旋钮Last-Event-ID当作可靠性保险再加上默认自带的心跳与防缓冲头——一个能扛生产的 FastAPI SSE 流式推送接口就是这四件事。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Weex WebView 落地指南:从加载 H5 到双向通信的完整流程
Weex WebView 落地指南:从加载 H5 到双向通信的完整流程

Weex WebView 落地指南:从加载 H5 到双向通信的完整流程 【免费下载链接】weex A framework for building Mobile cross-platform UI 项目地址: https://gitcode.com/gh_mirrors/we/weex 原生页面已经搭好了,但运营希望活动页用 H5 动态下发&… · 2026/11/2 5:02:56

从30万亿 Token 到开放真实业务:一家硬件公司的 AI 底气
从30万亿 Token 到开放真实业务:一家硬件公司的 AI 底气

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 9:44:57

谷歌浏览器国内下载地址_chrome官网
谷歌浏览器国内下载地址_chrome官网

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 8:03:16

上海特种工操作证被查怎么查电子证书?手把手教你避坑
上海特种工操作证被查怎么查电子证书?手把手教你避坑

上海特种工操作证被查怎么查电子证书?手把手教你避坑 你是不是也遇到过这种情况?不知道去哪报名怕被中介坑,结果还被查出证有问题,整个人都不好了。特别是最近 上海特种工操作证被查 的新闻越来越多,很多人都开始慌了。其实,只要掌握了正确的方法,… · 2026/11/13 12:09:21

电工证哪里报名更靠谱千万别踩坑
电工证哪里报名更靠谱千万别踩坑

电工证哪里报名更靠谱千万别踩坑 怕考不过白交培训费?这年头考个电工证都不容易,稍不留神就掉进培训机构的坑里, 千万别踩坑 ,别等到出事才知道后悔。 电工证到底值不值得考? 如果你是建筑工地、水电安装、维修电工等行业从业者, 电工证 几乎是… · 2026/11/13 12:09:21

高压电工作业人数法规最新变化:电子证书怎么转,外省证能用吗?
高压电工作业人数法规最新变化:电子证书怎么转,外省证能用吗?

高压电工作业人数法规最新变化:电子证书怎么转,外省证能用吗? 之前考的证在外省能不能转过来?这几乎是每个在外地工作、想把证书“搬”回来的人最头疼的问题。最近不少朋友私信问,说在河南安阳干工程的,之前在别处考的高压电工作业证,现在能不能直接用… · 2026/11/13 12:09:21

霍城高级电工证考试通过率揭秘:外省证能转吗?别再踩坑了
霍城高级电工证考试通过率揭秘:外省证能转吗?别再踩坑了

霍城高级电工证考试通过率揭秘:外省证能转吗?别再踩坑了 之前考的证在外省能不能转过来?这是很多持证人问过的问题,特别是像你这种在霍城从事电工工作的朋友,可能之前在别处考过证,现在想回来发展或者换工作,就想知道怎么把证书转过来。今天咱们就来揭… · 2026/11/13 12:09:21

常德市哪里考电工证多少钱?学历不高也能轻松拿下
常德市哪里考电工证多少钱?学历不高也能轻松拿下

常德市哪里考电工证多少钱?学历不高也能轻松拿下 你是不是还在担心自己学历不高,考不了电工证?别急, 常德市哪里考电工证 这个问题其实并不难解决。 多少钱… · 2026/11/13 12:09:21

电工证过期了怎么续考,含金量还在吗?工地太忙根本没时间复习考试
电工证过期了怎么续考,含金量还在吗?工地太忙根本没时间复习考试

电工证过期了怎么续考,含金量还在吗?工地太忙根本没时间复习考试 工地太忙根本没时间复习考试,手里那本电工证眼看就要到期了,你是不是也愁得睡不着?别急,今天就把 电工证过期了怎么续考… · 2026/11/13 12:08:20

电工证丢失还能补吗?千万别踩坑,丢了证等于失业
电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/12 14:09:01

电力电缆作业证直播报名入口与办理流程良心建议
电力电缆作业证直播报名入口与办理流程良心建议

电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/13 5:40:45

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/12 23:27:43

维修电公用考电工证吗 在哪考最靠谱
维修电公用考电工证吗 在哪考最靠谱

维修电公用考电工证吗 在哪考最靠谱 工地太忙根本没时间复习考试,你是维修电工,天天在项目上跑,连抽个空背个题都难。那问题来了—— 维修电公用考电工证吗 ?答案是: 必须考 。尤其是在当前施工行业,没有电工证,连进场都可能被拦下。而且,… · 2026/11/13 0:00:08

电工证是不是可以登高?含金量和证书范围你必须知道的事
电工证是不是可以登高?含金量和证书范围你必须知道的事

电工证是不是可以登高?含金量和证书范围你必须知道的事 证书过期了不知道怎么复审延期,这事儿很多人遇到过,尤其是像你这样在郑州金水区做劳务班组负责人,手里握着几十个工人的证书,稍微一疏忽,就可能影响工程进度和公司信誉。特别是电工证是不是可以登… · 2026/11/13 0:00:08

鸡西电工证哪家下证快官方报名入口怎么找
鸡西电工证哪家下证快官方报名入口怎么找

鸡西电工证哪家下证快官方报名入口怎么找 你是不是也担心 学历不高怕报不上名 ?别急,今天我就来跟你说说, 鸡西电工证哪家下证快 ,还有 官方报名入口 到底怎么找,别让那些“代办”“代考”耽误了你的机会。… · 2026/11/13 0:00:08

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:12:21

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:11:51

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/12 21:15:21

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码