go语言如何使用gin库实现SSE长连接

 更新时间:2023年06月09日 11:58:10   作者:合众国的原野  
所谓长连接指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持,下面这篇文章主要给大家介绍了关于go语言如何使用gin库实现SSE长连接的相关资料,需要的朋友可以参考下

前言

项目需求:在go项目中实现SSE长连接,耗时操作完成后,后端主动通知前端消息。

1.建立长连接

最主要的操作是修改请求中的Content-Type类型为"text/event-stream"。

需要注意几点,后端首先不能让请求处理代码跑完,如果跑完这个请求就会断掉,保存的*gin.Context信息也就没用了,因此要新建一个range chan维持处理状态。

另外这里如果用for循环代替chan,会导致前端持续发送请求到后端。

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/labstack/gommon/log"
	"net/http"
	"strings"
	"time"
)
 
var ifChannelsMapInit = false
 
var channelsMap = map[string]chan string{}
 
func initChannelsMap() {
	channelsMap = make(map[string]chan string)
}
 
func AddChannel(userEmail string, traceId string) {
	if !ifChannelsMapInit {
		initChannelsMap()
		ifChannelsMapInit = true
	}
	var newChannel = make(chan string)
	channelsMap[userEmail+traceId] = newChannel
	log.Infof("Build SSE connection for user = " + userEmail + ", trace id = " + traceId)
}
 
func BuildNotificationChannel(userEmail string, traceId string, c *gin.Context) {
	AddChannel(userEmail, traceId)
	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	w := c.Writer
	flusher, _ := w.(http.Flusher)
	closeNotify := c.Request.Context().Done()
	go func() {
		<-closeNotify
		delete(channelsMap, userEmail+traceId)
		log.Infof("SSE close for user = " + userEmail + ", trace id = " + traceId)
		return
	}()
	fmt.Fprintf(w, "data: %s\n\n", "--ping--")
	flusher.Flush()
	for msg := range channelsMap[userEmail+traceId] {
		fmt.Fprintf(w, "data: %s\n\n", msg)
		flusher.Flush()
	}
}

2.后端主动通知前端消息

当耗时操作处理完成后,调用该方法,前端会收到通知。

func SendNotification(userEmail string, messageBody string, actionType string) {
	log.Infof("Send notification to user = " + userEmail)
	var msg = dao.NotificationLog{}
	msg.MessageBody = messageBody
	msg.UserEmail = userEmail
	msg.Type = actionType
	msg.Status = UNREAD
	msg.CreateTime = time.Now()
	msg.Create()
	msgBytes, _ := json.Marshal(msg)
	for key := range channelsMap {
		if strings.Contains(key, userEmail) {
			channel := channelsMap[key]
			channel <- string(msgBytes)
		}
	}
}

3.调试

准备两个接口,分别是建立SSE和触发耗时操作

GroupV1Rest.GET("/notification/socket-connection", controllers.SocketConnection)
GroupV1Rest.GET("/notification/export-excel", controllers.ExportExcel)

打开浏览器,进入调试模式,在console页输入

e = new EventSource('/business/v1/notification/socket-connection');
e.onmessage = function(event) {
    console.log(event.data);
};

看到日志打印‘--ping--’,长连接已建立

 此时发送第二个请求,调试模式看到通知被chan处理

返回浏览器,可以看到已经收到通知

4.关闭长连接 

前端关闭页面后,自动触发监听事件,后端清理连接信息

总结 

到此这篇关于go语言如何使用gin库实现SSE长连接的文章就介绍到这了,更多相关go实现SSE长连接内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go引入自建包名报错:package XXX is not in std解决办法

    go引入自建包名报错:package XXX is not in std解决办法

    这篇文章主要给大家介绍了go引入自建包名报错:package XXX is not in std的解决办法,这是在写测试引入包名的时候遇到的错误提示,文中将解决办法介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • golang简单位运算示例

    golang简单位运算示例

    这篇文章主要介绍了golang简单位运算,包括位移运算、取反及位与位或等运算,需要的朋友可以参考下
    2016-07-07
  • Go语言MySQLCURD数据库操作示例详解

    Go语言MySQLCURD数据库操作示例详解

    这篇文章主要为大家介绍了Go语言MySQLCURD数据库操作示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Go语言实现一个Http Server框架(一) http库的使用

    Go语言实现一个Http Server框架(一) http库的使用

    本文主要介绍用Go语言实现一个Http Server框架中对http库的基本使用说明,文中有详细的代码示例,感兴趣的同学可以借鉴一下
    2023-04-04
  • go语言中for range使用方法及避坑指南

    go语言中for range使用方法及避坑指南

    Go中的for range组合可以和方便的实现对一个数组或切片进行遍历,但是在某些情况下使用for range时很可能就会被"坑",下面这篇文章主要给大家介绍了关于go语言中for range使用方法及避坑指南的相关资料,需要的朋友可以参考下
    2022-09-09
  • 对Go语言中的context包源码分析

    对Go语言中的context包源码分析

    这篇文章主要对Go语言中的context包源码进行分析,context包析是1.15,context包定义了一个Context类型过这个Context接口类型, 就可以跨api边界/跨进程传递一些值,下面我们就来对context包源码进行分析,需要的小伙伴可以参考一下
    2022-02-02
  • 详解Go语言如何实现类似Python中的with上下文管理器

    详解Go语言如何实现类似Python中的with上下文管理器

    熟悉 Python 的同学应该知道 Python 中的上下文管理器非常好用,那么在 Go 中是否也能实现上下文管理器呢,下面小编就来和大家仔细讲讲吧
    2023-07-07
  • CentOS7使用yum安装Golang的超详细步骤

    CentOS7使用yum安装Golang的超详细步骤

    CentOS默认并没有安装golang运行环境,下面这篇文章主要给大家介绍了关于CentOS7使用yum安装Golang的超详细步骤,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Go语言轻量级线程Goroutine用法实例

    Go语言轻量级线程Goroutine用法实例

    这篇文章主要介绍了Go语言轻量级线程Goroutine用法,实例分析了goroutine使用技巧,需要的朋友可以参考下
    2015-02-02
  • Golang官方限流器库实现限流示例详解

    Golang官方限流器库实现限流示例详解

    这篇文章主要为大家介绍了Golang官方限流器库使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论