SpringBoot+SSE实现实时推送,告别轮询,实时消息推送更高效。
在传统的Web应用中,实时消息推送一直是个技术难题。最常见的轮询方式虽然简单,但存在严重的性能问题:假设一个电商平台有100万用户在线查看订单状态,如果每个用户每5秒轮询一次,就会产生每秒20万次请求,其中大部分都是无效请求(因为订单状态并没有变化)。这不仅消耗大量服务器资源,还会导致用户体验不佳。
SSE(Server-Sent Events)作为HTML5规范的一部分,专门为服务器向客户端推送消息而设计。它基于HTTP协议,采用单向通信模式,具有以下核心优势:
- 轻量级:基于标准HTTP协议,无需额外协议升级
- 自动重连:连接断开后浏览器会自动尝试重连,无需手动处理
- 事件ID支持:通过Last-Event-ID实现断线续传功能
- 原生支持:浏览器原生支持,无需引入额外库
- 实现简单:相比WebSocket,开发成本大幅降低
SpringBoot集成SSE实现步骤
1. 基础控制器实现
首先创建一个SSE控制器,使用Spring的SseEmitter类:
@RestControllerpublic class SseController { @GetMapping(value = "/sse/notifications", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter createSseConnection() { // 设置超时时间(-1表示永不超时) SseEmitter emitter = new SseEmitter(-1L); try { emitter.send(SseEmitter.event() .name("connect") .data("连接成功")); } catch (IOException e) { emitter.completeWithError(e); } // 添加连接关闭回调 emitter.onCompletion(() -> { log.info("SSE连接关闭"); }); emitter.onTimeout(() -> { log.warn("SSE连接超时"); emitter.complete(); }); return emitter; }}2. 消息推送服务
创建一个专门的消息推送服务,管理所有SSE连接:
@Servicepublic class SseNotificationService { private final Map<String, SseEmitter> sseEmitters = new ConcurrentHashMap<>(); public SseEmitter createConnection(String userId) { SseEmitter emitter = new SseEmitter(-1L); sseEmitters.put(userId, emitter); try { emitter.send(SseEmitter.event() .name("connect") .data("连接建立成功")); } catch (IOException e) { emitter.completeWithError(e); } // 连接关闭时清理 emitter.onCompletion(() -> { sseEmitters.remove(userId); }); return emitter; } public void sendNotification(String userId, NotificationMessage message) { SseEmitter emitter = sseEmitters.get(userId); if (emitter != null) { try { emitter.send(SseEmitter.event() .name("notification") .data(JSON.toJSONString(message))); } catch (IOException e) { sseEmitters.remove(userId); } } }}3. 核心配置说明
在配置文件中添加关键配置:
server: tomcat: threads: max: 200 connection-timeout: 60000spring: mvc: async: request-timeout: 60000这些配置确保服务器能够处理大量长连接,并设置合理的超时时间。
实际应用场景

SSE特别适合以下场景:
- 订单状态更新:用户下单后实时显示订单处理进度
- 系统通知推送:重要系统消息的及时通知
- 实时日志查看:运维人员监控系统运行状态
- 股票价格更新:金融类应用的实时价格推送
以订单状态推送为例,可以通过事件监听机制实现:
@EventListenerpublic void handleOrderStatusChange(OrderStatusChangeEvent event) { Order order = event.getOrder(); sseService.sendNotification(order.getUserId(), SseMessage.builder() .type("order_status_change") .data(order) .build());}与其他推送技术对比
表格
复制
技术方案 | 优势 | 劣势 | 适用场景 |
轮询 | 实现简单,兼容性好 | 资源浪费,延迟高 | 低频更新,兼容性要求高 |
SSE | 简单高效,自动重连 | 单向通信 | 服务器推送,实时通知 |
WebSocket | 双向通信,实时性强 | 实现复杂,协议升级 | 聊天应用,双向交互 |
注意事项与最佳实践
- 连接管理:合理设置超时时间,定期清理无效连接,防止内存泄漏
- 消息设计:统一消息格式,控制消息大小,使用类型标识便于客户端处理
- 错误处理:实现优雅降级,SSE不可用时回退到轮询方式
- 安全考虑:添加认证授权机制,确保消息推送的安全性
- 性能优化:使用线程池异步发送,批量推送提升效率
总结
SSE是实现服务器推送消息的理想方案,特别适合单向实时推送场景。相比传统轮询,它能大幅减少无效请求;相比WebSocket,它实现更简单、维护成本更低。在实际项目中,合理使用SSE技术,能够为用户提供更流畅的实时体验,同时降低系统复杂度和资源消耗。
推荐标签
#SpringBoot# #SSE技术# #实时推送# #消息推送# #后端开发#
感谢关注【AI码力】,获取更多技术秘籍!
文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有