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

SSE是什么?SSE解决什么问题?在什么场景使用SSE?

        定义:SSE,首先需要明确其全称是 Server-Sent Events(服务器发送事件),它是一种基于 HTTP 协议的服务器向客户端单向推送实时数据的技术标准。与 WebSocket 等双向通信技术不同,SSE 专注于 “服务器到客户端” 的单向实时数据传输,具有轻量、易用、基于现有 HTTP 生态的核心优势。

一、SSE的核心定义:

        SSE的本质是客户端和服务端建立一次持久化的HTTP连接,服务器通过这个连接持续向客户端“流式”发送结构化数据(格式为text/event-stream),客户端实时监听并解析这些数据,实现服务器主动推,客户端被        动收的实时通信。

它的核心特点可总结为:

  • 单向通信:仅支持服务器向客户端推送数据,客户端无法通过同一连接向服务器发送数据(若需客户端交互,需额外用 AJAX/HTTP 请求)。
  • 基于 HTTP:无需建立新的通信协议(如 WebSocket 的 ws:// 协议),可复用现有 HTTP 端口(80/443)、防火墙规则和代理配置,降低部署成本。
  • 持久连接:一次连接可长期保持(默认超时时间可配置),避免频繁建立 / 断开连接的开销。
  • 自动重连:客户端(如浏览器)原生支持断线后自动重连(默认重试间隔 3 秒),无需开发者额外实现。
  • 结构化数据:服务器发送的数据需遵循特定格式(包含 eventdataidretry 等字段),客户端可按字段解析,支持 “事件分类”(如区分 “消息通知”“数据更新” 等事件)。

二、SSE 的核心作用:解决什么问题?

在 SSE 出现前,客户端获取实时数据的常见方案(如 “轮询”“长轮询”)存在明显缺陷,SSE 正是为解决这些问题而生:

        因此,SSE 的核心作用是:以最低成本实现 “服务器到客户端” 的单向实时数据传输,平衡 “实时性”“低开销” 和 “易用性”。

三、SSE 的典型应用场景:什么时候用?

SSE 仅适用于 “服务器需主动向客户端推数据,客户端无需向服务器推数据” 的场景,常见场景包括:

1. 实时通知类场景
  • 业务通知:用户收到的订单状态变更(如 “订单已发货”)、账户余额变动、消息提醒(如 “有人 @你”)。
  • 系统通知:网站公告更新、服务器维护提醒、APP 版本更新提示。
  • 示例:电商平台中,用户下单后,服务器通过 SSE 实时推送 “支付确认→订单审核→商品出库” 的状态变更。
2. 实时数据监控类场景
  • 数据仪表盘:后台系统的实时数据统计(如实时用户在线数、订单成交量、接口调用量),无需页面刷新即可更新。
  • 设备监控:物联网(IoT)场景中,传感器实时上传的温度、湿度、设备运行状态(如服务器 CPU 使用率),客户端通过 SSE 实时展示。
  • 示例:运维人员的监控面板,通过 SSE 实时接收各服务器的内存使用率、磁盘空间数据,异常时即时高亮。
3. 实时内容更新类场景
  • 实时资讯 / Feed 流:新闻网站的 “突发新闻推送”、社交平台的 “好友动态更新”(如朋友圈新内容)、直播平台的 “弹幕”(轻量弹幕场景)。
  • 实时日志:开发 / 测试场景中,服务器实时日志(如接口请求日志、错误日志)通过 SSE 推送到前端页面,无需手动刷新日志页面。
  • 示例:股票行情页面,服务器通过 SSE 每秒推送一次实时股价、涨跌幅数据,客户端实时更新 K 线图。

四、SSE 的技术细节补充(帮助深入理解)

要正确使用 SSE,需了解其关键技术规范:

1. 数据格式要求

服务器发送的数据流必须是 text/event-stream 格式,每行需遵循以下字段规则(字段名区分大小写):

  • data:核心数据内容,可多行(多行需每行加 data:),客户端接收后需拼接;若数据为空,代表 “心跳包”(维持连接)。
    • 示例:data: {"orderId": 123, "status": "已发货"}
  • event:事件类型(可选),用于客户端区分不同类型的推送(如 event: orderStatus 代表订单状态变更,event: notification 代表消息通知)。
    • 示例:event: orderStatus\ndata: {"orderId": 123, "status": "已发货"}
  • id::数据唯一标识(可选),客户端会记录最后一个 id,断线重连时会通过 Last-Event-ID 请求头告知服务器,避免数据丢失。
  • retry::客户端断线后的重试间隔(毫秒,可选),默认 3000ms(3 秒)
  • 空行:每个事件的结束标志(必须有,否则客户端无法解析)。
2. 客户端实现
前端实例:
<template><h3>实时消息:</h3><div id="messageContainer"></div>
</template><script lang="js">// 1. 连接 SSE 接口(注意:需处理跨域,后端需配置 CORS)const userId = "user123";const eventSource = new EventSource(`/sse/notify/${userId}`);// 2. 监听默认事件(无 event 字段的推送)eventSource.onmessage = function(event) {const data = JSON.parse(event.data);showMessage(`默认事件:${data.message}`);};// 3. 监听指定类型事件(对应后端的 event: notification)eventSource.addEventListener('notification', function(event) {const data = JSON.parse(event.data);showMessage(`[${new Date(data.time).toLocaleString()}] ${data.message}`);});// 4. 监听连接打开eventSource.onopen = function() {showMessage("SSE 连接已建立");};// 5. 监听错误(包括断开重连)eventSource.onerror = function(error) {if (eventSource.readyState === EventSource.CLOSED) {showMessage("SSE 连接已关闭,将自动重连...");} else {showMessage("SSE 连接错误: " + error);}};// 辅助函数:显示消息到页面function showMessage(text) {const div = document.createElement('div');div.textContent = text;document.getElementById('messageContainer').appendChild(div);}// 页面关闭时主动断开连接window.onbeforeunload = function() {eventSource.close();};</script>
后端示例:

使用java(Springboot)实现

        第一种:手动通过 HttpServletResponse 构造 SSE 响应格式。使用 ScheduledExecutorService 定时推送消息。通过 PrintWriter 直接写入响应流。

@RestController
public class SSEController {/*** SSE通知接口* produces = MediaType.TEXT_EVENT_STREAM_VALUE 的作用:* 1. 指定响应内容类型为 text/event-stream,这是SSE(Server-Sent Events)的标准MIME类型* 2. 告诉客户端浏览器这是一个SSE流,浏览器会自动建立长连接并监听服务器推送的消息* 3. 确保Spring框架正确处理SSE响应格式** @param userId   用户ID* @param response HTTP响应对象,用于输出SSE数据流*/@GetMapping(value = "/sse/notify/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public void sseNotify(@PathVariable String userId, HttpServletResponse response) {// TODO: 实现SSE推送逻辑response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);response.setCharacterEncoding("UTF-8");response.setHeader("Cache-Control", "no-cache");//缓存控制response.setHeader("Connection", "keep-alive");//保持长连接try {PrintWriter writer = response.getWriter();ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(() -> {try {// 1. 构建 SSE 格式数据(必须遵循规范)// event: 事件类型(可选)writer.write("event: notification\n");
//                    数据内容writer.write("data: {\"userId\":\"" + userId + "\",\"message\":\"新消息推送\",\"time\":" + System.currentTimeMillis() + "}\n");// id: 消息ID(可选,用于重连时定位)writer.write("id:  " + System.currentTimeMillis() + "\n");writer.write("\n");//空行结束一个事件writer.flush();//刷新缓冲区if (writer.checkError()) {throw new IOException("客户端断开连接");}} catch (IOException e) {executor.shutdown(); // 断开连接时停止任务}}, 0, 3, TimeUnit.SECONDS);} catch (Exception e) {e.printStackTrace();}}
}

        第二种:使用 Spring 提供的 SseEmitter 类来处理 SSE 连接。SseEmitter 封装了大部分 SSE 相关的操作,如发送事件、处理连接断开等。

    @GetMapping(value = "/sse/notify/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public SseEmitter sseNotify(@PathVariable String userId) {SseEmitter emitter = new SseEmitter(0L); // 0表示永不超时ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(() -> {try {emitter.send(SseEmitter.event().name("notification").data("{\"userId\":\"" + userId + "\",\"message\":\"新消息推送\",\"time\":" + System.currentTimeMillis() + "}"));} catch (Exception e) {emitter.completeWithError(e);executor.shutdown();}}, 0, 3, TimeUnit.SECONDS);// 连接断开时清理资源emitter.onCompletion(executor::shutdown);emitter.onTimeout(executor::shutdown);return emitter;}

        第三种:使用 AsyncContext 实现异步处理,避免阻塞主线程。通过 request.startAsync() 开启异步处理。结合 ScheduledExecutorService 定时推送消息。

    @GetMapping(value = "/sse/notify/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public void sseNotify(@PathVariable String userId, HttpServletRequest request, HttpServletResponse response) {// 启用异步支持AsyncContext asyncContext = request.startAsync();asyncContext.setTimeout(0); // 设置永不超时response.setContentType("text/event-stream");response.setCharacterEncoding("UTF-8");response.setHeader("Cache-Control", "no-cache");response.setHeader("Connection", "keep-alive");try {PrintWriter writer = response.getWriter();ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(() -> {try {writer.write("event: notification\n");writer.write("data: {\"userId\":\"" + userId + "\",\"message\":\"新消息推送\",\"time\":" + System.currentTimeMillis() + "}\n");writer.write("id: " + System.currentTimeMillis() + "\n");writer.write("\n");writer.flush();if (writer.checkError()) {throw new IOException("客户端断开连接");}} catch (Exception e) {executor.shutdown();asyncContext.complete();}}, 0, 3, TimeUnit.SECONDS);} catch (Exception e) {e.printStackTrace();}}
