需求背景
当发生信息变更,应用程序能够更快速地响应用户的操作或推送最新的信息,减少不必要的网络请求和响应,降低网络带宽的消耗
技术选型
SSE和WebSocket都是用于实现实时通信的技术,但它们在实现方式、适用场景和特性上有所不同。以下是SSE相对于WebSocket的优势:
- 简单易用:SSE在使用上相对简单,特别是对于只需要单向通信(从服务器到客户端)的场景。大多数现代浏览器都原生支持SSE,无需额外的库或插件。这使得SSE的集成和开发过程相对简单快捷。
- 内建重连机制:SSE自带自动重连功能,如果连接断开,浏览器会尝试重新建立连接。这在处理临时网络中断或服务器故障时非常有用,能够确保客户端能够持续接收服务器发送的事件。
- 基于HTTP:SSE操作基于标准的HTTP协议,这使得它更容易与现有的Web基础设施和中间件兼容。SSE可以利用HTTP的缓存、代理和安全性特性,而无需引入新的协议或中间件。
- 轻量级:SSE在数据传输上相对轻量级,它只发送文本格式的数据,不需要进行复杂的编码或解码操作。这使得SSE在带宽使用上更加高效,适用于需要频繁发送小量数据的场景
SSE简介
SSE(Server-Sent Events)是一种用于实现服务器主动向客户端推送数据的技术,也被称为“事件流”(Event Stream)。它基于 HTTP 协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送
集成方案
不做任何处理的情况下,一个客户端只能被拥有该SSE连接的服务端推送消息。因此SSE的服务端集群需要借助Redis的发布订阅模式做特殊处理。
前端发起连接请求同时携带用户名,后端维护一个Map<uniqueName, SseEmitter>,通过这个Map实现消息的实时推送,但如果是集群,其他服务器的Map中可能找不到对应的SseEmitter。
解决方案:
当Message变更时,需要将对应的用户信息封装到Message中,利用Redis的发布订阅模式,统一将Message推送到Redis中,此时拥有Map<uniqueName, SseEmitter>的所有服务器会触发监听,满足业务推送条件则会触发消息推送
SSE连接
建立连接后,随机发送初始化数据,这里开启异步线程,等待连接完成后发送初始化数据。
public class NotificationController {
private final SseEmitterService sseEmitterService;
/**
* 创建服务器发送事件(SSE)连接。
* 由于SSE连接的特性,本方法仅支持通过GET请求传递参数。
* <p>
* SS