早期网站仅展示静态内容,而如今我们更期望:实时更新 、即时聊天 、通知推送 和动态仪表盘。
那么要如何实现实时的用户体验呢?三大经典技术各显神通:
- • SSE (Server-Sent Events):轻量级单向数据流
- • WebSocket:双向全双工通信
- • Long Polling(长轮询):传统过渡方案
假设目前有三个业务场景,需要实现数据实时更新:
- • 股票交易仪表盘
- • 即时聊天平台
- • 实时新闻推送
面对这些需求,我们应该如何决策选择合适的方案呢?
下面让我们从架构、性能和扩展性角度一起探讨一下。
什么是长轮询?
原理解析
客户端持续询问服务器:
- • "有更新吗?"
- • "没有"
- • "现在呢?"
- • "还是没有"
- • "现在呢?"
- • "有了!"
就像在吃饭排队叫号的时候,站在店门口每隔5分钟询问是否到你一样,效率低下。
Spring Boot实现(长轮询式REST端点):
@GetMapping("/updates")
public ResponseEntity<String> getUpdate() {
// 模拟延迟或等待事件
return ResponseEntity.ok("最新更新!");
}
✔ 优点:
- • 实现简单(标准REST)
- • 兼容性最佳
✘ 缺点:
- • 高延迟
- • 资源浪费(大量空请求)
- • 扩展性差
适用场景
当无法使用WebSocket或SSE 且需要支持老旧浏览器或代理时使用,一般常见于大型企业的遗留系统中使用。
什么是SSE?
原理解析
客户端建立连接后:
- • "持续监听中..."
- • 服务器随时推送:
- • "新事件1"
- • "新事件2"
- • "连接保持"
仅支持服务器到客户端的单向通信,适合实时数据流。
Spring Boot实现(SSE端点):
@GetMapping("/stream")
public SseEmitter stream() {
SseEmitter emitter = new SseEmitter();
// 异步推送更新
emitter.send("实时更新!");
return emitter;
}
✔ 优点:
- • 轻量(基于HTTP/1.1)
- • 兼容多数代理
- • 自动重连机制
✘ 缺点:
- • 单向通信
- • 部分环境支持有限
- • 控制粒度较粗
适用场景
需要简单高效的服务器到客户端更新(如:股票行情、实时比分、状态仪表盘、监控系统等)。
什么是WebSocket?
原理解析
建立双向通道实现实时对话:
- • 服务器:"Bob有新消息"
- • 客户端:"收到!...."
类似对讲机的全双工通信模式。
Spring Boot配置与实现
@Configuration
@EnableWebSocket
publicclassWebSocketConfigimplementsWebSocketConfigurer {
publicvoidregisterWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(newMyHandler(), "/ws").setAllowedOrigins("*");
}
}
// 处理器
publicclassMyHandlerextendsTextWebSocketHandler {
@Override
protectedvoidhandleTextMessage(WebSocketSession session, TextMessage message) {
session.sendMessage(newTextMessage("回显:" + message.getPayload()));
}
}
✔ 优点:
- • 双向通信
- • 低延迟
- • 可通过消息中间件扩展
✘ 缺点:
- • 代理兼容性问题
- • 扩展复杂度高
- • 需维持长连接
适用场景
适用于聊天室、游戏、协作应用等需要双向交互的场景。
对比小结
最后,结合上面的分析,对于文章开头的业务场景,最终选型方案可以是:
- • 股票交易仪表盘:SSE
- • 即时聊天平台:WebSocket
- • 实时新闻推送(遗留系统):Long Polling
当然,技术选型需因地制宜,具体还是要根据实际场景来选择最优方案!
SSE适用场景总结:
Server-Sent Events(SSE)是一种允许服务端主动向客户端推送实时数据的技术,基于 HTTP 长连接实现,适用于需要单向实时通信的场景。以下是 SSE 服务端的典型应用场景及优势分析:
一、实时数据推送
场景特点 :需要服务端主动向客户端发送更新数据,客户端被动接收(单向通信)。
典型场景 :
- 股票行情 / 金融数据
-
- 服务端实时获取股票价格、交易数据等,主动推送给前端展示,避免客户端频繁轮询消耗资源。
- 优势:低延迟、轻量级(相比 WebSocket 更简单,适合单向数据)。
- 新闻 / 动态更新
-
- 社交媒体、资讯平台实时推送新消息、公告或用户动态,如微博热搜更新、头条新闻推送。
- 监控与仪表盘
-
- 服务器状态监控、工业设备传感器数据(如温度、压力)实时展示,运维人员通过仪表盘实时查看异常告警。
二、通知与消息系统
场景特点 :需要即时通知用户,无需用户主动请求。
典型场景:
- 即时通信(IM)通知
-
- 邮件、短信、站内信的新消息提醒(如微信新消息通知),服务端主动推送通知内容至客户端。
- 订单状态更新
-
- 电商平台中,订单支付成功、发货、物流状态变更时,服务端实时通知用户客户端或商家后台。
- 系统告警
-
- 服务器故障、网络异常、安全事件等告警信息,第一时间推送给运维人员的监控终端。
三、实时协作与多人互动
场景特点 :多人协同操作时,需要实时同步状态。
典型场景:
- 在线文档协作
-
- 类似 Google Docs、飞书文档的多人编辑场景,用户 A 修改内容后,服务端主动将变更推送给其他协作用户 B、C,实现实时同步。
- 实时投票 / 问答互动
-
- 在线会议、直播中的投票结果实时展示,或答题系统中实时更新用户排名和答案统计。
- 游戏实时状态
-
- 轻量级多人游戏(如网页端卡牌游戏、实时对战游戏)中,服务端推送玩家动作、游戏状态变更等数据。
四、日志与审计追踪
场景特点 :需要实时记录和展示操作日志,供审计或监控使用。
典型场景:
- 后台管理系统日志监控
-
- 管理员在后台查看实时操作日志(如用户登录记录、数据修改记录),服务端主动推送新日志条目。
- 金融交易审计
-
- 银行、证券等系统中,实时记录并推送交易日志,供合规部门审计或风控系统分析。
五、事件驱动的异步处理反馈
场景特点 :客户端发起异步请求后,服务端处理完成后主动返回结果。
典型场景:
- 文件上传 / 处理结果通知
-
- 用户上传大文件后,服务端在文件处理完成(如转码、压缩)后,通过 SSE 推送处理结果(成功 / 失败)及文件访问地址。
- 长任务状态查询
-
- 批量数据导入、复杂计算任务(如报表生成)的进度更新,服务端主动推送任务完成百分比或状态信息。
六、与 WebSocket 的对比及适用选择
|----------|-----------------------|----------------------|
| 维度 | SSE | WebSocket |
| 协议 | 基于 HTTP,单向通信(服务端→客户端) | 独立协议,双向通信(全双工) |
| 复杂度 | 实现简单,服务端无需处理客户端请求 | 需要处理双向消息,复杂度较高 |
| 兼容性 | 主流浏览器原生支持(无需额外库) | 需要 JavaScript 库或框架支持 |
| 流量消耗 | 轻量级,数据格式简单(文本流) | 可传输二进制数据,适合高频通信 |
| 典型场景 | 单向实时推送(如新闻、通知) | 双向互动(如聊天、游戏、实时协作) |
选择建议:
- 若只需单向推送,优先选 SSE(开发成本低、兼容性好)。
- 若需要双向通信(如聊天、控制指令),选 WebSocket。
七、SSE 的优势与局限
优势:
- 简单易用 :基于 HTTP,服务端实现难度低,客户端通过原生
EventSource
API 即可接入。 - 低延迟:长连接保持,避免轮询的 "请求 - 响应" 延迟。
- 节省资源 :相比轮询减少 HTTP 请求次数,降低服务端压力。
局限:
- 单向通信:无法支持客户端主动向服务端发送消息(需配合其他机制,如独立 HTTP 接口)。
- 浏览器限制 :不支持跨域(需服务端配置
Access-Control-Allow-Origin
),且无法在 Node.js 等非浏览器环境中使用。
总结
SSE 服务端适用于单向实时数据推送 场景,如实时通知、状态更新、日志监控等。其轻量级、低复杂度的特性使其成为替代轮询的高效方案,尤其适合不需要双向通信的业务场景。在实际开发中,可结合 Spring Boot、Node.js 等框架快速实现,配合客户端EventSource
完成实时通信。