简介:Server-Sent Events(SSE)是一种基于标准HTTP协议的服务器单向推送技术,可在一条长连接上持续向客户端发送事件流。本文系统讲解SSE的定义、报文格式、工作流程与断线重连机制,对比轮询和WebSocket的差异,并梳理其在LLM流式输出、实时监控等场景的应用价值与接入注意事项,帮助开发者快速理解并正确选型。
Server-Sent Events(SSE,服务器发送事件)是一种构建在标准HTTP协议之上的服务器到客户端单向推送技术。它允许服务器在接受一次客户端请求后保持响应连接不关闭,并在同一条连接上以流式方式持续发送结构化的事件数据;客户端只需使用浏览器原生的 EventSource 接口,即可像监听普通事件一样接收这些数据。
可以从三个视角理解这一概念:
需要强调的是,SSE的“单向”指的是数据流方向:服务器可以随时推送,但客户端无法通过同一条连接向服务器发送业务数据(重连时携带的协议信息除外)。
传统HTTP遵循“一问一答”模式:客户端发起请求,服务器返回完整响应后连接即结束。当业务需要“服务器有新数据就立刻告知客户端”时,这一模式会出现明显短板,常见应对方式各有代价:
SSE的设计哲学是:既然大量实时场景本质上只需要“服务器→客户端”这一个方向,那就把这一件事用最标准的方式做好——普通HTTP GET请求、一条保持打开的响应连接、约定好的文本格式。由此带来两个直接收益:
SSE协议的核心是一个极简的文本格式。服务器将响应头设置为:
Content-Type: text/event-stream
并建议同时设置不缓存相关响应头,随后持续写出事件块。每个事件块由若干“字段名: 值”形式的行组成,事件与事件之间必须以一个空行(即两个换行符 \n\n)分隔——空行是客户端判定“一个事件结束”的唯一依据。
四个标准字段:
此外,以冒号开头的行是注释行,会被客户端忽略,常被用作心跳保活。
报文示例:
: pingevent: messageid: 1001data: {"delta": "今天天气"}event: messageid: 1002data: {"delta": "不错"}event: doneid: 1003data: [DONE]
一次完整的SSE交互可拆解为六步:
new EventSource("/api/stream"),浏览器自动发起HTTP GET请求,并携带 Accept: text/event-stream 请求头;服务端伪代码(与具体框架无关):
处理 GET /stream:设置 Content-Type: text/event-stream设置不缓存id = 0while 连接保持:data = 等待并获取下一段数据id = id + 1写出 "id: {id}\n"写出 "data: {data}\n\n"刷新输出缓冲
客户端示例:
const es = new EventSource("/api/stream");es.onmessage = (e) => {const chunk = JSON.parse(e.data);appendToUI(chunk.delta);};es.addEventListener("done", () => es.close());es.onerror = () => {// 浏览器会自动重连,这里通常只需做界面提示};
SSE把推送可靠性中最难的两件事直接内建到了协议中:自动重连由浏览器实现,开发者无需手写重试逻辑;断点续传依赖 id 与 Last-Event-ID 的配合——服务器为每个事件赋予单调递增的 id,客户端重连时把最后收到的 id 带回,服务器只需从该 id 之后继续写流即可。这使SSE在弱网环境下的表现明显优于手写轮询或裸长连接方案。当然,服务端需要正确设计 id 的语义与存储,才能保证续传既不丢事件也不重复事件。
| 对比维度 | 轮询 | SSE | WebSocket |
|---|---|---|---|
| 通信方向 | 客户端拉取 | 服务器推送(单向) | 全双工 |
| 协议基础 | 标准HTTP | 标准HTTP | 独立协议(HTTP升级握手) |
| 连接形态 | 反复建立短连接 | 一条长连接 | 一条长连接 |
| 自动重连 | 需自行实现 | 浏览器内置 | 需自行实现 |
| 断点续传 | 无 | id + Last-Event-ID | 需自行设计 |
| 数据类型 | 任意 | UTF-8文本 | 文本与二进制 |
| 基础设施兼容 | 好 | 好,纯HTTP流 | 部分代理需额外配置 |
选型建议可概括为三句话:只需要服务器到客户端的单向实时数据,优先SSE;需要客户端也高频向服务器发数据(聊天、游戏、协同白板),选WebSocket;实时性要求仅为秒级甚至更低,普通轮询足够,不必引入长连接。
: ping)作为心跳;在百度智能云等云环境中部署时,同样建议结合负载均衡与网关的超时参数统一规划心跳间隔;回到定义本身:SSE是一种基于标准HTTP、面向“服务器到客户端”单向事件流推送的轻量级实时技术。它用最小的协议复杂度换取了三样东西——流式传输的即时性、浏览器内置的自动重连与断点续传、以及与现有HTTP基础设施的天然兼容。在LLM流式输出、实时监控、进度通知等单向推送场景中,它通常比WebSocket更经济、比轮询更实时;而在需要双向高频通信的场景中,其边界也十分清晰。理解“单向流、文本事件格式、长连接”这三个关键词,就抓住了SSE的本质。