当前位置: 首页 > news >正文

SSE (Server-Sent Events) 详解:比 WebSocket 更轻量的实时推送方案

🚀 SSE (Server-Sent Events) 详解:比 WebSocket 更轻量的实时推送方案

摘要:在 AI 流式输出、实时通知、数据监控等场景中,我们常需要服务器主动向客户端推送数据。除了大名鼎鼎的 WebSocket,还有一个被严重低估的“神器”——SSE。本文将带你彻底搞懂 SSE 的原理、协议格式、代码实战以及与 WebSocket 的选型对比。

一、 什么是 SSE?

SSE(Server-Sent Events,服务端推送事件)是一种基于 HTTP 协议的单向实时通信技术。它是 HTML5 规范的一部分,允许服务器向客户端持续发送文本数据流。

用一句话概括它的本质:
SSE = HTTP 长连接 + 文本事件流格式 + 浏览器原生自动重连

💡 核心特点

  • 单向通信:只能服务器 → 客户端(客户端发请求仍走普通 HTTP)
  • 基于 HTTP:无需协议升级,天然穿透防火墙/代理
  • 自动重连:浏览器EventSourceAPI 内置断线重连机制
  • 纯文本传输:数据格式为 UTF-8 文本,不支持二进制
  • 轻量级:无需引入第三方库,浏览器原生支持

二、 为什么需要 SSE?(痛点分析)

在没有 SSE 之前,实现"服务器推数据"通常有两种方式:

方案缺点
短轮询 (Polling)定时发请求,浪费带宽和 CPU,延迟高
长轮询 (Long Polling)每次收到数据后连接断开再重连,开销大
WebSocket双向通信能力强,但协议复杂、需额外部署、部分代理不友好

SSE 恰好填补了中间地带:当你只需要"服务器持续推数据给客户端"时,它比轮询高效得多,又比 WebSocket 简单得多。

🔥典型场景:ChatGPT 等 AI 对话的流式输出、股票行情推送、构建进度条、实时日志、消息通知

三、 工作原理与协议格式

3.1 通信流程

客户端 服务器 | | |--- GET /events -------------->| | Accept: text/event-stream | | | |<-- 200 OK -------------------| | Content-Type: text/event-stream | Cache-Control: no-cache | | | |<-- data: {"msg":"hello"} ----| ← 第一条数据 |<-- data: {"msg":"world"} ----| ← 第二条数据 |<-- event: done --------------| ← 自定义事件 |<-- data: [DONE] -------------| | ...连接保持打开... |

3.2 SSE 数据格式(重要!)

SSE 是纯文本协议,每条消息由以下字段组成(以\n\n分隔多条消息):

字段必填说明
data:消息内容,多行数据每行都以data:开头
event:事件名称,默认为message
id:消息ID,用于断线重连时告诉服务器上次收到的位置
retry:重连等待时间(毫秒)

示例原始响应体:

id: 1 event: update data: {"temperature": 26.5} data: 这是一条普通消息 event: done data: [DONE]

四、 代码实战

4.1 前端(浏览器原生 API)

constsource=newEventSource('/api/stream');// 默认 message 事件source.onmessage=(e)=>{console.log('收到数据:',e.data);};// 自定义事件监听source.addEventListener('update',(e)=>{console.log('更新事件:',JSON.parse(e.data));});// 错误处理 & 自动重连source.onerror=(e)=>{console.log('连接异常,浏览器将自动重连...',e);// 如需手动关闭:source.close()};

4.2 后端(Node.js / Express 示例)

