SSE的特点、场景与技术解析
在实时交互需求日益增长的 Web 开发领域,除了常见的 HTTP、WebSocket,Server - Sent Events(SSE,服务器发送事件 )凭借其独特的单向持续推送能力,在特定场景中发挥着关键作用。本文将深入剖析 SSE,带你了解它的核心特点、适用场景以及与其他通信方式的差异。
一、SSE 是什么?
SSE 是一种基于 HTTP 协议的 Web API,允许服务器主动向客户端持续推送实时数据。从协议层面看,它利用 HTTP 长连接,让服务器能以 “流” 的形式,将更新数据不断发送给客户端,无需客户端频繁发起请求查询。
简单理解,就像你订阅了一个实时资讯频道,服务器是内容发布方,一旦有新消息(如监控系统的状态变更、股票行情波动 ),就通过这条 “专属通道” 直接推送给你,而你作为客户端只需保持接收状态即可。
二、SSE 的核心特点
(一)单向推送
SSE 聚焦于 “服务器到客户端” 的单向数据传输。这意味着客户端主要是数据接收方,服务器主动掌控数据推送节奏。比如实时监控系统中,传感器数据上传到服务器后,服务器通过 SSE 直接把最新监控指标(温度、压力等 )推给客户端展示,客户端无需反向给服务器发请求要数据,简化了交互逻辑。
(二)基于 HTTP 长连接
依托 HTTP 协议建立长连接,无需额外复杂握手流程。与普通 HTTP 短连接(请求 - 响应后断开 )不同,SSE 的长连接会持续保持,只要双方不主动关闭,服务器就能随时发数据。这既利用了 HTTP 协议的通用性(防火墙、代理通常对 HTTP 友好 ),又实现了实时性需求。
(三)自动重连机制
客户端在与服务器连接意外中断时,会自动尝试重新建立连接。这一特性保障了通信的稳定性,比如网络波动导致连接暂时断开,SSE 客户端无需手动编写重连逻辑,就能自行恢复连接,继续接收后续推送的数据。
三、SSE 的适用场景

(一)实时监控系统
像工厂设备监控,服务器实时采集设备运行参数(转速、温度 ),通过 SSE 持续推送给监控大屏或管理端。一旦设备参数异常,能第一时间在客户端呈现,便于运维人员及时响应。
(二)股票行情更新
金融交易平台中,股票价格、成交量等数据瞬息万变。SSE 可让服务器把最新行情数据不断推送给投资者客户端,保证用户看到近乎实时的股价波动,辅助交易决策。
(三)消息通知类应用
比如站内信、系统公告,当服务器端有新消息产生(如用户收到新评论、平台发布重要通知 ),通过 SSE 直接推送给客户端,实现消息的实时触达,提升用户体验。
四、SSE 与其他通信方式的差异
(一)对比普通 HTTP
普通 HTTP 是 “客户端主动查询,服务器被动响应” 模式,适合浏览网页、查询静态或低频更新数据场景。而 SSE 是服务器主动推送,无需客户端反复发请求,更贴合实时性需求场景。例如查询历史订单用普通 HTTP 即可,但获取实时订单状态变更就得靠 SSE 持续推送。
(二)对比 WebSocket
WebSocket 主打 “双向高频交互”,客户端和服务器可随时互发消息,像在线聊天、实时协作(多人文档编辑 )这类场景,双方需要频繁收发指令和数据,WebSocket 更擅长。但 SSE 专注单向推送,实现更简单(基于 HTTP ,无需额外协议支持 ),对于只需服务器发数据给客户端的场景,SSE 轻量化优势明显,开发成本更低。
五、SSE 的简单实现(分别以 Js和Java 为例 )
(一)服务器端(Node.js + Express )
const express = require('express');
const app = express();
// 处理 SSE 请求
app.get('/sse', (req, res) => {
// 设置响应头,标识为 SSE 类型
res.setHeader('Content - Type', 'text/event - stream');
res.setHeader('Cache - Control', 'no - cache');
res.setHeader('Connection', 'keep - alive');
// 模拟持续推送数据,每隔 2 秒发一次
const timer = setInterval(() => {
const data = `data: ${new Date().toLocaleTimeString()}\n\n`;
res.write(data);
}, 2000);
// 连接关闭时清除定时器
req.on('close', () => {
clearInterval(timer);
});
});
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
或
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.time.LocalTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@RestController
public class SseController {
// 模拟 SSE 推送间隔
private static final long SEND_INTERVAL = 2; // 秒
@GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter handleSse() {
SseEmitter emitter = new SseEmitter(60_000L); // 设置超时时间
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
try {
// 模拟每隔 2 秒推送一次数据
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
try {
String data = LocalTime.now().toString();
emitter.send(data);
} catch (IOException e) {
emitter.complete();
}
}, 0, SEND_INTERVAL, TimeUnit.SECONDS);
// 客户端断开连接时取消推送任务
emitter.onCompletion(() -> {
future.cancel(true);
executor.shutdown();
});
emitter.onTimeout(() -> {
future.cancel(true);
executor.shutdown();
emitter.complete();
});
} catch (Exception e) {
emitter.completeWithError(e);
}
return emitter;
}
}
(二)客户端(浏览器 JavaScript )
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SSE Demo</title>
</head>
<body>
<div id="data">等待推送数据...</div>
<script>
const eventSource = new EventSource('/sse'); // Js
const eventSource = new EventSource('http://localhost:8080/sse'); // Java
eventSource.onmessage = function (event) {
document.getElementById('data').innerText = `最新推送数据:${event.data}`;
};
eventSource.onerror = function (error) {
console.error('SSE 连接出错:', error);
document.getElementById('data').innerText = 'SSE 连接已断开或出错';
};
</script>
</body>
</html>
大概的效果:
最新推送数据:15:30:00
最新推送数据:15:30:02
最新推送数据:15:30:04
...
上述代码中,服务器端通过设置特定响应头开启 SSE 通信,定时推送当前时间;客户端用 EventSource
对象建立连接,监听 onmessage
事件接收数据并展示,简单实现了 SSE 单向推送功能。
六、总结
SSE 以其单向持续推送、基于 HTTP 长连接、自动重连等特性,在实时监控、行情更新等场景中成为高效选择。与普通 HTTP 、WebSocket 各有分工,开发者可根据实际需求(单向 / 双向、实时性强度 )灵活选用。随着实时交互场景不断丰富,SSE 凭借轻量化、针对性强的优势,会持续在 Web 实时通信领域占据一席之地,值得大家深入了解与应用 。