SSE
本文最后更新于:2025年6月28日 晚上
Server-Sent Events (SSE)
Server-Sent Events (SSE) 是一种允许服务器向客户端实时推送数据的Web技术,它基于HTTP协议,提供了一种简单有效的服务器到客户端的单向通信机制。
注意:SSE更适配响应式编程
响应式编程(WebFlux)的优势
响应式栈(如WebFlux + Reactor)的SSE实现更高效:
(简单示例)
1 |
|
优势:
特性 | 阻塞式(MVC) | 响应式(WebFlux) |
---|---|---|
线程占用 | 1连接=1线程 | 固定少量IO线程 |
内存消耗 | 每个连接独立缓冲 | 共享背压缓冲 |
广播复杂度 | O(n)手动发送 | O(1)自动多播 |
扩展性 | 千级连接 | 万级连接 |
适用场景选择
✅ 适合响应式SSE的场景:
- 高并发(如实时仪表盘、股票行情)
- 需要组合多个异步数据源(如数据库变更+消息队列)
- 长周期事件流(如文件导入进度)
❌ 适合传统阻塞式的场景:
- 简单低频通知(如单个用户订单状态更新)
- 遗留系统无法升级响应式栈
- 需要与阻塞式库(如JPA/Hibernate)深度集成
性能对比数据
在相同4核8G服务器上:
连接数 | Spring MVC SSE | WebFlux SSE |
---|---|---|
1,000 | 线程池耗尽 | 内存占用200MB |
10,000 | 崩溃 | 内存占用1.2GB |
延迟 | 15-30ms | 2-8ms |
基本概念
SSE 的主要特点包括:
- 单向通信:仅服务器可以向客户端推送数据
- 基于HTTP:使用标准HTTP协议,不需要特殊协议
- 文本格式:数据以纯文本格式传输
- 自动重连:内置连接断开后的自动重连机制
- 简单API:浏览器端使用简单的EventSource API
工作原理
-
客户端通过
EventSource
对象发起连接 -
服务器保持连接打开,以
text/event-stream
格式发送数据 -
数据以流的形式持续发送,格式为:
1
2event: message
data: 这是消息内容\n\n
与WebSocket的比较
特性 | SSE | WebSocket |
---|---|---|
通信方向 | 单向(服务器→客户端) | 双向 |
协议 | HTTP | 独立的ws/wss协议 |
数据格式 | 文本 | 文本或二进制 |
自动重连 | 支持 | 需要手动实现 |
复杂度 | 简单 | 较复杂 |
浏览器支持 | 广泛(除IE) | 广泛 |
适用场景
SSE 非常适合以下场景:
- 实时通知系统
- 新闻/股票行情推送
- 社交媒体动态更新
- 实时日志监控
- 需要简单实时功能的场景
注意事项
- 浏览器兼容性:大多数现代浏览器支持,但IE不支持
- 连接限制:浏览器对每个源的SSE连接数有限制(通常6个)
- 代理问题:某些代理服务器可能缓冲SSE流
- 数据格式:仅支持文本,不支持二进制数据
SSE 提供了一种轻量级的实时通信解决方案,在不需要双向通信的场景下,比WebSocket更简单易用。
代码示例(阻塞式):
扩展:像集成微信扫码登录这种,可以通过SSE的方式替代前端轮询扫码登录状态的大量无效请求开销。大致流程就是:前端生成的唯一设备id,请求登录二维码,后端返回二维码并将设备id作为SSE连接id,然后启动SSE线程。前端启动SSE事件监听,前后端心跳测试正常。登录成功后,向前端发送登录成功事件通知,前端跳转到登录页。
服务端(后端)
Maven依赖
1 |
|
spring配置文件
application.yaml
1 |
|
跨源配置
Webconfig.java
1 |
|
异常类
1 |
|
存储连接
使用ConcurrentHashMap存储
1 |
|
心跳任务
用来检测对方是否还存在
1 |
|
SSE业务类
1 |
|
Controller
1 |
|
1 |
|
客户端(前端)
login.html
1 |
|
index.html
1 |
|
相关示例参考:https://github.com/zuster/my-demo-springboot-sse?tab=readme-ov-file
代码示例(响应式):
待本人以后学习完响应式编程后,再来完善。