app.get('/api/stream',(req,res)=>{// ⚠️ 关键响应头res.setHeader('Content-Type','text/event-stream');res.setHeader('Cache-Control','no-cache');res.setHeader('Connection','keep-alive');letcount=0;consttimer=setInterval(()=>{res.write(`data:${JSON.stringify({count:++count})}\n\n`);if(count>=10){clearInterval(timer);res.write('event: done\ndata: [DONE]\n\n');res.end();}},1000);req.on('close',()=>clearInterval(timer));});

4.3 Python FastAPI 示例(AI 流式输出常用)

fromfastapi.responsesimportStreamingResponseimportasyncio,jsonasyncdefevent_generator():foriinrange(10):yieldf"data:{json.dumps({'token':f'word_{i}'})}\n\n"awaitasyncio.sleep(0.5)yield"data: [DONE]\n\n"@app.get("/chat/stream")asyncdefchat_stream():returnStreamingResponse(event_generator(),media_type="text/event-stream")

五、 SSE vs WebSocket 选型指南

维度SSEWebSocket
通信方向单向(服务器→客户端)双向
协议HTTPWS/WSS
数据格式纯文本文本 + 二进制
自动重连✅ 浏览器内置❌ 需手动实现
实现复杂度⭐ 极低⭐⭐⭐ 较高
代理/防火墙兼容✅ 优秀⚠️ 可能被拦截
连接数限制同域最多 6 个(HTTP/1.1)无此限制
适用场景AI流式输出、通知、监控聊天室、游戏、协同编辑

⚠️注意:HTTP/1.1 下浏览器对同一域名 SSE 连接数限制为 6 个。如果使用 HTTP/2+,此问题基本消除。生产环境强烈建议开启 HTTP/2

六、 常见坑与最佳实践

  1. Nginx 缓冲问题:Nginx 默认会缓冲响应,导致 SSE 数据延迟到达。务必添加:
    proxy_buffering off; proxy_cache off; X-Accel-Buffering: no; # 或在后端响应头中设置
  2. 跨域问题:SSE 遵循 CORS 规则,需正确配置Access-Control-Allow-Origin
  3. 认证问题EventSourceAPI不支持自定义 Header,无法传 Token。解决方案:
    • URL 参数传递 Token(注意安全)
    • Cookie 认证
    • 使用fetch+ReadableStream手动实现 SSE 客户端(推荐)
  4. 断点续传:善用id字段 +Last-Event-ID请求头,实现断线后从断点继续接收
  5. 不要滥用:如果需要频繁双向通信,请直接上 WebSocket

七、 总结

你的需求推荐方案
服务器单向推数据,快速落地SSE
AI 大模型流式对话SSE(业界标准)
实时聊天 / 多人协作 / 游戏WebSocket
低频数据同步短轮询 / 长轮询

SSE 不是 WebSocket 的替代品,而是互补品。在合适的场景选择合适的工具,才是架构设计的精髓。


📝笔记标签#SSE#Server-Sent-Events#实时通信#WebSocket#AI流式输出#前端#后端

如果这篇笔记对你有帮助,欢迎点赞收藏 ❤️ ~

http://www.rkmt.cn/news/1469103.html

相关文章:

  • 2026年入职转行网络安全,该如何进行职业规划?看这一篇就够
  • 2026国产超声波液位差计十大品牌综合实力全景测评 - 水质仪表品牌排行榜
  • Java 质数 (prime numbers) 算法实现
  • Veo 2额度用得快?不是你生成多,而是没关这1个默认开关(实测降低76%无效消耗)
  • 深圳艾景特科技:开发者猫叔如何打造面向中国市场的 AI 投研产品
  • 记录AAAAA
  • LeetCode 274 · H 指数:排序后一条规则搞定
  • 联想刃7000K终极BIOS解锁完整指南:简单三步释放硬件全部潜力
  • 某中学sql注入漏洞
  • 2026年东莞办公设备租赁配套服务商盘点:复印机/打印机/电脑租赁、整机组装与监控安装企业参考 - 海棠依旧大
  • 如何高效配置OpenCore引导器:PC运行macOS的完整方案指南
  • PoE网络变压器中共模扼流圈(CMC)的放置与磁饱和问题解析
  • VidDown:一个免费、本地优先的在线工具站(重点:视频解析下载)
  • Python信用评分卡终极指南:从零开始构建专业风险模型
  • Qt 6.0安装后第一件事:用Qt Creator创建你的第一个Hello World程序(Windows平台)
  • 如何用LibreSignage快速构建企业级数字标牌系统
  • 【每日一题】LeetCode 70. 爬楼梯 TypeScript
  • 光子晶体腔设计优化与水环境应用挑战
  • 2026年园艺工具品牌选购参考:绿植营养土、通用营养土、家用营养土、养花营养土、进口营养土、CPAI园艺产品综合梳理 - 海棠依旧大
  • 3分钟搞定Axure RP中文界面:新手也能快速上手的完整汉化教程
  • 2026年6月市面上评价高的消失模铸造件源头厂家推荐,保丽龙泡沫板/泡沫箱/消失模铸造件,消失模铸造件品牌找哪家 - 品牌推荐师
  • VMware虚机如何使用U盘
  • ThreadLocal 内存泄露?别慌,这锅双亲委派背得有点冤!附自愈方案
  • 2026 国内加速版 OpenClaw 安装,解决下载缓慢问题
  • Matlab实现偏置曲柄滑块机构运动学仿真:位移/速度/加速度曲线与误差分析
  • JTAG TAP状态机HDL实现与可观测调试实战
  • 抖音批量下载工具技术解析:从API破解到智能策略切换的架构设计
  • 2026年 缠绕模具厂家/折弯模具/方形模具/玻璃钢缠绕模具/电力设施模具最新推荐榜单:定制工艺与耐用口碑深度解析 - 品牌企业推荐师(官方)
  • 拥抱 Vibe Coding:重构一个现代化智能语音助手 (ClearVoice-ASR)
  • 终极Typora插件大全:62个免费功能增强工具完全指南