SSE 的基本原理
SSE 是基于 HTTP 的单向数据流推送:客户端发起一次连接后,服务器保持连接不断发送数据。浏览器端用 EventSource
接口接收消息。
后端返回示例(Node.js/Express)
app.get('/stream', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const send = (event, data) => {
res.write(`event: ${event}\n`);
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// 定时推送
const timer = setInterval(() => {
send('message', { time: Date.now() });
}, 2000);
// 客户端断开时清理
req.on('close', () => {
clearInterval(timer);
res.end();
});
});
前端接收示例
const es = new EventSource('/stream');
es.addEventListener('message', (e) => {
console.log('消息:', JSON.parse(e.data));
});
es.addEventListener('error', (e) => {
console.error('SSE 错误', e);
});
Nginx / 反向代理配置注意点
- 关闭或增大代理的超时时间:
proxy_read_timeout 1h;
- 确保
Content-Type: text/event-stream
不被篡改。 - 禁用压缩(某些情况下会破坏数据流格式)。
# 例:Nginx 反向代理 SSE
location /stream {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off; # 禁用缓冲
proxy_cache off;
proxy_read_timeout 1h; # 适当延长超时
}
部署与常见问题
- CDN/负载均衡可能会中断长连接,需要配置白名单或使用 WebSocket 代替。
- HTTPS 必需(浏览器新规范)。
- 如果需要心跳包,请按固定间隔发送注释行防止连接被关闭:
:\n\n