简介:本文系统讲解SSE(Server-Sent Events)技术,从概念定义、HTTP协议基础、工作原理到典型应用场景与选型注意事项,帮助开发者快速理解这一服务器单向实时推送技术,掌握其与轮询、WebSocket等方案的差异,为实时通信技术选型提供清晰参考。
SSE,全称 Server-Sent Events(服务器发送事件),是一种基于 HTTP 协议的服务器向客户端单向推送数据流的技术。它允许服务端在已经建立的 HTTP 连接上持续向客户端发送文本格式的事件流,客户端无需反复发起请求即可持续接收服务端推送的数据。
从技术定位上看,SSE 并不是一个独立于 HTTP 的全新协议,而是构建在标准 HTTP/1.1 协议之上的一种特定用法和扩展能力。可以将其理解为 HTTP 协议的一种”长连接 + 流式响应”组合模式:服务端通过设置特定的响应头,声明本次响应为事件流(text/event-stream),随后保持连接不关闭,持续写入数据;客户端则通过专门的 EventSource 接口接收并解析这些数据。
用一句话概括其技术本质:
SSE = HTTP 扩展响应头 + Keep-Alive 长连接 + 文本事件流格式
它解决的核心问题是:在只需要”服务器向客户端”单向传递数据的场景下,提供一种比轮询更高效、比双向协议更轻量的实时推送方式。
在实时数据推送需求出现之前,客户端获取服务端数据主要依赖两种方式:
传统短轮询:客户端按固定间隔反复发起 HTTP 请求,询问服务端是否有新数据。这种方式实现简单,但存在明显缺陷——大量请求在无数据时也是空转,造成带宽和服务器资源的浪费;同时轮询间隔决定了数据延迟,实时性难以保证。
长轮询:客户端发起请求后,服务端在没有数据时保持连接挂起,直到有数据或超时才返回,客户端收到响应后立即发起下一次请求。长轮询减少了空转请求,但每次数据传递后仍需重新建立连接,连接开销和实现复杂度依然较高。
SSE 的价值在于:它在 HTTP 语义范围内提供了一种”一次连接、持续推送”的机制。连接建立后,服务端可以随时向客户端写入数据,数据到达即被推送,延迟低;同时由于复用标准 HTTP 协议,它天然穿透大多数代理、网关和防火墙,部署成本低,客户端实现也非常简单。
对于只需要单向数据流的场景——如实时通知、日志流、进度更新、行情推送、AI 生成内容的流式输出等——SSE 提供了一种简单、可靠且易于落地的实时推送方案。
SSE 的运行依赖以下几个关键组成部分:
Content-Type: text/event-stream,并通常携带 Cache-Control: no-cache、Connection: keep-alive 等头部,表明这是一个持续的事件流。SSE 的消息体是纯文本,采用行式结构,常见字段包括:
data:消息数据内容,可多行,多行时以换行拼接;event:自定义事件类型名称,客户端可按事件名分别监听;id:消息标识,用于断线重连时通过 Last-Event-ID 请求头告知服务端已接收位置;retry:指定重连等待时间(毫秒)。一个示意性的消息格式如下:
event: messageid: 1024data: {"status": "processing", "progress": 45}data: 这是一条普通消息
每条消息以一个空行结束,客户端据此切分消息边界。
const source = new EventSource('/api/stream');source.onmessage = (e) => {console.log('收到数据:', e.data);};source.addEventListener('progress', (e) => {console.log('进度事件:', e.data);});source.onerror = () => {console.log('连接异常,等待自动重连');};
function handleStream(request, response):response.setHeader("Content-Type", "text/event-stream")response.setHeader("Cache-Control", "no-cache")response.setHeader("Connection", "keep-alive")while connectionOpen:data = waitForNewData()if data exists:response.write("id: " + data.id + "\n")response.write("data: " + data.payload + "\n\n")else:response.write(": keep-alive\n\n") // 注释行维持连接
上述伪代码体现了 SSE 服务端的核心逻辑:声明流式响应头、保持连接、按格式写入消息,并通过注释行或心跳维持连接活跃。
SSE 与轮询:轮询由客户端驱动,反复请求;SSE 由服务端驱动,一次连接持续推送。后者在实时性和资源效率上更优,但需要服务端支持长连接。
SSE 与 WebSocket:WebSocket 是独立的双向通信协议,支持客户端与服务端互相发送消息,适合聊天、协同编辑、游戏等强交互场景;SSE 是单向的、基于 HTTP 的轻量方案,适合纯推送场景。二者不是替代关系,而是按交互方向需求选型。
SSE 与长轮询:长轮询每次收到数据后连接结束、需重新发起;SSE 连接持续存在,数据可连续推送,且具备标准化的事件格式与重连语义。
id 字段实现断点续传时,需保证 id 的生成规则稳定且可追溯。SSE 是一种建立在 HTTP 协议之上的服务器单向实时推送技术,其本质是”HTTP 流式响应 + 长连接保持 + 标准化文本事件格式”。它以极低的接入成本,为单向实时数据推送场景提供了简单可靠的解决方案,尤其在 AI 流式输出、实时通知、进度订阅等场景中表现突出。
理解 SSE 的关键,在于明确其适用边界:它擅长”服务器推、客户端收”的单向流式通信,而非双向交互;它复用了 HTTP 生态的兼容性与易用性,但也因此继承了连接管理与中间层超时等工程约束。在技术选型时,结合数据方向、实时性要求、连接规模与部署环境综合判断,才能让 SSE 发挥出应有的价值。