为什么ChatGPT采用SSE协议而不是Websocket?

标签: chatgpt sse 协议 | 发表时间:2023-12-29 08:01 | 作者:程序新视界
出处:https://juejin.im/backend?sort=monthly_hottest

R-C.png

在探索ChatGPT的使用过程中,我们发现GPT采用了流式数据返回的方式。理论上,这种情况可以通过全双工通信协议实现持久化连接,或者依赖于基于EventStream的事件流。然而,ChatGPT选择了后者,也就是本文即将深入探讨的SSE(Server-Sent Events)技术。

要理解这个选择,我们需要关注ChatGPT的使用场景。作为一个基于深度学习的大型语言模型,ChatGPT需要处理大量的自然语言数据,这无疑需要大量的计算资源和时间。相较于普通的读取数据库操作,其响应速度自然会慢许多。

对于这种可能需要长时间等待响应的对话场景,ChatGPT采用了一种巧妙的策略:它会将已经计算出的数据“推送”给用户,并利用SSE技术在计算过程中持续返回数据。这样做可以避免用户因等待时间过长而选择关闭页面。

什么是 SSE?

SSE(Server-Sent Events)是一种Web技术,它允许服务器实时向客户端推送数据。相比于传统的轮询和长轮询机制,SSE提供了一种更高效且实时的数据推送方式。这种技术主要应用于构建实时应用,例如实时消息推送、股票行情更新等。

SSE是HTML5规范中的一个通信相关API,它主要包含两个部分:服务端与浏览器端的通信协议(基于HTTP协议),以及浏览器端JavaScript可使用的EventSource对象。

SSE运行在HTTP协议之上,它允许服务器以事件流(Event Stream)的形式将数据发送给客户端。客户端通过建立持久化的HTTP连接,并监听这个事件流,从而可以实时接收到服务器推送的数据。

SSE具有以下几个主要特点:

  • 简单易用:SSE使用基于文本的数据格式,如纯文本、JSON等,这使得数据发送和解析都相对简单直接。
  • 单向通信:SSE仅支持从服务器到客户端的单向通信。这意味着服务器可以主动推送数据给客户端,但客户端只能被动接收数据。
  • 实时性:由于SSE能够建立持久化连接,服务器因此可以实时地将数据推送给客户端,无需客户端频繁地发起请求。这大大提高了数据传输的效率和实时性。

SSE与WebSocket的比较

WebSocket是一种Web技术,用于实现实时双向通信,它与SSE(Server-Sent Events)在某些方面存在差异。以下是对两者的比较:

  • 数据推送方向:SSE主要支持从服务器到客户端的单向通信,这意味着服务器可以主动地向客户端推送数据。而WebSocket则支持双向通信,允许服务器和客户端之间进行实时的数据交换。
  • 连接建立:SSE利用基于HTTP的长连接,通过常规的HTTP请求和响应来建立连接,进而实现数据的实时推送。相反,WebSocket采用自定义的协议,通过创建WebSocket连接来实现双向通信。
  • 兼容性:由于SSE基于HTTP协议,因此它可以在大多数现代浏览器中使用,并且无需进行额外的协议升级。虽然WebSocket在绝大多数现代浏览器中也得到了支持,但在某些特定的网络环境下可能会遇到问题。
  • 适用场景:SSE适合于需要服务器向客户端实时推送数据的场景,例如股票价格更新、新闻实时推送等。而WebSocket则适合于需要实时双向通信的场景,如聊天应用、多人在线协作编辑等。

选择使用SSE还是WebSocket主要取决于具体的业务需求和场景。如果你只需要实现从服务器向客户端的单向数据推送,并且希望保持操作简便且兼容性好,那么SSE是一个理想的选择。然而,如果你需要实现双向通信,或者需要更高级的功能和控制,那么WebSocket可能会更适合你的需求。

SSE的实现原理

