首页 > 其他分享 >后端消息推送-SSE协议

后端消息推送-SSE协议

时间:2023-05-11 18:03:44浏览次数:43  
标签:协议 WebSocket log clientId source SSE 推送 id

介绍

  HTTP 服务器推送也称 HTTP 流,是一种客户端-服务器通信模式,它将信息从 HTTP 服务器异步推送到客户端,而无需客户端请求。现在的 web 和 app 中,越来越多的场景使用这种通信模式,比如实时的消息提醒,IM在线聊天,多人文档协作等。以前实现这种类似的功能一般都是用ajax长轮询,而现在我们有了新的、更优雅的选择 —— WebSocket 和 SSE。

  • WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
  • SSE 是 Server-Sent Events 的简称, 是一种服务器端到客户端(浏览器)的单项消息推送。对应的浏览器端实现 Event Source 接口被制定为HTML5 的一部分。不过现在IE不支持该技术。相比于 WebSocket,SSE 简单很多,服务器端和客户端工作量都要小很多、简单很多,同时实现的功能也要有局限。

SSE与WebSocket有相似功能,都是用来建立浏览器与服务器之间的通信渠道。两者的区别在于:

  • WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。
  • WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在 HTTP协议之上的,现有的服务器软件都支持。
  • SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。
  • SSE默认支持断线重连,WebSocket则需要额外部署。
  • SSE支持自定义发送的数据类型。
  • SSE不支持CORS,参数url就是服务器网址,必须与当前网页的网址在同一个网域(domain),而且协议和端口都必须相同。WebSocket支持

本文介绍SSE的使用方式(如果系统中对这种消息的准确性和可靠性有严格的要求,则使用websocket,websocket的使用相对复杂的多)
如果想了解SSE的详细基础知识,可以参考阮一峰老师的这篇文章:Server-Sent Events 教程

SSE后端代码实现

SpringMVC中,已经集成了该功能,所以无需额外引入jar包,直接上代码:

@RestController
@RequestMapping("/notice")
public class NoticeController {

    @Autowired
    private NoticeService noticeService;

    @GetMapping(path = "createSseEmitter")
    public SseEmitter createSseEmitter(String id) {
        return noticeService.createSseEmitter(id);
    }

    @PostMapping(path = "sendMsg")
    public boolean sendMsg(String id, String content) {
        noticeService.sendMsg(id, content);
        return true;
    }

}

@Slf4j
@Service
public class NoticeServiceImpl implements NoticeService {
    @Autowired
    @Qualifier("sseEmitterCacheService")
    private CacheService<SseEmitter> sseEmitterCacheService;

    @Override
    public SseEmitter createSseEmitter(String clientId) {
        if (StringUtil.isBlank(clientId)) {
            clientId = UUID.randomUUID().toString().replace("-", "");
        }
        SseEmitter sseEmitter = sseEmitterCacheService.getCache(clientId);
        log.info("获取SSE,id={}", clientId);
        final String id = clientId;
        sseEmitter.onCompletion(() -> {
            log.info("SSE已完成,关闭连接 id={}", id);
            sseEmitterCacheService.deleteCache(id);
        });
        return sseEmitter;
    }
    @Override
    public void sendMsg(String clientId, String content) {
        if (sseEmitterCacheService.hasCache(clientId)) {
            SseEmitter sseEmitter = sseEmitterCacheService.getCache(clientId);
            try {
                sseEmitter.send(content);
            } catch (IOException e) {
                log.error("发送消息失败:{}", e.getMessage(), e);
                throw new BusinessRuntimeExcepption(CustomExcetionConstant.IO_ERR, "发送消息失败", e);
            }
        } else {
            log.error("SSE对象不存在");
            throw new BusinessRuntimeExcepption("SSE对象不存在");
        }
    }
}

这里,只列出了核心的代码,简而言之,需要做到两点即可:

  1. 前端首先是发起一个请求,创建SseEmitter,即createSseEmitter方法,该方法必须返回一个SseEmitter对象;
  2. 返回的SseEmitter,后端必须要缓存起来(我用的是ehcache,也可以直接定义一个map来缓存);

前端代码

使用浏览器原生提供的方法即可:

const url = '/xx/xxx'
// 1. 创建实例
var source = new EventSource(url)

// 2. 事件监听
// 建立连接后,触发`open` 事件
source.addEventListener('open', (e) => {
    console.log('open', e)
})
// 收到消息,触发`message` 事件
source.addEventListener('message', (e) => {
    console.log('message', e)
})
// 发生错误,触发`error` 事件
source.addEventListener('error', (e) => {
    console.log('error', e)
})
// 自定义事件
source.addEventListener('eventName', (e) => {
  // ...
}, false)

// 3. 关闭链接
source.close()

