golang实现HTML服务器推送事件的客户端与服务端插件库go-sse的使用

Golang实现HTML服务器推送事件的客户端与服务端插件库go-sse的使用

go-sse简介

go-sse是一个提供服务器推送事件(Server-Sent Events)实现的Golang包,它符合WHATWG HTML规范第9.2节的要求,适合需要连接到SSE服务器端点或向前端服务提供事件的应用程序。

特性

  • 包中每个类型和方法都有完整的文档
  • 符合WHATWG HTML规范
  • 广泛的测试套件确保一致性

go-sse要求最低Go 1.18版本。

基本用法

首先导入包:

import "github.com/lampctl/go-sse"

作为客户端使用

创建客户端:

// 从URL创建客户端配置
cfg, err := sse.NewClientConfigFromURL("http://example.com/sse")
if err != nil {
    // 处理错误
}
// 创建客户端
c := sse.NewClient(cfg)

c.Events通道读取事件:

for e := range c.Events {
    fmt.Println("Event received!")
    fmt.Println(e.Data)
}

注意:如果连接关闭或中断,客户端将根据规范尝试重新连接,并从中断处继续返回事件。这都在后台处理,不会影响事件通道的状态。

完成后关闭客户端:

c.Close()

作为服务器使用

服务器组件通过实现http.HandlerHandler提供:

// 创建默认配置的处理器
h := sse.NewHandler(nil)

// 或者自定义初始化配置
h := sse.NewHandler(&sse.HandlerConfig{
    NumEventsToKeep:   10,  // 保留的事件数量
    ChannelBufferSize: 4,   // 通道缓冲区大小
})

发送事件:

h.Send(&sse.Event{
    Type: "alert",          // 事件类型
    Data: "The aliens are invading!",  // 事件数据
    ID:   "12345",         // 事件ID
})

完成后关闭处理器:

h.Close()

完整示例

服务端示例

package main

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

	"github.com/lampctl/go-sse"
)

func main() {
	// 创建SSE处理器
	h := sse.NewHandler(nil)
	
	// 设置HTTP路由
	http.Handle("/events", h)
	
	// 启动HTTP服务器
	go http.ListenAndServe(":8080", nil)
	
	// 每秒发送一个事件
	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()
	
	count := 0
	for range ticker.C {
		count++
		h.Send(&sse.Event{
			Type: "message",
			Data: fmt.Sprintf("Event %d", count),
			ID:   fmt.Sprintf("%d", count),
		})
	}
}

客户端示例

package main

import (
	"fmt"
	"log"

	"github.com/lampctl/go-sse"
)

func main() {
	// 创建客户端配置
	cfg, err := sse.NewClientConfigFromURL("http://localhost:8080/events")
	if err != nil {
		log.Fatal(err)
	}
	
	// 创建客户端
	c := sse.NewClient(cfg)
	defer c.Close()
	
	// 接收事件
	for e := range c.Events {
		fmt.Printf("Received event: %+v\n", e)
	}
}

这个示例展示了如何使用go-sse库创建SSE服务器和客户端。服务端每秒发送一个事件,客户端接收并打印这些事件。


更多关于golang实现HTML服务器推送事件的客户端与服务端插件库go-sse的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现HTML服务器推送事件的客户端与服务端插件库go-sse的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-sse实现HTML服务器推送事件(SSE)

SSE(Server-Sent Events)是一种允许服务器向客户端推送数据的Web技术,它基于HTTP协议,使用简单且高效。下面我将介绍如何使用go-sse库在Golang中实现SSE的客户端和服务端。

安装go-sse库

首先安装go-sse库:

go get github.com/tmaxmax/go-sse

服务端实现

基本服务端示例

package main

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

	"github.com/tmaxmax/go-sse"
)

