很多AI聊天服务,比如ChatGPT、Claude和Gemini,在响应用户请求时,文字是一个字一个字地“蹦”出来的,带来了流畅的交互体验。这种实时流式输出的背后究竟是什么技术原理呢?
从根本上说,Web服务是基于HTTP协议运行的。这个协议的工作方式是单向通信:客户端发送请求,服务器返回一个完整的响应。然而,我们希望服务器能够实时将AI生成的消息片段(tokens)发送给客户端。传统的HTTP请求-响应模式显然无法满足这种需求。
WebSockets是解决方案吗?
作为一种替代方案,你可能会想到使用WebSockets,但它也并非最佳选择。原因有三:
- 流式消息传递本质上只需要服务器向客户端单向传输多块数据,并不需要一个双向通信通道。
- 由于WebSocket不直接基于HTTP,这意味着它无法开箱即用地利用HTTP的现有特性,例如认证(通过cookies或tokens)、CORS(跨域资源共享)、缓存以及日志记录等。
- 它使得扩展变得困难。特别是负载均衡的配置是一个大难题。在典型的Web服务中,负载均衡器可以将流量均匀地分配到多台服务器。但如果使用WebSockets,特定的服务器必须与客户端保持持久连接。因此,你必须使用“粘性会话”(Sticky Sessions)来维持连接,这使得水平扩展变得困难,因为流量无法均匀分布。
答案是Server-Sent Events (SSE)
实际上,这个问题完全可以通过HTTP协议来解决,那就是**Server-Sent Events (SSE)**。
传统的HTTP响应通常会一次性发送所有数据,并通过Content-Length字段告知浏览器数据长度。一旦浏览器收到指定长度的数据,就会关闭连接。
另一方面,SSE响应则有所不同。它使用HTTP/1.1 200 OK,但关键在于设置了Transfer-Encoding: chunked和Content-Type: text/event-stream。
在这种情况下,浏览器会认为响应尚未结束,会保持连接开放,并实时处理到达的数据块。通过这种方式,我们可以在保持标准HTTP协议的同时,让服务器为单个请求分多次发送响应。这就是AI消息流式传输的实现原理。