使用SpringBoot + SSE服务器数据推送

使用SpringBoot + SSE服务器数据推送

  • 前景+解决方案
    • 解决方案存在的问题
  • 使用SSE注意事项
    • 原生使用
    • Spring 提供的 SseEmitter
    • SseEmitter具体使用
    • 使用思路
  • 完结

前景+解决方案

项目中使用到了服务器向前端实时推送消息。场景解决方案:
1、前端使用短时间的定时器,轮训访问后端,每次访问更新数据或根据标识更新部分信息
2、众所周知的 WebSocket
3、比较新的技术,SSE

解决方案存在的问题

1、前端使用定时器轮训:
优点:一定程度上,减少代码开发维护,大部分中小公司都采取这种《敏捷》开发方案(个人经历)
缺点:实时性欠缺。虽然现在的HTTP默认长链接缓存,每次请求不需要经历多次握手,但是会有请求头+响应头等信息,还是浪费不必要的带宽(带宽是很宝贵的,财大气粗者忽略)。前端使用定时器不当,会造成页面卡顿或崩掉现象。

2、WebSocket 双向通道
优点:实时性,大众化,社区活跃,解决问题方便。
缺点:整合项目时稍重,引入依赖+添加相关配置+链接代码维护(忽略相关配置),功能过大,大部分的项目是服务器端向前端推送,webSocket是双向推送。

3、SSE
优点:单向推送,无需整合,spring boot 提供现成功能。
缺点:存在bug较多,社区较少,出现问题不好找到解决方案。

使用SSE注意事项

原生使用

原生的使用是基于对头信息的修改。

// 一般的使用方式
@RequestMapping(value="/push",produces="text/event-stream;charset=utf-8")
@ResponseBody
 public String push() {
     Random r = new Random();
     try {
         Thread.sleep(5000);
     } catch (InterruptedException e) {
         // ignore
     }
     return "data:Testing 1,2,3" + r.nextInt() +"\n\n";
 }

注意:
1、SSE 头信息 produces=“text/event-stream;charset=utf-8” 是必须的
2、响应是以 \n\n 结尾

这里只是一个简单的Demo,基于原生使用,明显不足。

Spring 提供的 SseEmitter

简书上的demo使用spring提供的工具类使用方便。
问题:不能完成我们项目的业务,实时推送。

SseEmitter具体使用

send() - 发送消息
complete() - 如果调用此方法,再次发送数据消息时会报错。如果提送多次数据,尽量不要调用此方法。
onCompletion() - 监听消息发送完成/异常时会触发。

spring官方文档api解释

使用思路

问题:前端断开后,后台无法监听或接收到信息。

当获取一个链接时,将SseEmitter存储至容器中,并且主动推送一次消息。
在存储之前添加onCompletion(),会在发送数据完成或异常时,移除容器中的SseEmitter
当需要推送时,根据标识从容器中获取SseEmitter,调用send()【这里建议使用观察者模式】

完结

本篇章个人使用经验所得,对源码还没有进行分析。
如果有不对的地方,大家多多指点。

你可能感兴趣的:(SSE服务器推送,spring,boot)