GO Server-Sent Events (SSE)
1. 什么是 Server-Sent Events (SSE)?
Server-Sent Events (SSE) 是一种服务器向客户端单向推送事件的技术。使用 SSE,服务器可以通过一个持续的 HTTP 连接向客户端发送实时更新,适用于实时通知、数据流等场景。
2. 为什么选择 SSE?
- 简单易用:使用 HTTP 协议,不需要像 WebSocket 那样升级协议。
- 自动重连:浏览器原生支持 SSE,会在连接断开时自动尝试重新连接。
- 文本传输:以纯文本的形式传输数据,易于调试。
3. 使用场景
- 实时通知:如社交媒体通知、消息提醒。
- 实时数据流:股票行情、在线用户数量等。
- 日志监控:实时显示服务器日志、应用状态。
4. 基本原理
- 服务器端:持续向客户端发送事件流。数据以
text/event-stream
格式传输,保持 HTTP 连接打开。 - 客户端:使用
EventSource
API 连接到 SSE 端点,接收服务器推送的事件。
5. SSE 服务器端实现(Go 示例)
在服务器端,我们将使用 Go 语言创建一个 SSE 端点,每秒向客户端发送一次当前时间。
5.1 设置 Go 环境
确保你的系统已经安装 Go。你可以在 Go 官网 下载并安装。
5.2 创建 SSE 服务器
package main
import (
"fmt"
"net/http"
"time"
)
func sseHandler(w http.ResponseWriter, r *http.Request) {
// 设置必要的 HTTP 头
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// 确保客户端可以接收实时数据
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}
// 持续发送数据到客户端
for {
// 向客户端发送当前时间
fmt.Fprintf(w, "data: %s\n\n", time.Now().Format(time.RFC3339))
flusher.Flush() // 确保数据被立即发送到客户端
// 模拟延迟
time.Sleep(1 * time.Second)
}
}
func main() {
http.HandleFunc("/events", sseHandler)
fmt.Println("Server started on :8080")
http.ListenAndServe(":8080", nil)
}
5.3 运行服务器
将上述代码保存为 main.go
,然后在终端运行:
go run main.go
服务器将启动并监听 localhost:8080
。
6. SSE 客户端实现(前端示例)
在客户端,我们将使用浏览器的 EventSource
API 连接到服务器,并接收实时数据。
6.1 创建 HTML 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSE Demo</title>
</head>
<body>
<h1>Server-Sent Events Demo</h1>
<div id="output"></div>
<script>
const output = document.getElementById('output');
// 创建一个新的 EventSource 实例
const evtSource = new EventSource('/events');
// 当接收到消息时执行
evtSource.onmessage = function(event) {
const newElement = document.createElement("div");
newElement.innerHTML = "Received: " + event.data;
output.appendChild(newElement);
};
// 处理错误
evtSource.onerror = function() {
console.error('EventSource failed.');
};
</script>
</body>
</html>
6.2 运行前端
将上述 HTML 文件保存为 index.html
,在浏览器中打开。确保浏览器可以访问运行中的 Go 服务器,页面会显示每秒推送的当前时间。
7. SSE 工作原理详解
-
数据格式:SSE 传输数据以
text/event-stream
格式,包含事件类型、数据等。常见格式:data: Hello World\n\n
其中
\n\n
表示事件结束。 -
自动重连:浏览器会在连接断开时自动尝试重新连接。
-
事件类型:可以自定义事件类型,通过
event: eventType
指定,客户端使用addEventListener
监听不同类型事件。
8. 使用注意事项
- 单向通信:SSE 只能实现服务器到客户端的单向通信。如果需要双向通信,请考虑使用 WebSocket。
- 兼容性:SSE 在大多数现代浏览器中支持良好,但在一些旧版浏览器(如 IE)中不支持。
- 数据量控制:SSE 适合发送小规模实时数据。如果数据量大或频率高,需注意性能和带宽。
9. 进阶功能
- 事件分组:通过
event
字段发送不同类型的事件,前端可以使用addEventListener
监听指定类型事件。 - 重试间隔:服务器可以通过
retry
字段设置客户端重连间隔时间。 - 自定义数据:可以通过
id
字段发送事件 ID,客户端可以使用lastEventId
恢复连接后从特定 ID 开始接收数据。
10. 参考资料
- MDN Web Docs - Server-Sent Events
- Go 官方文档
总结
通过这个教程,你已经了解了什么是 Server-Sent Events (SSE)、它的使用场景以及如何在 Go 中实现一个简单的 SSE 服务器,并在前端接收实时数据。SSE 是一种简单、有效的实时数据推送方式,适用于单向、低延迟的实时更新需求。