找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1917

积分

0

好友

254

主题
发表于 2025-12-30 22:20:26 | 查看: 22| 回复: 0

服务器发送事件(SSE)是一种允许服务器向客户端进行实时单向数据推送的技术。作为 WebSockets 的轻量级替代方案,它在许多场景下提供了更低的网络开销与资源消耗。本文将演示如何在 Go 语言中实现 SSE,并深入探讨其与 WebSockets 的优劣对比。

什么是 SSE?

SSE 是一种基于 HTTP 的协议,它允许客户端通过一个持久连接订阅来自服务器的事件流。服务器发送的数据格式为文本,每个事件可以拥有自己的名称,数据负载可以是纯文本或 JSON。

如何实现?

下面的示例清晰地展示了使用 Go 实现 SSE 服务端和前端客户端的完整过程。核心在于正确设置 HTTP 响应头,这一原则适用于任何后端语言。

后端(Go 语言)

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, "index.html")
    })

    http.HandleFunc("/sse", func(w http.ResponseWriter, _ *http.Request) {
        w.Header().Set("Content-Type", "text/event-stream")
        w.Header().Set("Cache-Control", "no-cache")
        w.Header().Set("Connection", "keep-alive")

        messageCounter := 0

        for {
            someMessage := fmt.Sprintf("Message: %v", messageCounter)

            eventName := "event: myCustomEvent\n"
            payloadMessage := fmt.Sprintf("data: %s\n\n", someMessage)

            w.Write([]byte(eventName))
            w.Write([]byte(payloadMessage))

            time.Sleep(1 * time.Second)

            w.(http.Flusher).Flush()

            messageCounter++
        }
    })

    http.ListenAndServe(":3333", nil)
}

对路由 /sse 的处理函数设置了 SSE 必需的关键响应头:Content-Type: text/event-stream 声明了事件流内容类型,Cache-Control: no-cache 防止响应被缓存,Connection: keep-alive 则用于保持连接活跃。随后,服务器进入一个无限循环,不断生成并发送格式化的 SSE 事件。

注意:事件流格式要求使用 \n 作为换行符。event: 行定义事件类型(可选),data: 行承载有效载荷,最后由一个额外的 \n(即空行)来表示一个事件的结束。

经过格式化后,客户端接收到的数据流大致如下:

event: myCustomEvent
data: Message: 1

event: myCustomEvent
data: Message: 2

前端(HTML + JavaScript)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SSE</title>
</head>
<body>
  <h1>SSE - Real Time Messages</h1>

  <ul id="messages"></ul>

  <script>
    const eventSource = new EventSource('/sse');

    eventSource.addEventListener('myCustomEvent', event => {
      const messagesElement = document.getElementById('messages');
      const li = document.createElement('li');

      li.innerText = event.data;

      messagesElement.appendChild(li);

      console.log(event);
    });
  </script>
</body>
</html>

前端代码非常简洁。我们创建了一个 EventSource 对象,连接到后端的 /sse 端点,从而建立持久连接。随后,通过 addEventListener 监听服务器端定义的 myCustomEvent 事件。每当该事件被触发,前端就会从 event.data 中获取消息内容,并将其动态添加到页面的列表中。

图1:SSE实时消息在前端页面的展示效果
SSE前端消息展示效果

图2:浏览器开发者工具中查看SSE事件流连接
浏览器网络面板SSE事件流

SSE 的优点和缺点

优点

  • 基于HTTP:使用标准HTTP/HTTPS端口(80/443),易于穿透防火墙和代理服务器,兼容性极佳。
  • 轻量高效:相比于WebSocket,网络开销和服务器资源占用更少,因为连接建立后主要是服务器向客户端的单向数据推送。
  • 实现简单:直接利用现有HTTP协议栈,编程模型对于开发者更为熟悉。

缺点

  • 单向通信:只能由服务器向客户端推送数据,客户端无法通过同一连接向服务器发送信息。
  • 浏览器支持:虽然主流现代浏览器都支持,但在某些老旧或特定平台上的支持度可能不如WebSocket完善。
  • 协议限制:作为HTTP的上层功能,无法利用WebSocket协议级别的特性,如二进制数据传输、更高效的压缩和多路复用。

SSE 与 WebSockets 的比较

SSE 和 WebSockets 都用于实现实时通信,但定位不同。

WebSockets 提供了全双工通信通道,客户端和服务器可以随时相互发送数据。这使得它非常适合需要频繁双向交互的应用,例如在线聊天室、协同编辑、多人在线游戏等。

SSE服务器到客户端的单向通道。它完美契合了服务器主动向客户端推送更新,而客户端无需上行的场景。典型的应用包括实时新闻推送、股票价格变动、社交媒体动态通知、服务器日志流式输出等。

此外,WebSocket 是一个独立的、在TCP之上实现的协议,支持二进制帧和自定义扩展。而 SSE 是纯文本的,基于 HTTP 协议,其简单性既是优势也是限制。

选择哪种技术取决于你的具体需求:如果需要双向、低延迟、任意格式数据的自由交换,WebSocket 是首选;如果业务模型主要是服务器向客户端广播或推送文本信息,那么更简单、对服务器压力更小的 SSE 可能是更优解。欢迎在云栈社区继续探讨实时通信技术的更多细节。




上一篇:树莓派部署UniFi网络控制器教程:OpenJDK 17与MongoDB 4.4配置指南
下一篇:使用geo_plotkit高效绘制连续型栅格:Python实现中国地形图可视化
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-11 11:55 , Processed in 0.292626 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表