恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
计算机编程杂识--9--SSE vs Streamable HTTP
首页
资讯中心
/
计算机编程杂识--9--SSE vs Streamable HTTP
计算机编程杂识--9--SSE vs Streamable HTTP
发布时间:2026/8/28 23:43:27
一、基本概念SSEServer-Sent EventsW3C 标准协议专门用于服务器向客户端单向推送数据流。设计初衷解决服务器需要持续主动向客户端推送数据的问题。如果要断开需要客户端服务器双方提前约定好结束符[任意]然后服务端给客户端发送结束符客户端接收到后close()即可。结束需要程序员自己控制。协议 HTTPContent-Type: text/event-stream 方向 服务器 → 客户端单向 连接 长连接服务器持续推送 客户端APIEventSource浏览器内置Streamable HTTP普通 HTTP 请求 响应体流式返回Chunked Transfer Encoding不是独立协议。设计初衷解决客户端发一次请求服务端需要较长时间生成响应希望边生成边返回的问题。一次请求一次响应就会断开断开时服务器发送完后协议自身会在最后发送一个0\r\n\r\n的结束符。结束不需要程序员自己控制协议 普通 HTTPContent-Type 任意 方向 请求和响应都可以流式半双工 连接 标准 HTTP 请求-响应响应完即释放 客户端APIfetch ReadableStream二、核心区别1. 连接生命周期SSE连接和会话绑定会话没结束连接就不释放 → 独占 Streamable HTTP连接和请求绑定响应完就释放 → 可共享复用 SSE 时间线 |token空等token空等token| ↑ 连接一直占着空等时也不能给别人用 Streamable HTTP 时间线 |token|释放|释放|token|释放|释放|token| ↑↑ ↑↑ 连接空闲可以服务其他客户端的请求2. 断开后的重连行为SSE连接断开 → 浏览器自动重连EventSource 内置行为 Streamable HTTP连接断开 → 程序员自己写重试逻辑SSE 自动重连完整过程T0 客户端const es new EventSource(/stream) → 浏览器发 GET 请求 T1 服务端响应Content-Type: text/event-stream data: 消息1\n\n data: 消息2\n\n T2 连接断开服务端关闭或网络中断 → 浏览器触发 onerror → readyState 从 OPEN(1) 变为 CONNECTING(0) T3 浏览器等待 retry 间隔默认 3 秒 → 浏览器自动重新发 GET 请求代码里没写任何重连逻辑 GET /stream HTTP/1.1 Last-Event-ID: 2 ← 如果之前有 id自动带上 T4 服务端响应 200 text/event-stream → 重连成功继续接收 204 / 404 → 浏览器放弃readyState 变 CLOSED(2)服务端可控制重连间隔服务端发retry: 5000\n\n → 浏览器下次重连等 5 秒 服务端发retry: 0\n\n → 浏览器立即重连3. 结束机制SSE 应用层约定程序员自己定[DONE]、[END] 等 因为 SSE 协议没有正常结束机制 服务端单方面关闭 → 浏览器自动重连 → 没断成 Streamable HTTPHTTP 协议自带结束符0\r\n\r\n框架自动处理 程序员不用关心结束标识 响应体写完 → 框架自动发结束符 → 响应完成SSE 的三种结束方式方式1客户端单方面断开不需要双方协定 客户端es.close() → 立即断开不重连 方式2双方协定一个标识 服务端data: [DONE]\n\n 客户端收到 [DONE] → es.close() → 标识可以是任意字符串只要双方约定好 方式3服务端单方面断开 服务端重连时返回 204 状态码 客户端浏览器看到 204 → 放弃重连Streamable HTTP 的结束服务端生成器 return / 写完 → 框架自动发结束符 → 响应完成 客户端fetch 收到结束符 → 知道响应完了 → 不重连 → 不需要双方协定任何标识4. 通信方向SSE 单向服务器 → 客户端 Streamable HTTP半双工请求-响应不同时双向 WebSocket 全双工双方同时收发5. 双方主动断开能力客户端主动断开服务端主动断开SSEes.close()程序员手动调直接关闭响应但浏览器会重连Streamable HTTPcontroller.abort()程序员手动调生成器 return框架自动结束SSE 服务端单方面关闭 → 浏览器自动重连 → 没真正断开 Streamable HTTP 服务端写完 → 框架自动发结束符 → 真正结束三、协议层面对比两者底层都是 HTTPTCP 连接都可以保持keep-alive SSE HTTP/1.1 200 OK Content-Type: text/event-stream data: token1\n\n data: token2\n\n ...永远不发结束标记 → 应用层响应永不完成 → TCP 连接被独占 Streamable HTTP HTTP/1.1 200 OK Transfer-Encoding: chunked 5\r\n hello\r\n 0\r\n\r\n ← 结束标记应用层事务完成 → 应用层响应完成 → TCP 释放可复用关键区别SSE 应用层响应无结束标记 → TCP 被独占 Streamable HTTP应用层响应有结束标记 → TCP 释放可复用 两者 TCP 都没断keep-alive但 - Streamable HTTP 的 TCP 空闲了可以服务别人 - SSE 的 TCP 被锁住了不能服务别人四、适用场景SSE 适合服务器持续主动推送客户端被动接收 - 实时通知推送 - 股票行情 - 日志流 - 服务端状态变更通知特点服务器决定什么时候推连接一直保持断了自动重连。Streamable HTTP 适合客户端问一次服务端流式答一次 - LLM 流式输出ChatGPT 式打字效果 - 大文件流式下载 - 长耗时任务的进度返回特点问一次答一次答完就结束不保持连接。WebSocket 适合双方随时互发消息 - 聊天室 - 实时协作编辑 - 语音/视频通话特点全双工双方都可以随时主动发数据。五、不适合用 SSE 的场景LLM 流式对话SSE 的问题 - 问一次答一次的场景不需要持久连接 - 自动重连反而捣乱答完了浏览器还重连 - data: 前缀格式增加解析开销 正确做法Streamable HTTP - 响应完自动结束不重连 - 原生格式无额外开销 - 程序员可控六、总结对比表维度SSEStreamable HTTP本质专用协议text/event-stream普通 HTTP 流式响应方向单向服务器→客户端半双工请求-响应连接占用独占会话期间不释放共享响应完即释放自动重连✅ 浏览器内置❌ 程序员自己写结束机制应用层约定需客户端 es.close()HTTP 协议自带框架自动结束符无协议设计上不结束0\r\n\r\nchunked 结束标记客户端主动断开es.close()controller.abort()服务端主动断开关闭响应但浏览器会重连生成器 return框架自动结束二进制支持❌ 需 base64✅ 原生浏览器原生 APIEventSourcefetch ReadableStream自定义请求头❌ 不支持✅ 支持断点续传❌ 不适合✅ HTTP Range典型场景持续推送通知、行情一问一答LLM 对话七、选型决策服务器要持续主动推送 → SSE自动重连正好需要 客户端问一次服务端答一次 → Streamable HTTP答完就结束正好需要 双方随时互发消息 → WebSocket全双工 大文件断点续传 → HTTP Range 请求206 Partial Content一句话总结SSE 和 Streamable HTTP 协议层面没本质区别都是 HTTP 流式响应。区别在于客户端 API 的设计意图——EventSource 设计成自动重连的持久连接fetch 设计成一问一答。选哪个不取决于协议取决于场景。