目录
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
结尾)。