SSE 服务端推送

引言

Server-Sent Events (SSE) 是一种服务器推送技术,允许服务器向客户端实时推送数据。在以下场景特别有用:

  • 实时数据更新(如股票价格、天气信息)

  • 社交媒体信息流

  • 实时日志显示

  • 进度通知

Pasted image 20250402200626.png

SSE 的本质

SSE 本质上是基于 HTTP 协议的单向通信机制:

  • 使用 HTTP 长连接实现服务器到客户端的单向数据流

  • 数据格式为纯文本,编码必须是 UTF-8

  • 基于标准 HTTP 协议,无需特殊协议支持

SSE 的特点

  1. 单向通信:服务器到客户端的单向数据流

  2. 自动重连:断开后默认自动重连

  3. 简单易用:使用标准 HTTP,无需 WebSocket 的复杂配置

  4. 支持自定义事件

  5. 天然支持跨域(CORS)

SSE 客户端 API

基本使用示例:

javascript
const evtSource = new EventSource('/events');

// 监听消息
evtSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log(data);
};

// 监听连接打开
evtSource.onopen = function() {
    console.log('连接已建立');
};

// 监听错误
evtSource.onerror = function(err) {
    console.error('发生错误:', err);
};

// 监听自定义事件
evtSource.addEventListener('custom-event', function(e) {
    console.log('自定义事件:', e.data);
});

// 关闭连接
// evtSource.close();

SSE 服务端实现

数据格式

服务器发送的数据必须遵循特定格式:

  • 每条消息以 data: 开头

  • 每条消息以 \n\n 结尾

  • 支持多个字段:data、event、id、retry

data 字段

text
data: 消息内容\n\n

多行数据:

text
data: 第一行\n
data: 第二行\n\n

id 字段

用于消息标识,断线重连时会发送 Last-Event-ID 头:

text
id: 1\n
data: 消息内容\n\n

event 字段

用于指定事件类型:

text
event: custom-event\n
data: 消息内容\n\n

retry 字段

指定重连时间(毫秒):

text
retry: 10000\n
data: 消息内容\n\n

Node 服务器实例

javascript
const express = require('express');
const app = express();

app.get('/events', (req, res) => {
    // 设置 SSE 所需的 headers
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });

    // 发送初始数据
    res.write('data: 连接已建立\n\n');

    // 定时发送数据
    const intervalId = setInterval(() => {
        const data = {
            time: new Date().toISOString(),
            value: Math.random()
        };
        
        res.write(`data: ${JSON.stringify(data)}\n\n`);
    }, 1000);

    // 监听连接关闭
    req.on('close', () => {
        clearInterval(intervalId);
    });
});

app.listen(3000, () => {
    console.log('SSE 服务器运行在 3000 端口');
});

注意事项

  1. 格式有特定要求:开头为 data:、结尾为 \n\n

  2. 每个浏览器的并发 SSE 连接数有限制

  3. 某些代理服务器可能不支持长连接

  4. 建议实现错误重试机制

  5. 大规模使用时注意服务器资源管理

总结

SSE 是一个简单但强大的服务器推送方案:

  • 相比 WebSocket 更轻量,实现更简单

  • 单向通信满足大多数推送场景

  • 基于 HTTP 协议,兼容性好

  • 自动重连机制提高可靠性

适用场景:

  • 实时数据更新

  • 消息通知

  • 日志流式处理

参考资料