1. 背景
随着现代技术的快速发展,即时交互变得越来越重要。用户不仅希望获取信息,而且希望以更直观和实时的方式体验它。这在聊天应用程序和其他实时通信工具中尤为明显,用户习惯看到对方正在输入的提示。
ChatGPT,作为 OpenAI 的代表性产品之一,不仅为用户提供了强大的自然语言处理能力,而且关注用户的整体交互体验。在使用 ChatGPT 进行交互时,用户可能已经注意到了一个细节:当它产生回复时,回复会像人类逐字输入的方式逐渐出现,而不是一次性显示完整答案。
这种打字效果给人一种仿佛与真人对话的感觉,进一步增强了其自然语言处理的真实感。一开始,许多开发者可能会误以为这是通过 WebSockets 实现的,这是因为 WebSockets 是一种常用于实时通信的技术。然而,仔细研究后,我们发现 ChatGPT 使用了一种不同的技术:基于 EventStream 的方法。更具体地说,它似乎是通过 SSE (Server-Sent Events) 来实现逐个字地推送答案的。
此外,考虑到 ChatGPT 的复杂性和其涉及的大量计算,响应时间可能会长于其他基于数据库的简单查询。因此,采用 SSE 逐步推送结果的方式可以帮助减少用户感到的等待时间,从而增强用户体验。
2. SSE 简介
Server-Sent Events(通常简称为SSE)是一种允许服务器向Web页面发送实时更新的技术。与WebSocket技术相比,SSE专门设计用于从服务器到客户端的单向通信。这种单向性使其在某些场景中更为简单和直观。
2.1 主要特点
-
单向通信:SSE 专为从服务器到客户端的单向通信设计。客户端不能通过SSE直接发送数据到服务器,但可以通过其他方法如AJAX与服务器进行交互。
-
基于HTTP:SSE 基于 HTTP 协议运行,不需要新的协议或端口。这使得它能够轻松地在现有的Web应用架构中使用,并且通过标准的HTTP代理和中间件进行支持。
-
自动重连:如果连接断开,浏览器会自动尝试重新连接到服务器。
-
格式简单:SSE 使用简单的文本格式发送消息,每个消息都以两个连续的换行符分隔。
-
原生浏览器支持:许多现代浏览器(如 Chrome、Firefox 和 Safari)已原生支持SSE,但需要注意的是,某些浏览器,如Internet Explorer和早期的Edge版本,不支持SSE。
2.2 SSE 与 WebSockets
虽然 SSE 与 WebSockets 在某种程度上有些相似,但它们之间还存在一些关键差异,如下所示:
对比项 | Server-Sent Events (SSE) | WebSockets |
---|---|---|
基于协议 | 基于 HTTP,简化了连接和交互的过程 | 通常基于 WS/WSS(基于TCP),更为灵活 |
通信能力 | 单向通信:仅服务器向客户端发送消息 | 双向通信能力 |
配置 | 配置简单,易于理解和使用 | 需要更复杂的配置和理解 |
断线与消息追踪 | 自带的断线重连和消息跟踪功能 | 通常需要手动处理或使用额外库 |
数据格式 | 通常为文本,但可以发送经过编码/压缩的二进制消息 | 支持文本和原始二进制消息 |
事件处理 | 支持多种自定义事件 | 基本消息机制,不能像SSE那样自定义事件类型 |
连接并发性 | 连接数可能受到 HTTP 版本的限制,尤其是在HTTP/1.1中 | WebSocket被设计为支持更高的连接并发性 |
安全性 | 仅支持HTTP和HTTPS的安全机制 | 支持WS和WSS,可以在WSS上实现更强大的加密 |
浏览器兼容性 | 大部分现代浏览器支持,但不是所有浏览器 | 几乎所有现代浏览器都支持 |
开销 | 由于基于HTTP,每次消息可能有较大的头部开销 | 握手后,消息头部开销相对较小 |
3. 服务端深入解析
3.1 SSE 的协议机制
Server-Sent Events(SSE)是一个基于 HTTP 的协议,允许服务器单向地向浏览器推送信息。为了成功地使用 SSE,服务器和客户端都必须遵循一定的规范和流程。
当客户端(例如浏览器)发出请求订阅 SSE 服务时,服务器需要通过设置特定的响应头部信息来确认该请求。这些头部信息包括:
-
Content-Type: text/event-stream
: 这表示返回的内容为事件流。 -
Cache-Control: no-cache
: 这确保服务器推送的消息不会被缓存,以保障消息的实时性。 -
Connection: keep-alive
: 这指示连接应始终保持开放,以便服务器可以随时发送消息。