SpringBoot 接入SSE实现消息实时推送的优点,原理以及实现
前言
上一篇文章 我写的关于SpringBoot整合t-io是websocket实时通信的文章中我们可以了解到 websocket是双向通信的,而且需要TCP连接的支持,今天在这里我要说的SSE(Server-Sent Events) 是一个单项通信的消息实时推送框架,它仅支持由服务器发送消息到客户端,而且是基于HTTP/HTTPS的。对于我们只需要从服务器向客户端推送的数据使用SSE会更加轻便,性能更强。
SSE 单向数据推送的优点
1. 简单易用
- 基于HTTP:SSE使用标准的HTTP协议,无需额外的协议升级(如WebSocket的握手)。这使得它更容易集成到现有HTTP基础设施中。
- 客户端API简单:浏览器端使用
EventSource
对象,API非常简单,只需几行代码即可建立连接并监听事件。 - 自动重连:
EventSource
内置了自动重连机制,当连接断开时,客户端会自动尝试重新连接。
2. 单向通信(服务器到客户端)
- 对于只需要服务器向客户端推送数据的场景(如实时通知、股票行情、新闻更新等),SSE是理想的选择。它不需要客户端向服务器发送数据,从而减少了复杂性和开销。
3. 轻量级
- SSE的数据格式是纯文本,每条消息由
event
、data
和id
等字段组成,结构简单,解析高效。 - 与WebSocket相比,SSE在协议层更轻量,不需要维护双向通信的复杂状态。
4. 支持标准HTTP功能
- 安全性:SSE可以通过HTTPS运行,确保数据传输的安全性。
- 认证和授权:由于基于HTTP,可以方便地使用Cookie、HTTP认证或Token进行访问控制。
- 代理友好:SSE可以通过标准的HTTP代理和防火墙,而WebSocket可能会在某些严格的网络环境中被阻止。
5. 自动处理连接管理
- 客户端(浏览器)的
EventSource
会自动处理连接建立、断开和重试逻辑,开发者无需手动实现这些功能。
6. 文本数据友好
- 对于推送文本数据(如JSON、XML、纯文本),SSE非常高效。如果需要传输二进制数据,则WebSocket更合适。
7. 兼容性
- 浏览器支持:现代浏览器(包括IE/Edge、Firefox、Chrome、Safari、Opera)都支持SSE。对于不支持的浏览器(如IE11及以下),可以使用polyfill(如
eventsource
库)。 - 服务器端:几乎所有后端语言和框架都支持SSE,因为本质上它只是长轮询的标准化和简化。
8. 效率
- 相比传统的轮询(Polling)或长轮询(Long Polling),SSE使用持久连接,服务器可以在有数据时立即推送,减少了不必要的请求和延迟。
9. 事件驱动
- 服务器可以发送不同类型的事件(通过
event
字段),客户端可以为不同的事件注册不同的处理函数,实现更灵活的消息处理。
10. 与现有技术栈集成容易
- 如果你已经有一个RESTful API,添加SSE端点通常很简单,无需引入额外的库或中间件(如WebSocket服务器)。
对比WebSocket
- 双向 vs 单向:WebSocket提供全双工通信,适合需要双向交互的场景(如聊天应用)。SSE仅支持服务器到客户端的单向通信。
- 复杂性:WebSocket需要更复杂的服务器和客户端实现,而SSE更简单。
- 二进制数据:WebSocket支持二进制数据,SSE仅支持文本(但可以Base64编码二进制数据)。
适用场景
- 实时通知(如邮件、消息提醒)
- 实时数据监控(如股票行情、实时日志)
- 新闻推送、赛事比分更新
- 任何需要服务器主动向客户端推送数据的场景
SSE 代码实现
1. SSE 工具类,支持消息推送与心跳保持
@Slf4j
public class SseUtils {// 存储用户ID与SseEmitter的映射private static final Map<Long, SseEmitter> emitterMap = Maps.newConcurrentMap();// 心跳任务映射:用户ID -> 心跳任务pri