以下是SSE(Server-Sent Events)的实现原理:

  • 连接建立:通常情况下,客户端(如浏览器)通过发送HTTP GET请求到服务器来请求建立一个SSE连接。
  • 服务器响应:一旦服务器接收到请求,它将返回一个HTTP响应,该响应的状态码为200,内容类型(Content-Type)设置为"text/event-stream"。
  • 数据推送:服务器可以通过已经建立的连接向客户端推送数据。每次推送的数据被称作一个事件(Event)。每个事件由一个或多个以"\n\n"分隔的数据块组成。每个数据块都是一行文本,可能包含一个以":"开头的注释行、以"data:"开头的数据行,或者以"id:"和"event:"开头的行来指定事件ID和事件类型。
  • 客户端处理:当客户端接收到服务器推送的事件后,它会触发相应的JavaScript事件处理器来处理这些事件。
  • 重连:如果连接断开,客户端会自动尝试重新连接。如果服务器在事件中指定了ID,那么在重新连接时,客户端会发送一个"Last-Event-ID"的HTTP头部信息到服务器,告诉服务器客户端接收到的最后一个事件的ID。根据这个信息,服务器可以决定从哪个事件开始重新发送数据。

总结起来,SSE使用了基于文本和HTTP协议的简单机制,使得服务器能够实时地将数据推送到客户端,而无需客户端频繁地发起新的请求。

使用SSE的注意事项

以下是在使用SSE(Server-Sent Events)技术进行实时数据推送时需要注意的几个关键点:

  • 异步处理:由于SSE基于长连接的机制,因此数据推送过程可能会持续较长时间。为了防止服务器线程被阻塞,建议采用异步方式处理SSE请求。例如,可以在控制器方法中使用@Async注解或利用CompletableFuture等异步编程方式。
  • 超时处理:SSE连接可能会因网络中断、客户端关闭等原因而超时。为了避免无效连接占据服务器资源,建议设置超时时间并处理超时情况。例如,可以利用SseEmitter对象的setTimeout()方法设定超时时间,并通过onTimeout()方法处理超时逻辑。
  • 异常处理:在实际应用中,可能会遇到网络异常、数据推送失败等问题。这种情况下,可以使用SseEmitter对象的completeWithError()方法将异常信息发送给客户端,并在客户端通过eventSource.onerror事件进行处理。
  • 内存管理:在使用SseEmitter时,需要特别注意内存管理问题,尤其是在大量并发连接的场景下。当客户端断开连接后,务必及时释放SseEmitter对象,以避免资源泄漏和内存溢出。
  • 并发性能:SSE的并发连接数可能对服务器性能产生影响。如果需要处理大量并发连接,可以考虑使用线程池或其他异步处理方式,以最大化服务器资源利用。
  • 客户端兼容性:虽然大多数现代浏览器都支持SSE,但一些旧版本的浏览器可能不支持。因此,在使用SSE时,需要确保目标客户端对其有良好的支持,或者提供备选的实时数据推送机制。

以上这些注意事项可以根据具体应用需求进行调整和优化。在实际应用中,确保服务器的稳定性、安全性和性能是非常重要的。同时,在处理SSE连接时,可以考虑适当的限流和安全控制措施,以防止滥用和恶意连接的出现。总的来说,使用SSE技术时需要全面考虑各个方面的因素,才能实现高效、稳定、安全的实时数据推送服务。

SpringBoot集成SSE案例

假设正在开发一个实时股票价格监控应用,需要将股票价格实时推送给客户端。以下为Spring Boot中集成SSE技术实现的场景示例代码。

首先,定义一个控制器来处理SSE请求和发送实时股票价格:

  import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.Random;
