在现代 Web 开发中,实时数据推送已经成为许多应用的核心需求。无论是股票行情、社交媒体通知,还是在线协作编辑,用户都希望能够即时获取最新的信息。在这种背景下,服务器发送事件(Server-Sent Events,SSE)作为一种轻量级的实时通信技术,提供了一种简单而高效的解决方案。
服务器发送事件(SSE)是一种基于 HTTP 协议的单向通信技术,允许服务器通过持久连接向客户端持续推送数据。它使用EventSource
API 来接收数据,服务器通过text/event-stream
格式发送消息。这种方式特别适合需要实时更新数据的应用场景,例如新闻推送、在线监控、社交媒体通知等。
SSE 的适用场景:
与 WebSockets 相比,SSE 更适合单向数据流的场景。它直接基于 HTTP 协议,无需额外的协议支持,因此更加轻量级。
EventSource
轻松接收数据,无需复杂的配置或额外的服务器支持。SSE 采用纯文本格式发送数据,每条消息以换行符\n\n
结束。消息格式如下:
data: 这是一条普通消息
data: {"name": "John", "message": "Hello"}
SSE 还支持自定义事件类型,客户端可以监听不同类型的消息:
event: update
data: {"status": "success", "timestamp": "2025-02-13T12:00:00Z"}
event: alert
data: {"message": "系统异常"}
在客户端,可以使用addEventListener
监听特定事件:
eventSource.addEventListener("update", (event) => {
console.log("更新消息:", event.data);
});
服务器还可以通过id
字段提供断点恢复功能。客户端在重连时会自动带上Last-Event-ID
,服务器可以据此恢复消息流:
id: 12345
data: 这是一条可以恢复的消息
以下是一个完整的 SSE 服务器和前端代码示例。
package main
import (
"fmt"
"log"
"net/http"
"time"
)
// SSE处理函数
func sseHandler(w http.ResponseWriter, r *http.Request) {
// 设置SSE必要的HTTP头
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
w.Header().Set("Access-Control-Allow-Origin", "*") // 允许跨域
// 获取写入流
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
return
}
// 定期发送数据
for {
_, err := fmt.Fprintf(w, "FunTester data: 当前时间:%s\n\n", time.Now().Format(time.RFC3339))
if err != nil {
log.Println("FunTester 客户端连接断开:", err)
break
}
flusher.Flush() // 立即推送数据到客户端
time.Sleep(2 * time.Second)
}
}
func main() {
http.HandleFunc("/events", sseHandler)
port := 8080
log.Printf("SSE服务器运行在 FunTester http://localhost:%d/events", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}
代码解析
Access-Control-Allow-Origin: *
允许跨域访问。const eventSource = new EventSource('/events');
eventSource.onmessage = (event) => {
console.log("收到消息:", event.data);
};
eventSource.onerror = () => {
console.log("FunTester 连接丢失,尝试重连...");
};
浏览器会自动维护 SSE 连接,并在断开时尝试重新连接。
SSE 和 WebSockets 都能实现实时数据推送,但它们的设计目标不同。
特性 | SSE | WebSocket |
---|---|---|
通信方式 | 单向(服务器 → 客户端) | 双向(客户端 ↔ 服务器) |
协议 | 基于 HTTP(EventStream) | 自定义 TCP 协议 |
自动重连 | 浏览器内置支持 | 需要手动实现 |
兼容性 | 兼容 HTTP 代理、CDN | 可能受限于防火墙、代理 |
适用场景 | 服务器数据推送(新闻、日志) | 聊天、游戏、协作编辑 |
如果应用只需要服务器向客户端推送数据(如股票行情、新闻、社交通知),SSE 是更好的选择。如果需要双向交互(如在线游戏、WebRTC、IM 聊天),WebSockets 更适合。
SSE 在以下场景中表现出色:
如果应用主要是服务器向客户端推送数据,SSE 是最简单、最稳定的选择。
keep-alive
以防止超时断开。proxy_buffering off;
确保流式传输。Last-Event-ID
允许客户端在断开后重新获取丢失的数据。res.setHeader('Access-Control-Allow-Origin', '*');
SSE 是一种轻量级、易实现的实时数据推送方案,适用于单向数据流场景,如股票市场、新闻推送、社交媒体通知等。相较于 WebSockets,SSE 更简单,浏览器原生支持自动重连,不需要额外的协议或服务器负担。
如果你的应用只需要服务器推送数据到客户端,SSE 是一个理想的选择。而如果你需要双向实时通信,WebSockets 可能更合适。正确选择技术,才能让应用更加高效和稳定。
FunTester 原创精华