func main() {
	// 创建SSE服务
	s := sse.NewService()

	// 创建事件发布器
	publisher := s.NewPublisher("updates")

	// 启动一个goroutine定期发送事件
	go func() {
		for i := 0; ; i++ {
			// 构造事件
			event := sse.Event{
				ID:    fmt.Sprintf("%d", i),
				Event: "message",
				Data:  []byte(fmt.Sprintf("当前时间: %v", time.Now().Format(time.RFC3339))),
			}

			// 发布事件
			publisher.Publish(event)

			// 每秒发送一次
			time.Sleep(time.Second)
		}
	}()

	// 设置HTTP路由
	http.Handle("/events", s)

	// 启动HTTP服务器
	fmt.Println("SSE服务器运行在 http://localhost:8080/events")
	http.ListenAndServe(":8080", nil)
}

高级功能

  1. 自定义连接处理
s := sse.NewService(sse.WithConnectionTTL(5*time.Minute))
  1. 跨域支持
s := sse.NewService(sse.WithCORS(sse.CORS{
	Origins:        []string{"*"},
	Methods:        []string{"GET"},
	AllowedHeaders: []string{"Content-Type"},
}))
  1. 认证和鉴权
http.Handle("/events", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	// 检查认证
	if r.Header.Get("Authorization") != "Bearer secret" {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	
	// 处理SSE连接
	s.ServeHTTP(w, r)
}))

客户端实现

基本客户端示例

package main

import (
	"fmt"
	"log"

	"github.com/tmaxmax/go-sse"
)

func main() {
	// 创建客户端
	client := sse.NewClient("http://localhost:8080/events")

	// 订阅事件
	subscription := client.Subscribe("updates")

	// 处理接收到的消息
	for {
		select {
		case event := <-subscription.Events:
			fmt.Printf("收到事件: ID=%s, 类型=%s, 数据=%s\n", 
				event.ID, event.Name, string(event.Data))
		case err := <-subscription.Errors:
			log.Printf("发生错误: %v\n", err)
			return
		}
	}
}

高级客户端功能

  1. 自定义HTTP客户端
client := sse.NewClient("http://localhost:8080/events",
	sse.WithHTTPClient(&http.Client{
		Timeout: 10 * time.Second,
	}),
)
  1. 重试策略
client := sse.NewClient("http://localhost:8080/events",
	sse.WithRetryPolicy(func(statusCode int, err error) time.Duration {
		if statusCode == http.StatusTooManyRequests {
			return 30 * time.Second
		}
		return 5 * time.Second
	}),
)
  1. 自定义头部
client := sse.NewClient("http://localhost:8080/events",
	sse.WithHeaders(map[string]string{
		"Authorization": "Bearer token",
		"X-Custom-Header": "value",
	}),
)

实际应用场景

实时日志监控

// 服务端
func logStreamHandler(w http.ResponseWriter, r *http.Request) {
	publisher := sseService.NewPublisher("logs")
	
	// 模拟日志流
	go func() {
		for {
			logEntry := generateLogEntry() // 生成日志条目
			event := sse.Event{
				Event: "log",
				Data:  []byte(logEntry),
			}
			publisher.Publish(event)
			time.Sleep(500 * time.Millisecond)
		}
	}()
	
	sseService.ServeHTTP(w, r)
}

实时数据仪表盘

// 客户端
func main() {
	client := sse.NewClient("http://localhost:8080/metrics")
	
	// 订阅多个事件类型
	metricsSub := client.Subscribe("cpu", "memory", "network")
	
	for {
		select {
		case event := <-metricsSub.Events:
			switch event.Name {
			case "cpu":
				updateCPUUsage(string(event.Data))
			case "memory":
				updateMemoryUsage(string(event.Data))
			case "network":
				updateNetworkStats(string(event.Data))
			}
		case err := <-metricsSub.Errors:
			log.Println("连接错误:", err)
			return
		}
	}
}

注意事项

  1. 连接管理:SSE连接是长连接,需要妥善处理断开和重连
  2. 性能考虑:大量并发连接会消耗服务器资源
  3. 浏览器兼容性:现代浏览器都支持SSE,但IE不支持
  4. 安全性:确保敏感数据通过HTTPS传输,并实施适当的认证机制

go-sse库提供了简单而强大的SSE实现,适合需要服务器向客户端实时推送数据的应用场景。

回到顶部