​
@RestController
public class StockController {
​
    @GetMapping(value = "/stock-price", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamStockPrice() {
        SseEmitter emitter = new SseEmitter();
        // 模拟生成实时股票价格并推送给客户端
        Random random = new Random();
        new Thread(() -> {
            try {
                while (true) {
                    // 生成随机的股票价格
                    double price = 100 + random.nextDouble() * 10;
                    // 构造股票价格的消息
                    String message = String.format("%.2f", price);
                    // 发送消息给客户端
                    emitter.send(SseEmitter.event().data(message));
                    // 休眠1秒钟
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }).start();
        return emitter;
    }
}

在上述代码中,定义了一个 streamStockPrice()方法,该方法使用 @GetMapping注解将 /stock-price路径映射到该方法上,并指定 produces = MediaType.TEXT_EVENT_STREAM_VALUE以表明该方法将产生SSE事件流。

在方法内部创建了一个 SseEmitter对象作为事件发射器,并在一个单独的线程中不断生成随机的股票价格,并将价格转换为字符串形式发送给客户端。

通过 emitter.send()方法发送的数据会被封装为SSE事件流的形式,客户端可以通过监听该事件流来实时接收股票价格。

在前端页面中,创建一个简单的HTML页面来展示实时股票价格:

  <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>实时股票价格监控</title>
  </head>
  <body>
    <h1>实时股票价格</h1>
    <div id="stock-price"></div>
​
    <script>
      const eventSource = new EventSource('/stock-price');
      eventSource.onmessage = function (event) {
        document.getElementById('stock-price').innerHTML = event.data;
      };
    </script>
  </body>
</html>

上述代码中,通过 new EventSource('/stock-price')创建了一个 EventSource对象,它与 /stock-price路径建立SSE连接。然后,通过 eventSource.onmessage定义了接收消息的回调函数,在收到新消息时更新页面上的股票价格。

通过以上代码,可以在浏览器中打开该HTML页面,它会建立与服务器的SSE连接,并实时接收并展示股票价格。这只是使用SSE实现实时数据推送的一个简单示例。在实践中,可以根据具体的业务需求和场景,进行更复杂和丰富的实现。

小结

SSE(Server-Sent Events)是一种基于HTTP协议的轻量级实时通信技术,具备服务端推送、断线重连和简单轻量等优点。然而,它也存在一些限制,例如无法进行双向通信、连接数受限以及仅支持GET请求等。

在Web应用程序中,SSE可以实现各种即时数据推送功能,如股票在线数据更新、日志推送、实时显示聊天室人数等。

然而,需要注意的是,并非所有的实时推送场景都适合使用SSE。在需要处理高并发、高吞吐量和低延迟的场景下,WebSocket可能是更好的选择。而对于那些需要轻量级推送解决方案的场景,SSE可能会更加适合。

因此,在选择实时更新方案时,我们需要根据具体的需求和应用场景来做出决策。只有这样,我们才能确保选择的技术能够最大程度地满足我们的需求。

相关 [chatgpt sse 协议] 推荐:

为什么ChatGPT采用SSE协议而不是Websocket?

- - 掘金后端本月最热
在探索ChatGPT的使用过程中,我们发现GPT采用了流式数据返回的方式. 理论上,这种情况可以通过全双工通信协议实现持久化连接,或者依赖于基于EventStream的事件流. 然而,ChatGPT选择了后者,也就是本文即将深入探讨的SSE(Server-Sent Events)技术. 要理解这个选择,我们需要关注ChatGPT的使用场景.

ChatGPT的几个声明

- -
ChatGPT是一个免费的研究预览. 我们的目标是获取外部反馈,以改进我们的系统并使其更加安全. 虽然我们已经设置了保障措施,但系统偶尔可能会生成不正确或误导性的信息,并产生冒犯或有偏见的内容. 我们的AI培训师可能会审核对话以改善我们的系统. 请不要在您的对话中分享任何敏感信息. 整个欧洲都有兴趣“封禁”ChatGPT.

最强语言 AI 诞生 - ChatGPT

- - 煞有介事
没错,最强语言 AI 已经诞生,那就是 ChatGPT. ChatGPT 是 OpenAI 实验室最近推出的语言 AI,上周三推出,今天已经有 100万用户量,甚至马斯克都已经注意到了. 这两天也是各个圈子在一直分享和「玩」,有技术圈、web3 圈. 我也注册试玩了下,从 SEO 角度,内容质量和流畅度确实远超其他 AI 几条街.

ChatGPT背后人工智能算法

- - 今日话题 - 雪球
ChatGPT背后人工智能算法,关键的原创技术,其实全部都是国外公司发明的. 这里做一点简单的科普,人工智能原创性研究,中国还有很大进步空间,ChatGPT也不是普通的公司能够复刻的出来的. 深度残差网络(ResNet)由微软(亚洲)研究院发明. 在此之前,研究员们发现深度神经网络的效果要比浅层神经网络要好得多,这也就是所谓的深度学习.

ChatGPT会取代搜索引擎吗

- - 知乎每日精选
作为智能对话系统,ChatGPT最近两天爆火,都火出技术圈了,网上到处都在转ChatGPT相关的内容和测试例子,效果确实很震撼. 我记得上一次能引起如此轰动的AI技术,NLP领域是GPT 3发布,那都是两年半前的事了,当时人工智能如日中天如火如荼的红火日子,今天看来恍如隔世;多模态领域则是以DaLL E2、Stable Diffusion为代表的Diffusion Model,这是最近大半年火起来的AIGC模型;而今天,AI的星火传递到了ChatGPT手上,它毫无疑问也属于AIGC范畴.

ChatGPT ReAct (Reason+Act) 模式实现

- - hooopo (Hooopo)
ChatGPT 是一个语言模型,对自然语言的理解和输出比人类要强很多,对编程语言和结构化处理相关的问题更是比人类好很多. 对于开发者来说,目前 ChatGPT 存在的几个问题:. 在 Chat 模型里对话过长会出现失忆现象. 前两个问题可以通过 数据填充机制(Augmentation)解决. 后几个问题一般引入 ReAct(Reason+Act) 模式来解决.

如何评价OpenAI的超级对话模型ChatGPT? - 知乎

- -
有幸参与ChatGPT训练的全过程. RLHF会改变现在的research现状,个人认为一些很promising的方向:在LM上重新走一遍RL的路;如何更高效去训练RM和RL policy;写一个highly optimized RLHF library来取代我的. dataset的质量、多样性和pretrain在RLHF的比重很重要.

爆火的chatGPT,和它的前世今生

- - 虎嗅网 - 首页资讯
本文来自微信公众号: Web3天空之城(ID:Web3SkyCity),作者:城主,原文标题:《从爆火的chatGPT讲起:自然语言生成式AI的前世今生,你想了解的一切》,题图来自:视觉中国. AIGC在这几个月成了一个大热的话题. 颇有些风水轮流转的感觉,如同年初大火特火的web3一样,AIGC是现在的当红炸子鸡,创业投资讨论里如果不带点AIGC就是妥妥的落伍.

一文读懂ChatGPT模型原理 - 知乎

- -
本文是ChatGPT原理介绍,但没有任何数学公式,可以放心食用). ChatGPT模型真可谓称得上是狂拽酷炫D炸天的存在了. 一度登上了知乎热搜,这对科技类话题是非常难的存在. 不光是做人工智能、机器学习的人关注,而是大量的各行各业从业人员都来关注这个模型,真可谓空前盛世. 我赶紧把 OpenAI 以往的 GPT-n 系列论文又翻出来,重新学习一下,认真领会.

你最关注的 10 个问题,我们替你问了 ChatGPT

- - 极客公园
AIGC 作画带给人们的惊艳感觉还没散去,ChatGPT 又来刺激人类脆弱的神经了. 当地时间 11 月 30 日,代替「跳票」的 GPT-4,OpenAI 发布了新的对话式 AI ChatGPT,没想到 ChatGPT 迅速出圈,其热烈程度甚至超过当年战胜人类棋手的 AlphaGo. 用户可以问 ChatGPT 任何问题,或者让它写一首歌,后者都能给出相当靠谱的答案.