当前位置: 首页 > java >正文

SSE详解

一、什么是 SSE?

SSE(Server-Sent Events)是一种基于 HTTP 协议的服务器推送技术,允许服务器主动向客户端(如浏览器)推送实时数据。与传统的轮询(Polling)或长轮询(Long Polling)不同,SSE 通过单一的持久连接实现数据的实时传输,客户端无需频繁发起请求。

二、SSE 的核心特点
  1. 单向通信
    SSE 是单向的,服务器可以主动推送数据到客户端,但客户端无法直接通过 SSE 向服务器发送数据(如果需要双向通信,需结合其他技术如 WebSocket)。

  2. 基于 HTTP 协议
    SSE 使用标准的 HTTP 协议,无需额外的协议或端口配置,兼容性好,易于实现。

  3. 轻量级
    相比 WebSocket,SSE 的实现更简单,代码量更少,适合简单的实时数据推送场景。

  4. 自动重连
    如果连接断开,浏览器会自动尝试重新连接,开发者无需手动处理重连逻辑。

  5. 支持事件类型
    服务器可以发送不同类型的事件,客户端可以根据事件类型执行不同的操作。

  6. 支持消息 ID
    每条消息可以包含一个唯一的 ID,用于断线重连后恢复消息流。

三、SSE 的工作原理
  1. 客户端发起请求
    客户端通过 JavaScript 创建一个 EventSource 对象,并指定服务器的 URL。

    const eventSource = new EventSource('/sse-endpoint');
    
  2. 服务器响应
    服务器返回的响应头需要包含以下内容:

    Content-Type: text/event-stream
    Cache-Control: no-cache
    Connection: keep-alive
    

    响应体由一系列事件组成,每个事件以 \n\n 分隔。

  3. 数据格式
    每个事件可以包含以下字段:

    • data: 消息内容(必须)
    • event: 事件类型(可选)
    • id: 消息 ID(可选)
    • retry: 重连时间(可选,单位:毫秒)

    示例:

    data: Hello, world!
    event: message
    id: 123
    retry: 10000data: Another message
    
  4. 客户端接收数据
    客户端可以通过以下方式监听事件:

    eventSource.onmessage = (event) => {console.log('Received:', event.data);
    };eventSource.addEventListener('message', (event) => {console.log('Custom event:', event.data);
    });
    
四、SSE 的应用场景
  1. 实时通知
    如社交媒体的实时消息提醒、邮件通知等。

  2. 实时数据更新
    如股票行情、天气预报、体育比分等。

  3. 日志监控
    实时推送服务器日志或应用状态。

  4. 进度更新
    如文件上传进度、任务执行进度等。

五、SSE 与 WebSocket 的对比
特性SSEWebSocket
通信方向单向(服务器到客户端)双向(全双工)
协议基于 HTTP独立协议(ws:// 或 wss://)
实现复杂度简单较复杂
数据格式文本(UTF-8)支持文本和二进制
自动重连支持需手动实现
适用场景简单的实时数据推送复杂的双向实时通信(如聊天应用)
六、SSE 的优缺点

优点

  1. 实现简单,代码量少。
  2. 基于 HTTP,兼容性好。
  3. 自动重连机制,可靠性高。
  4. 适合单向实时数据推送场景。

缺点

  1. 仅支持单向通信,无法满足双向实时通信需求。
  2. 只能传输文本数据,二进制数据需编码后传输。
  3. 浏览器兼容性有限(IE 不支持)。
七、SSE 的实现示例

服务器端(Node.js)

const express = require('express');
const app = express();app.get('/sse-endpoint', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');res.setHeader('Cache-Control', 'no-cache');res.setHeader('Connection', 'keep-alive');let counter = 0;const interval = setInterval(() => {counter++;res.write(`data: ${counter}\n\n`);}, 1000);req.on('close', () => {clearInterval(interval);res.end();});
});app.listen(3000, () => {console.log('Server running on port 3000');
});

客户端

const eventSource = new EventSource('http://localhost:3000/sse-endpoint');eventSource.onmessage = (event) => {console.log('Received:', event.data);
};eventSource.onerror = (error) => {console.error('Error:', error);
};
八、SSE与Springboot应用实例

在Spring Boot中应用SSE(Server-Sent Events)可实现高效的实时数据推送,适用于股票行情、通知推送等单向通信场景。以下是具体实践方案及关键点:

1. 基础实现步骤
  • 添加依赖:确保项目中包含spring-boot-starter-web依赖。
  • 创建控制器:使用SseEmitter处理客户端连接,通过@GetMapping注解定义SSE端点,设置produces = MediaType.TEXT_EVENT_STREAM_VALUE
  • 消息推送:通过SseEmitter.send()方法发送数据,支持文本或JSON格式。
  • 客户端监听:前端使用EventSource对象连接SSE端点,通过onmessageaddEventListener监听事件。
