[[toc]]
SSE 是什么?
基本特点
- SSE: Server-Sent Events
- 用途: 服务器向浏览器推送信息, 注意反过来不行
- 本质: 基于http协议的服务端推送技术
- 特点: 响应头mimetype 为
text/event-stream
, keep connection open - 数据: 流信息(streaming),数据流不是一次性数据包,会连续不断发送,比如 视频播放
- 通信: 以流信息方式,完成一次用时很长的下载
- 缓存: SSE会丢弃已经处理过的数据,不会缓存,而XHR会缓存
历史
- SSE 首次在 HTML5 规范中提出,于2014 年标准化。
- HTML5 引入了许多新功能,其中包括 SSE,提供简单有效的服务器到客户端实时通信机制。
EventSource 对象
- HTML5 引入 EventSource 对象,是 SSE 技术的核心。通过 E
- ventSource 对象,客户端可以与服务器建立连接,并监听服务器的事件。
- 这些事件可以是来自服务器的各种数据,如通知、更新或其他信息。
MIMI:text/event-stream
- 用于服务器向客户端推送消息、事件和通知的数据格式,属于HTML5的一部分
- text/event-stream将消息视为一系列流事件,以文本形式发送
- 该格式适用于SSE应用程序,服务器向客户端单向推送数据
- 关键字: stream 表示这是数据流, text 表示数据流以文本形式传送
限制:
- SSE 适用于单向通信,从服务器向客户端发送数据。
- 对于需要双向通信的应用程序,WebSocket 技术通常更合适。
SSE是如何保持http长连接?
- SSE的本质其实是一个HTTP的长连接
- 服务端给客户端发送的不是一次性的数据包,而是一个stream流,格式为text/event-stream。
- 由于是stream流,所以客户端不会关闭连接,会一直等着服务器发送新数据流,
- 视频播放就是这样的例子
Content-Type: text/event-stream 响应头
- 告诉浏览器使用SSE的协议来解析响应,并按照SSE规范处理收到的事件数据。
- 浏览器会将每个事件分解为适当的事件对象,对其进行处理和展示。
[注意]这里说的长连接
- 不是指 http1.1 的长连接(多个http对应1个tcp连接)
- 而是值 http 这个连接本身的长连接 (每次返回部分数据后, http连接没有断开)
普通http请求和sse对比
- 普通http:客户端发起请求,服务端响应,然后一次请求完毕
- sse: 客户端发起请求,连接一直保持,服务端有数据就可以返回数据给客户端
SSE和WS对比
- 通信: SSE 单向通道(当连接断开时,客户端无法通知服务端), 只能服务器向浏览器发送, WS 全双工通道, 更强大和灵活
- 协议: SSE 使用 HTTP 协议, WS 是Http+WebSocket协议
- 使用: SSE 轻量,使用简单;WS 相对复杂
- 断线: SSE 默认支持断线重连,WS 需要自己实现
- 数据: SSE 一般只用来传送文本,WS 默认支持传送二进制数据
WS通信过程
- 通过 http 切换协议,服务端返回 101 状态码后,代表协议切换成功。
- WebSocket 开始数据通信,一方可以随时向另一方推送消息。
SSE通信过程
- 客户端通过 http 发起请求
- 服务端可以多次返回内容,连接一直保持
适合哪些场景?
- 需要实时数据传输的场景中特别有用
- 如社交媒体更新、实时新闻、股票市场报价、在线游戏和协作工具等。
CICD 平台
- 日志实时打印
- 明显需要一段一段的传输
- 一般就是用 SSE 来推送数据
ChatGPT
- 回答一个问题不是一次性给你全部的,而是一部分一部分的加载回答,这也是基于 SSE
- 查看请求 https://chat.openai.com/backend-api/conversation
- 响应头是 Content-Type:text/event-stream; charset=utf-8
- 并且在打字机方式回复时,可以看到请求响应数据在慢慢增加
webpack hmr
- webpack热更新需要向浏览器推送信息
是否有跨域限制?
- 没有限制
- 跨域时,可以通过 withCredentials 参数指定是否发送cookie
兼容性
- SSE 技术通常在现代浏览器中受到支持,包括Chrome、Firefox、Safari和Edge等。
- IE,Opera Mini, 其他浏览器低版本 不支持
- Firefox 6+, Google Chrome 6+, Opera 11.5+, Safari 5+, Microsoft Edge 79+
demo
// 服务端
// server
var http = require("http");
http.createServer(function (req, res) {
if (req.url === "/stream") {
res.writeHead(200, {
// MIME类型 不能注释
"Content-Type":"text/event-stream",
// 3种都可以工作
"Cache-Control":"no-cache",
// "Cache-Control":"public",
// "Cache-Control":"max-age=30",
// 2种都可以工作
// "Connection":"keep-alive",
"Connection":"close",
// 本地file方式打开 不能注释