3. 服务器实现关键点
  • 响应头必须设置:Content-Type: text/event-streamCache-Control: no-cache(禁止缓存)、Connection: keep-alive(保持连接)。
  • 需支持 “流式输出”(不能一次性返回所有数据,需分块发送),不同后端语言实现方式不同(如 Node.js 的 res.write()、Java 的 response.getWriter().write())。
  • 需处理客户端断开连接的 “优雅关闭”(如监听 HTTP 连接关闭事件,释放服务器资源)
4.遇到跨域问题请参考

解决跨域问题https://blog.csdn.net/2302_80222668/article/details/152377377?spm=1001.2014.3001.5502

五、SSE 与 WebSocket 的对比:该怎么选?

很多人会混淆 SSE 和 WebSocket,两者的核心区别决定了适用场景:

结论

  • 若场景是 “单向推数据”(如通知、监控),优先选 SSE(成本低、易实现);
  • 若场景是 “双向交互”(如聊天、多人协同编辑),必须选 WebSocket。

http://www.dtcms.com/a/434460.html

相关文章:

  • 算法偏见的解药:将敏捷“灵魂”注入AI伦理
  • 基于前端+Node.js 的 Markdown 笔记 PDF 导出系统完整实战
  • lesson71:Node.js与npm基础全攻略:2025年最新特性与实战指南
  • 购买域名后 可以做网站么灰色关键词排名优化
  • 专业做家具的网站小程序注册方法
  • OWASP ZAP 工具安全测试介绍
  • Git介绍 常用命令
  • 教育机构作图:含拼团 / 课程封面模板,适配小程序
  • linux内核时间定时器延时
  • 远程安装vps相关软件记录
  • 山东高端网站建设方案宁波网站建设那家好
  • x86_64 centos7.2 上用aarch64-linux-gnu-gcc4.8.5交叉编译qt5.11.3
  • GLib线程池全面解析:原理、应用与性能优化
  • 东莞网站设计网址电影网站建设方案ppt模板下载
  • 51单片机-驱动LCD1602液晶显示屏教程
  • 【C++哲学】面向对象的三大特性之 多态
  • Python - 100天从新手到大师:第二十六天Python操作Word和PowerPoint文件
  • 算法基础 典型题 前缀和
  • 广告网站制作多少钱wordpress修改密码后还是登陆不了
  • 【MySQL】一篇讲透MySQL的MVCC机制!
  • 【开题答辩全过程】以 Web数据挖掘在电子商务中的应用研究为例,包含答辩的问题和答案
  • 网站界面美观度站长素材网站官网
  • 生活的方向,从来没有统一的标准答案——它不是一张固定的地图,也不是一条必须抵达的终点线,更像是你在行走中慢慢校准的“心之所向”。
  • 网站到期时间网站开发小图片
  • Git打tag标签
  • leetcode 494 目标和
  • 网站设置成灰色全球最牛的搜索引擎
  • Apache POI操作Docx文档时踩坑指南
  • K230基础-显示画面
  • 一级a做爰片免费网站 新闻wordpress用户修改文章