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

Server-Sent Events(SSE)详解:轻量级服务端推送方案

适用场景:实时通知、AI 流式输出、日志监控、股票行情等 单向文本流推送
关键词:SSE、EventSource、服务端推送、流式响应、HTTP 长连接


一、什么是 SSE?

SSE(Server-Sent Events) 是一种基于 HTTP 的 单向服务器推送技术,允许服务端主动向浏览器客户端持续发送文本数据流。

  • 标准 Web API:浏览器原生支持 EventSource 对象
  • 自动重连:断开后自动尝试恢复连接
  • 轻量简单:比 WebSocket 更易实现,比轮询更高效
  • 仅支持文本:不能传输二进制数据
  • 单向通信:只能服务端 → 客户端(不能反向发)

💡 典型应用:ChatGPT 网页版早期流式回复、实时构建日志、系统状态推送


二、SSE vs 其他通信方式对比

特性SSEWebSocket轮询(Polling)
通信方向单向(服务端 → 客户端)双向客户端 → 服务端
协议HTTP/1.1ws/wss(独立协议)HTTP
实现复杂度⭐ 简单⭐⭐⭐ 复杂⭐ 简单
自动重连✅ 内置支持❌ 需手动实现N/A
二进制支持❌ 仅文本✅ 支持✅(但低效)
浏览器兼容IE 不支持,现代浏览器全支持现代浏览器支持全支持
适用场景实时通知、流式文本聊天、游戏、协作编辑简单状态同步

结论:若只需 服务端推文本,优先选 SSE!


三、SSE 工作原理

1. 客户端发起请求

const eventSource = new EventSource('/api/stream');

2. 服务端返回特殊响应头

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

3. 服务端持续发送消息(以 \n\n 结尾)

data: 消息1event: update
data: {"status":"running"}id: 1001
data: 带ID的消息retry: 5000
data: 重连间隔5秒

4. 客户端自动接收并触发事件


四、SSE 消息格式规范

每条消息由若干字段组成,必须以 \n\n 结尾