由于,我请求该接口,需要带上token,所以直接使用EventSource不行,另外这个IE也不支持。所以选择了一个工具:event-source-polyfill

1. 先安装 event-source-polyfill

npm install event-source-polyfill --save

2. 使用

import { EventSourcePolyfill } from "event-source-polyfill";

createSource() {
  const url = '/xx/xx/xx'  
  const source = new EventSourcePolyfill(url, {
    headers: {
      token: 'xxxxx'
    }
  })

  source.addEventListener('open', (e) => {
    console.log('open', e)
  })
  source.addEventListener('message', (e) => {
    console.log('message', e)
  })
   source.addEventListener('error', (e) => {
    console.log('error', e)
  })
}

注意

前端配置了代理,所以一直收不到后端发送的消息,尝试加入以下参数:

// vue.config.js

module.exports = {
  // ...
  devServer: {
    compress: false,
    ....
  }  
}

 

标签:协议,WebSocket,log,clientId,source,SSE,推送,id
From: https://www.cnblogs.com/shenjp/p/17391795.html

相关文章

  • 网络编程-通信协议-三要素
    1.概述:即通过无线网络或者有线网络可以把不同地理位置且相互独立的计算机连同其外部设备连接起来,组成计算机网络。这样就实现了计算机之间的资源共享和信息的传递。2.网络通信三要素2.1)ip地址网络中计算机的唯一标识;32bit(4字节),一般用“点分十进制”表示,如:192.168.1.158ip地......
  • HTTP协议客户端之HttpClient介绍及使用
    1.HttpClient介绍HttpClient是ApacheJakartaCommon下的子项目,可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient相比JDK自带的URLConnection,增加了易用性和灵活性,使客户端发送Http请求变得更加容......
  • 消息推送平台的实时数仓?!flink消费kafka消息入到hive
    大家好,3y啊。好些天没更新了,并没有偷懒,只不过一直在安装环境,差点都想放弃了。上一次比较大的更新是做了austin的预览地址,把企业微信的应用和机器人消息各种的消息类型和功能给完善了。上一篇文章也提到了,austin常规的功能已经更新得差不多了,剩下的就是各种细节的完善。不知道大......
  • https安全协议C#
    ServicePointManager.SecurityProtocol=(SecurityProtocolType)48|(SecurityProtocolType)192|(SecurityProtocolType)768|(SecurityProtocolType)3072;ServicePointManager.Expect100Continue=true;ServicePointManager.ServerCertificat......
  • Android实现推送方式解决方案 (转1)
    Android实现推送方式解决方案本文介绍在Android中实现推送方式的基础知识及相关解决方案。 1.推送方式基础知识: 当我们开发需要和服务器交互的应用程序时,基本上都需要获取服务器端的数据,比如《地震应急通》就需要及时获取服务器上最新的地震信息。要获取服务器上不定时更新......
  • LEACH网络协议性能仿真包括能耗,死亡节点,剩余存活节点
    1.算法仿真效果matlab2022a仿真结果如下:      2.算法涉及理论知识概要         LEACH协议,全称是“低功耗自适应集簇分层型协议”(LowEnergyAdaptiveClusteringHierarchy),是一种无线传感器网络路由协议。基于LEACH协议的算法,称为LEACH算法。LEACH......
  • git仓库过渡,同时向两个仓库推送代码
    公司部门被大佬收购,产品项目迁移新公司仓库,过渡期间产品上线流程继续使用原公司的,新公司部署新系统后通过域名重定向逐渐将用户引流到新系统上完成切换,最后关闭原公司系统及上线流程。过渡期间新功能代码需要保证两边git仓库里一致,即执行gitpush命令时同时往两个仓库里推送代码......
  • 医院信息集成平台 HL7协议对接
    1.介绍HL7缩写于HealthLevelSeven,是创建于1987年,用来发展独立卫生保健行业的电子交换交换标准,经过多年的发展,HL7已经有多个版本。简单的理解其实就像XML,JSON格式一样,HL7也是一种数据格式,可以理解为一个包含很多行字符串的消息体,这一整个就是一个HL7消息内容。HL7官网http://ww......
  • 五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT)
    当Adobe、Microsoft、Sun等一系列巨头开始表现出对”开源”的青睐时,”开源”的时代即将到来!现今存在的开源协议很多,而经过OpenSourceInitiative组织通过批准的开源协议目前有58种。我们在常见的开源协议如BSD,GPL,LGPL,MIT等都是OSI批准的协议。如果要开源自己的代码,最好也是选......
  • websocket多实例推送解决方案-数据实时展示
    需求需要前端展示实时的订单数据信息。如下图所示,实时下单实时页面统计更新展示 思路方案前端使用websocket建立通信  后端监听数据库的binglog变更,实时得到最新数据,推送到前端 现状及问题客户端想实现实时获取数据的变更,使用了websocket+kafkaMq,当......