2. 核心代码示例
服务端代码
@RestController
@RequestMapping("/sse")
public class SseController {private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();@GetMapping("/connect")public SseEmitter connect(@RequestParam String userId) {SseEmitter emitter = new SseEmitter(60_000L);emitters.put(userId, emitter);emitter.onCompletion(() -> emitters.remove(userId));emitter.onTimeout(() -> emitters.remove(userId));// 模拟异步发送数据new Thread(() -> {try {for (int i = 0; i < 10; i++) {emitter.send(SseEmitter.event().data("Message " + i).id(String.valueOf(i)).name("sse-event"));Thread.sleep(1000);}emitter.complete();} catch (Exception e) {emitter.completeWithError(e);}}).start();return emitter;}// 广播消息示例public void broadcast(String message) {emitters.forEach((id, emitter) -> {try {emitter.send(message);} catch (IOException e) {emitters.remove(id);}});}
}
前端代码
<script>const eventSource = new EventSource('/sse/connect?userId=123');eventSource.onmessage = (event) => {console.log('Received:', event.data);};eventSource.addEventListener('sse-event', (event) => {console.log('Custom event:', event.data);});eventSource.onerror = () => {console.error('Connection error');eventSource.close();};
</script>
3. 关键优化点
  • 连接管理:使用ConcurrentHashMap存储连接,及时移除无效连接,避免内存泄漏。
  • 超时设置:合理设置SseEmitter的超时时间(如60秒),避免长时间占用资源。
  • 心跳机制:定期发送空消息(如comment("heartbeat"))保持连接活跃,防止超时断开。
  • 异步处理:通过线程池或@Async异步发送消息,避免阻塞主线程。
  • 跨域配置:在WebMvcConfigurer中配置CORS,允许前端跨域访问。
4. 进阶场景
  • 消息分组:通过URL参数(如groupId)区分客户端组,实现定向推送。
  • 消息广播:结合SimpMessagingTemplateRedisson实现多客户端广播。
  • 结构化数据:发送JSON数据时,设置MediaType.APPLICATION_JSON并解析前端数据。
5. 注意事项
  • 单向通信:SSE仅支持服务器到客户端的单向推送,如需双向通信,需结合WebSocket。
  • 浏览器兼容性:IE不支持SSE,需提供降级方案(如轮询)。
  • 性能调优:调整Tomcat线程池配置,避免高并发下资源耗尽。
6. 对比WebSocket
特性SSEWebSocket
通信方向单向(服务器→客户端)双向(全双工)
协议基于HTTP独立协议(ws://或wss://)
实现复杂度简单较复杂
适用场景实时通知、数据更新聊天、游戏等双向实时通信

SSE在Spring Boot中适合实现简单的实时数据推送,具有实现简单、兼容性好等优点。通过合理管理连接、设置超时和心跳机制,可确保系统的稳定性和可靠性。对于需要双向通信的场景,建议结合WebSocket使用。

八、总结

SSE 是一种简单高效的服务器推送技术,适合单向实时数据推送场景。它的实现简单、兼容性好,但在双向通信和二进制数据传输方面存在局限性。在实际应用中,开发者应根据具体需求选择 SSE 或 WebSocket。

在这里插入图片描述

http://www.xdnf.cn/news/13981.html

相关文章:

  • 前端跨域解决方案(1):什么是跨域?
  • 【Bluedroid】蓝牙启动之 GAP_Init 流程源码解析
  • 国际数字影像产业园:数字技术赋能 引领产业升级变革
  • 自动化基础随心记三-zabbix
  • AI 重构代码实战:如何用飞算 JavaAI 快速升级遗留系统?
  • python编程基础
  • aflplusplus:开源的模糊测试工具!全参数详细教程!Kali Linux教程!(二)
  • 智能客服系统开发方案:RAG+多智能体技术实现
  • 机器学习 vs 深度学习:区别与应用场景全解析
  • OpenSIPS3.4 load balancer fetch_freeswitch_stats 测试
  • 计算机是怎么跑起来的第四章
  • 性能优化相关
  • 杜勇书籍摘抄
  • 【linux】驱动学习问题及解决方法
  • Pytorch框架——自动微分和反向传播
  • ⻋载摄像头图像传感器分析
  • vue3 解析excel字节流文件 以表格形式显示页面上 带公式
  • 页面弹窗适配问题
  • Vue权限控制小妙招:动态渲染列表的优雅实现
  • 日常运维问题汇总_43
  • 【Zephyr 系列 23】构建 Web OTA 平台与远程运维工具链:从固件上传到设备在线升级全流程
  • golang使用tail追踪文件变更
  • 解决 Java 与 JavaScript 之间特殊字符传递问题的终极方案
  • ReentrantLock和RLock
  • 新增一个战斗角色
  • n8n实战:自动化生成AI日报并发布
  • USB串口通信、握手协议、深度学习等技术要点
  • window显示驱动开发—为 DirectX VA 2.0 扩展模式提供功能(一)
  • leetcode 2616. 最小化数对的最大差值 中等
  • 【备忘】PHP web项目一般部署办法