字段说明示例
data:消息内容(必填)data: hello
event:事件类型(可选,默认 messageevent: update
id:消息 ID(用于断线重连)id: 1001
retry:重连间隔(毫秒)retry: 3000

⚠️ 注意:

  • 每行以 \n 结尾;
  • 多行 data 会被拼接;
  • : 开头的行为注释(不触发事件),如 : ping\n\n

五、前端使用:EventSource API

基础用法

const es = new EventSource('/api/stream');// 默认事件(无 event 字段 或 event: message)
es.onmessage = (event) => {console.log('收到:', event.data);
};// 监听自定义事件
es.addEventListener('update', (event) => {const data = JSON.parse(event.data);console.log('状态更新:', data);
});// 连接建立
es.onopen = () => console.log('SSE 连接成功');// 错误处理(含自动重连失败)
es.onerror = (err) => console.error('SSE 错误:', err);// 手动关闭
es.close();

带认证的请求

⚠️ EventSource 不支持自定义请求头
解决方案:通过 URL 参数或 Cookie 传递 token

// 方式1:URL 参数
const es = new EventSource('/api/stream?token=xxx');// 方式2:同域 Cookie(自动携带)
const es = new EventSource('/api/stream');// 方式3:自定义客户端
自定义一个SSE客户端,自定定义数据协议// 方式4:使用现成的js库
event-source-polyfill
(https://www.npmjs.com/package/event-source-polyfill)

六、服务端实现示例

Node.js + Express

import express from 'express';
import cors from 'cors';const app = express();
app.use(cors({ origin: 'http://localhost:5173' }));app.get('/api/stream', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');res.setHeader('Cache-Control', 'no-cache');res.setHeader('Connection', 'keep-alive');res.flushHeaders(); // 立即发送响应头let count = 0;const interval = setInterval(() => {const msg = JSON.stringify({ time: new Date().toLocaleTimeString() });res.write(`event: update\ndata: ${msg}\n\n`);if (++count >= 5) {clearInterval(interval);res.end();}}, 1000);req.on('close', () => clearInterval(interval));
});app.listen(3000);

Python + Flask

from flask import Flask, Response
import json
import timeapp = Flask(__name__)@app.route('/stream')
def stream():def generate():for i in range(5):yield f"event: update\ndata: {json.dumps({'count': i})}\n\n"time.sleep(1)return Response(generate(), mimetype='text/event-stream')

七、Vue 3 中集成 SSE(Composition API)

<script setup>
import { ref, onUnmounted } from 'vue'const messages = ref([])
let es = nullconst connect = () => {es = new EventSource('/api/stream')es.onmessage = (e) => messages.value.push(e.data)es.addEventListener('update', (e) => {messages.value.push(JSON.parse(e.data))})es.onerror = () => {console.error('SSE 连接失败')es?.close()}
}onUnmounted(() => es?.close())
</script><template><button @click="connect">连接 SSE</button><div v-for="(msg, i) in messages" :key="i">{{ msg }}</div>
</template>

八、常见问题与解决方案

❌ 1. 跨域(CORS)被拦截

现象:请求失败,控制台报 CORS 错误
解决:服务端添加 CORS 头

app.use(cors({ origin: 'http://localhost:5173' }))

或使用 Vite 代理(开发环境):

// vite.config.ts
export default defineConfig({server: {proxy: {'/api': 'http://localhost:3000'}}
})

❌ 2. Safari 缓冲小 chunk

现象:消息延迟到达
解决:每条消息 ≥1KB,或加注释行:

res.write('data: small chunk\n\n');
res.write(': keep-alive\n\n'); // 注释行,不触发事件

❌ 3. require is not defined(Node.js ESM 错误)

原因:混用 importrequire
解决:统一使用 ES 模块

// package.json
{ "type": "module" }
// server.js
import express from 'express'; // ✅ 正确
// const express = require('express'); // ❌ 错误

九、最佳实践建议

场景建议
开发环境使用 Vite/Webpack 代理避免 CORS
生产环境Nginx 反向代理 + 后端 CORS
认证通过 URL 参数或 Cookie 传 token
消息格式使用 JSON,便于解析
错误处理监听 onerror,避免无限重连
资源清理组件卸载时调用 eventSource.close()

十、总结

SSE = 简单 + 高效 + 原生支持 的服务端推送方案。
当你需要 从服务端向浏览器持续推送文本数据 时,SSE 是比轮询更优、比 WebSocket 更轻量的选择。

记住三要素

  1. 服务端设置 Content-Type: text/event-stream
  2. 消息格式符合 SSE 规范(data: + \n\n
  3. 前端用 EventSource 监听事件

📚 延伸阅读

  • MDN: Server-Sent Events
  • HTML Standard: EventSource
http://www.dtcms.com/a/609800.html

相关文章:

  • Ubuntu 下 PostgreSQL 安装与配置完整指南
  • UCOS-III笔记(七)
  • DDR4系列之ECC功能(六)
  • [Linux——Lesson25.线程:生产与消费者模型]
  • JavaScript while 循环
  • OceanBase分区基础知识
  • 网站如何做备份wordpress文章列分页
  • 制作一个网站需要多久wordpress地址怎么打开
  • vscode如何使用git
  • 建好网站后如何向里面加东西威海那家做网站好
  • 银河麒麟桌面操作系统的安装部署与常规使用
  • 【软考 CPU主频】外频、倍频
  • NebulaChat项目构建笔记
  • Socket:TCP/UDP通信详解
  • QT opencv实现高拍仪场景识别物体轮廓的案例详解
  • 广水住房和城乡建设部网站舟山网站建设开发
  • 深度学习打卡第R4周:LSTM-火灾温度预测
  • 最好的营销策划公司做seo网站优化价格
  • 通过Rust高性能异步网络服务器的实现看Rust语言的核心优势
  • 第36节:AI集成与3D场景中的智能NPC
  • 一个基于 LayUI + .NET 开源、轻量的医院住院管理系统
  • StarRocks 4.0:让 Apache Iceberg 数据真正 Query-Ready
  • 网站建设 自己的服务器爬虫python入门
  • android抽屉DrawerLayout在2025的沉浸式兼容
  • 美颜SDK性能优化实战:GPU加速与AI人脸美型的融合开发
  • AndroidStudio历史版本下载
  • Mac抹除重装卡在激活锁?两步快速解锁
  • Java语言是编译型还是解释型| 探究Java的运行机制与性能优化
  • 网站发语音功能如何做广州比较好的网站建设公司
  • 公司网站域名更改怎么做建设行业协会网站发展的建议