还在用WebSocket做LLM流式传输?FastAPI + SSE让你少踩一半坑

SSE 客户端 服务器 流式 WebSocket
发布于 2026-06-12
138

我们非常重视原创文章,为尊重知识产权并避免潜在的版权问题,我们在此提供文章的摘要供您初步了解。如果您想要查阅更为详尽的内容,访问作者的公众号页面获取完整文章。

扫码阅读
手机扫码阅读

文章主旨:

对于服务器向客户端单向推送(如LLM流式输出、实时通知)的场景,Server-Sent Events(SSE)比WebSocket更简单、稳定且易于部署,是隐藏的“王者”方案。

关键要点:

  • SSE基于HTTP协议,浏览器原生支持自动重连,无需复杂连接管理;而WebSocket需手动处理握手、重连和代理拦截等问题。
  • FastAPI的StreamingResponse配合异步生成器可轻松实现SSE流式传输,关键包括格式组装、心跳检测、客户端断开检测及代理缓冲控制。
  • 生产环境需注意代理缓冲(关闭缓冲或设置X-Accel-Buffering: no)、超时(心跳维持)、多进程状态共享(用Redis等中央消息总线)以及HTTP/2连接数限制。
  • SSE适用于LLM token流式输出、实时通知、仪表盘数据更新等单向推送场景;双向通信如聊天、游戏则仍推荐WebSocket。
  • 性能优化方面:使用ASGI服务器、适当调高文件描述符限制、启用gzip压缩、批量发送高频事件、正确释放资源。

内容结构:

一、引言:WebSocket的痛点与SSE的优势

指出使用WebSocket做LLM流式传输时常遇到连接升级、负载均衡配置、代理拦截、断线重连等问题,而SSE基于普通HTTP,浏览器原生支持,自动重连,让部署架构回归简单。

二、SSE的定义与类比

用外卖订单比喻:WebSocket是双向电话,SSE是单向订单状态推送。SSE是HTML5标准,通过HTTP连接服务器推送数据,客户端用EventSource监听。对比了长轮询、SSE、WebSocket的特性(方向、协议、浏览器支持、自动重连、穿透性、适用场景)。

三、FastAPI + SSE实战:流式输出LLM token

环境准备:Python 3.10+,FastAPI 0.115+,Uvicorn。核心实现:StreamingResponse + 异步生成器,按SSE协议格式组装消息(event, data, id等)。代码展示了模拟LLM流式生成、心跳注释行、客户端断开检测、错误处理、以及重要响应头(Cache-Control, Connection, X-Accel-Buffering)。

四、浏览器客户端

使用原生EventSource监听事件,无需第三方库。展示监听tokendoneerror事件的代码。自动重连由浏览器处理,若服务器发送id字段,重连时会带上Last-Event-ID实现断点续传。

五、扩展思考:基于Redis Pub/Sub的广播通知

架构:后台任务 -> Redis发布 -> FastAPI进程订阅 -> SSE推送给客户端。代码展示了订阅全局频道并逐条推送的event_stream生成器。注意多进程部署时需共享Redis,进程数不能太多,大规模可用Kafka/NATS替代。

六、生产环境避坑指南

  • 代理缓冲:通过X-Accel-Buffering: no或nginx配置proxy_buffering off解决。
  • 超时问题:发送心跳注释行(每15-30秒),并调整代理超时设置。
  • 客户端断开检测:必须使用request.is_disconnected()避免资源浪费。
  • 多进程共享状态:引入中央消息总线(Redis、Kafka)。
  • HTTP/2与连接数限制:使用HTTP/2或分散到不同子域名。
  • CORS与认证:配置CORS中间件,支持withCredentials发送cookie。

七、性能调优建议

使用ASGI服务器、调高文件描述符限制、启用gzip压缩(显式添加text/event-stream)、批量发送高频事件、避免内存泄漏(try…finally)。

八、核心回顾与总结

原理:SSE基于HTTP的text/event-stream和分块传输;实践:FastAPI + StreamingResponse;避坑:代理缓冲、超时、断开检测、多进程状态共享。最后强调技术选型应回归本质,SSE适合单向推送,WebSocket适合双向通信。

文章总结:

本文通过对比SSE与WebSocket、提供完整代码示例和避坑指南,强烈建议在LLM流式输出和实时通知等单向推送场景中优先采用SSE,因为它更简单、稳定,能显著降低生产环境维护成本。

数据STUDIO