赞
踩
引用维基百科:
Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via HTTP connection. The Server-Sent Events EventSource API is standardized as part of HTML5[1] by the W3C.
在Web开发时,由于HTTP是无状态的协议,所以客户端浏览器必须首先向服务器发送请求才能接收新数据。所以如果要实现服务端向客户端发起通知,通常可以使用WebSocket或者客户端长轮询(Long-Poling)的方式。但是其实如果只是服务端向客户端推送单方向的数据流时,可以使用H5标准中的SSE,SSE使用户可以订阅服务器端的实时数据流。
Server Sent Events(SSE)和WebSocket都是Web技术中用于实现实时通信的协议。它们之间的一些差异如下:
综上所述,SSE和WebSocket都有自己的优势和劣势,适用于不同的应用场景。对于需要快速构建实时通信的简单场景,SSE是一种快速且易于部署的解决方案。而对于更复杂的应用程序需求,WebSocket则提供了更高效的数据传输和更灵活的控制机制。
Golang有开源库eventsource直接支持了SSE,在这里我们直接使用这个库构建服务器:
导入插件
gopkg.in/antage/eventsource.v1
直接运行,直接访问接口,获取响应值就行,
可以循环读取redis中的信息,推送给前端
package main import ( "context" "fmt" "net/http" "time" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gctx" "gopkg.in/antage/eventsource.v1" ) func main() { ctx := gctx.New() StartSSE(ctx) } func StartSSE(ctx context.Context) { s := g.Server() s.BindHandler("/sse", func(r *ghttp.Request) { es := eventsource.New( &eventsource.Settings{ Timeout: 5 * time.Second, IdleTimeout: 1 * time.Minute, CloseOnTimeout: true, }, func(request *http.Request) [][]byte { return [][]byte{ []byte("Content-Type: text/event-stream; charset=utf-8"), []byte("Connection: keep-alive"), []byte("X-Accel-Buffering: no"), // 防止 nginx 中间启用缓存,导致不能刷新到客户端 []byte("Cache-Control: no-cache,no-store"), []byte("Access-Control-Allow-Origin: *"), []byte("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"), } }, ) defer es.Close() es.ServeHTTP(r.Response.Writer, r.Request) // 请求参数校验 eventId := r.Get("eventId").String() event := r.Get("event").String() eventTime := r.Get("eventTime").Int64() if eventId == "" || event == "" || eventTime < 1 { es.SendEventMessage("请求事件异常", event, eventId) return } now := gtime.Now() t := gtime.NewFromTimeStamp(eventTime) if now.Timestamp() < eventTime || now.Sub(t) > 3*time.Minute { es.SendEventMessage("请求事件超时", event, eventId) return } // 循环执行时间 3 分钟 to := time.After(3 * time.Minute) for { select { case <-to: fmt.Println("Timeout!") return default: es.SendEventMessage("data数据", event, eventId) // 每秒轮询一次 time.Sleep(1 * time.Second) } } }) s.port(8080) s.Run() }
type HelloReq struct { g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"` } type HelloRes struct { g.Meta `mime:"text/html" type:"string" example:"<html/>" ` } var ( Hello = cHello{} ) type cHello struct{} func (c *cHello) Hello(ctx context.Context, req *common.HelloReq) (res *common.HelloRes, err error) { err = g.RequestFromCtx(ctx).Response.WriteTpl("/home/index.html") liberr.ErrIsNil(ctx, err) return }
客户端HTML页面在resource/template目录下,通过new EventSource("/events")
创建了前端的SSE接收实例对象evsrc,并设置了onmessage方法:每次接收到请求就在页面列表中加入一条数据;
<!DOCTYPE html> <html> <head> <title>SSE test</title> <script type="text/javascript"> window.addEventListener("DOMContentLoaded", function () { var evsrc = new EventSource("/sse"); evsrc.onmessage = function (ev) { document.getElementById("log") .insertAdjacentHTML("beforeend", "<li>" + ev.data + "</li>"); } evsrc.onerror = function (ev) { console.log("readyState = " + ev.currentTarget.readyState); } }) </script> </head> <body> <h1>SSE test</h1> <div> <ul id="log"> </ul> </div> </body> </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。