目录
1 背景
在使用 ChatGPT 时,发现输入 prompt 后,页面是逐步给出回复的,起初以为使用了 WebSckets 持久化连接协议,查看其网络请求,发现这个接口的通信方式并非传统的 http 接口或者 WebSockets,而是基于 EventStream 的事件流,像打字机一样,一段一段的返回答案。
ChatGPT 是一个基于深度学习的大型语言模型,处理自然语言需要大量的计算资源和时间,响应速度肯定比普通的读数据库要慢的多,普通 http 接口等待时间过长,显然并不合适。对于这种单项对话场景,ChagtGPT 将先计算出的数据“推送”给用户,边计算边返回,避免用户因为等待时间过长关闭页面。而这,正式采用了 SSE 技术。
2 简介
Server-Sent Events 服务器推送事件,简称 SSE,是一种服务端实时主动向浏览器推送消息的技术。 SSE 是 HTML5 中一个与通信相关的 API,主要由两部分组成:服务端与浏览器端的通信协议(HTTP
协议)及浏览器端可供 JavaScript 使用的 EventSource
对象。
从“服务端主动向浏览器实时推送消息”这一点来看,该 API 与 WebSockets API 有一些相似之处。但是,该 API 与 WebSockers API 的不同之处在于:
Server-Sent Events API | WebSockets API |
---|---|
基于 HTTP 协议 | 基于 TCP 协议 |
单工,只能服务端单向发送消息 | 全双工,可以同时发送和接收消息 |
轻量级,使用简单 | 相对复杂 |
内置断线重连和消息追踪的功能 | 不在协议范围内,需手动实现 |
文本或使用 Base64 编码和 gzip 压缩的二进制消息 | 类型广泛 |
支持自定义事件类型 | 不支持自定义事件类型 |
连接数 HTTP/1.1 6 个,HTTP/2 可协商(默认 100) | 连接数无限制 |
3 服务端实现
3.1 协议
SSE 协议非常简单,本质是浏览器发起 http 请求,服务器在收到请求后,返回状态与数据,并附带以下 headers: js Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive
- SSE API规定推送事件流的 MIME 类型为 text/event-stream
。 - 必须指定浏览器不缓存服务端发送的数据,以确保浏览器可以实时显示服务端发送的数据。 - SSE 是一个一直保持开启的 TCP 连接,所以 Connection 为 keep-alive。
3.2 消息格式
EventStream(事件流)为 UTF-8
格式编码的文本
或使用 Base64 编码和 gzip 压缩的二进制消息。 每条消息由一行或多行字段(event
、id
、retry
、data
)组成,每个字段组成形式为:字段名:字段值
。字段以行为单位,每行一个(即以 \n
结尾)。以冒号
开头的行为注释行,会被浏览器忽略。 每次推送,可由多个消息组成,每个消息之间以空行分隔(即最后一个字段以\n\n
结尾)。