当前位置:   article > 正文

GoNote第六章 GoFrame 接入SSE_goframe如何调用sse接口

goframe如何调用sse接口

GoNote第六章 GoFrame 接入SSE

什么是SSE(Server Sent Events)

引用维基百科:

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使用户可以订阅服务器端的实时数据流。

SSE与WebSocket

Server Sent Events(SSE)和WebSocket都是Web技术中用于实现实时通信的协议。它们之间的一些差异如下:

  1. SSE与WebSocket之间的主要区别在于,SSE是基于HTTP协议进行的,而WebSocket是独立的协议。因此,SSE可以轻松地使用现有的HTTP基础设施进行部署,而WebSocket则需要单独的网络端口并在服务器上进行特殊的配置。
  2. 对于服务器推送数据到客户端,SSE使用常规的HTTP响应,其中包含了许多按照事件流格式格式化的消息。而WebSocket则使用专用的双向数据通道,更适合双向通信的场景。
  3. 在使用SSE时,服务器推送消息的速度相对较慢,并且不能自由控制消息的发送时间间隔。而WebSocket具有更高的性能和更灵活的控制机制,可以处理更复杂的应用程序需求。
  4. 由于SSE是基于HTTP协议实现的,因此可以借助浏览器的缓存机制,从而减少网络流量和服务器负担。而WebSocket则需要通过自己的协议处理缓存问题,在这方面较为繁琐。

综上所述,SSE和WebSocket都有自己的优势和劣势,适用于不同的应用场景。对于需要快速构建实时通信的简单场景,SSE是一种快速且易于部署的解决方案。而对于更复杂的应用程序需求,WebSocket则提供了更高效的数据传输和更灵活的控制机制。

goFrame 引入SSE

Golang有开源库eventsource直接支持了SSE,在这里我们直接使用这个库构建服务器:

导入插件

gopkg.in/antage/eventsource.v1
  • 1

直接运行,直接访问接口,获取响应值就行,

可以循环读取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()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

跳转Html页面

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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

客户端HTML页面

客户端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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/962600
推荐阅读
相关标签
  

闽ICP备14008679号