一、SSE协议基础解析
服务器推送事件(Server-Sent Events,SSE)是基于HTTP协议的轻量级服务器推送技术,相比WebSocket具有更简单的实现机制和更好的浏览器兼容性。其核心特性包括:
- 单向通信:仅支持服务器向客户端推送数据
- 事件流格式:采用
text/event-stream内容类型 - 自动重连:客户端自动处理网络中断后的重连
- 事件ID:支持断线续传的Last-Event-ID机制
协议数据格式由多个事件块组成,每个事件块包含:
event: eventType\nid: eventId\ndata: payload1\ndata: payload2\n\n
其中\n\n表示事件结束,浏览器会自动解析这些字段。
二、前端实现详解
1. 创建EventSource对象
const eventSource = new EventSource('/api/stream');
构造函数参数为服务器端点URL,浏览器会自动添加Accept: text/event-stream请求头。
2. 事件监听机制
// 默认消息事件eventSource.onmessage = (e) => {console.log('Received:', e.data);};// 自定义事件类型eventSource.addEventListener('notification', (e) => {const data = JSON.parse(e.data);renderNotification(data);});// 错误处理eventSource.onerror = (e) => {if (e.status === 401) {handleAuthError();} else {console.error('SSE Error:', e);}};
3. 完整生命周期管理
// 初始化连接function initSSE() {const eventSource = new EventSource('/api/stream', {withCredentials: true // 跨域时发送cookies});// 连接建立回调eventSource.addEventListener('open', () => {console.log('SSE Connection established');});// 返回关闭函数return () => {eventSource.close();console.log('SSE Connection closed');};}// 使用示例const closeSSE = initSSE();// 需要关闭时调用 closeSSE();
三、后端实现方案
1. Node.js实现示例
const http = require('http');http.createServer((req, res) => {if (req.url === '/api/stream') {res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive','Access-Control-Allow-Origin': '*' // 跨域配置});// 发送初始事件res.write('event: connect\n');res.write('data: {"status": "connected"}\n\n');// 模拟实时数据推送const interval = setInterval(() => {res.write(`data: ${new Date().toISOString()}\n\n`);// 客户端断开时清理if (res.finished) {clearInterval(interval);}}, 1000);req.on('close', () => {clearInterval(interval);res.end();});} else {res.writeHead(404);res.end();}}).listen(3000);
2. Java Spring Boot实现
@RestControllerpublic class SSEController {@GetMapping(path = "/api/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public SseEmitter handleStream() {SseEmitter emitter = new SseEmitter(30_000L); // 30秒超时ExecutorService executor = Executors.newSingleThreadExecutor();executor.execute(() -> {try {for (int i = 0; i < 10; i++) {SseEmitter.SseEventBuilder event = SseEmitter.event().data("Message " + i).id(String.valueOf(i)).name("notification");emitter.send(event);Thread.sleep(1000);}emitter.complete();} catch (Exception e) {emitter.completeWithError(e);} finally {executor.shutdown();}});return emitter;}}
3. 生产环境优化建议
- 心跳机制:每15-30秒发送注释行保持连接
// 后端心跳示例setInterval(() => {res.write(': heartbeat\n\n');}, 20000);
- 背压控制:监控客户端处理速度,避免消息堆积
- 重试策略:实现指数退避重连机制
- 安全配置:
- 添加CORS头
- 实现JWT认证
- 限制最大连接数
四、异常处理与调试技巧
1. 常见错误场景
- 401未授权:检查CORS和认证配置
- 204无内容:服务器未正确设置Content-Type
- 连接频繁断开:检查代理服务器超时设置
2. 调试工具推荐
- 浏览器开发者工具:
- Network面板查看SSE连接
- Application面板监控EventSource对象
- Postman:支持SSE流式响应查看
- Wireshark:分析底层TCP连接状态
3. 日志记录最佳实践
// 增强版错误处理eventSource.onerror = (e) => {const errorLog = {time: new Date().toISOString(),status: e.target.readyState,eventPhase: e.eventPhase,// 其他诊断信息...};fetch('/api/logs', {method: 'POST',body: JSON.stringify(errorLog)});};
五、性能优化方案
1. 连接复用策略
- 单页面应用保持单个SSE连接
- 多标签页共享连接(通过BroadcastChannel API)
2. 数据压缩优化
// Node.js压缩示例const zlib = require('zlib');const transformStream = new zlib.Deflate();res.writeHead(200, {'Content-Type': 'text/event-stream','Content-Encoding': 'deflate'});dataStream.pipe(transformStream).pipe(res);
3. 负载均衡配置
- 会话保持:确保请求路由到同一后端实例
- 超时设置:调整负载均衡器超时时间(建议>30秒)
- 健康检查:针对SSE端点定制健康检查逻辑
六、典型应用场景
- AI实时推理:推送模型推理中间结果
- 金融行情:实时股票价格更新
- 物联网监控:设备传感器数据流
- 社交应用:实时通知系统
- 协作编辑:文档实时同步
通过合理应用SSE协议,开发者可以构建出低延迟、高可靠的实时数据推送系统。相比WebSocket,SSE在实现复杂度、浏览器兼容性和安全性方面具有独特优势,特别适合需要简单服务器推送的业务场景。