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

在这里插入图片描述
在探索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可能会更加适合。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/308609.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性代数——(期末突击)行列式(上)-行列式计算、行列式的性质

目录 行列式 行列式计算 逆序数 行列式的性质 转置 两行&#xff08;列&#xff09;互换 两行&#xff08;列&#xff09;对应相等 提公因子 两行&#xff08;列&#xff09;对应成比例 某行&#xff08;列&#xff09;为零 行列式分裂 行列式变换及三角行列式 行…

数据库一般会采取什么样的优化方法?

数据库一般会采取什么样的优化方法&#xff1f; 1、选取适合的字段属性 为了获取更好的性能&#xff0c;可以将表中的字段宽度设得尽可能小。 尽量把字段设置成not null 执行查询的时候&#xff0c;数据库不用去比较null值。 对某些省份或者性别字段&#xff0c;将他们定义为e…

Django 访问前端页面一直在转异常:ReferenceError:axios is not defined

访问&#xff1a;http://127.0.0.1:8080/ my.html 一、异常&#xff1a; 二、原因 提示&#xff1a;axios找不到&#xff01;&#xff01; 查看代码<script src"https://unpkg.com/axios/dist/axios.min.js"></script>无法访问到官网 三、解决 Using j…

命令行创建Vue项目

Vue项目创建 1. 打开UI界面 在命令行中&#xff0c;执行如下指令&#xff1a; vue ui 2. 打开项目管理器 3. 创建项目 创建项目的过程&#xff0c;需要联网进行&#xff0c;这可能会耗时比较长的时间&#xff0c;请耐心等待。 windows的命令行&#xff0c;容易卡顿&#xff0c…

Nacos注册

一、简介 Nacos是阿里云开源的一个服务发现、配置管理和服务鉴权平台&#xff0c;它提供了一种更简单、更便捷、更开放的方式来管理服务&#xff0c;帮助开发者快速实现服务的发现、配置的管理、服务的鉴权等功能。Nacos可以帮助开发者轻松管理微服务应用中的服务提供者、服务…

Nature | 大型语言模型(LLM)能够发现和产生新知识吗?

大型语言模型&#xff08;LLM&#xff09;是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络&#xff0c;这些神经网络由具有自注意力功能的编码器和解码器组成。编码器和解码器从一系列文本中提取含义&#xff0c;并理解其中的单词和短语之间的关系。通…

专治不服:40 亿条 if 语句

该文讲述了一个程序员尝试用一个特殊的算法来判断一个数是奇数还是偶数的故事。 他通过编写大量的if语句来实现这个算法&#xff0c;并尝试将它扩展到不同的位数。最终&#xff0c;他通过手动编写机器码&#xff0c;并使用函数指针调用这些代码&#xff0c;成功地实现了判断32…

在Ubuntu系统中安装Windows虚拟机

一. 材料准备 从官网下载windows系统的iso镜像&#xff08;非官网下载的镜像可能出现各种问题&#xff09;&#xff0c;稍后我附上百度云盘链接。 二. 安装VirtualBox 在应用商店中搜索VirtualBox&#xff0c;并安装&#xff0c;如下图&#xff1a; 三. 安装虚拟机 新建 …

Python圣诞树代码

Python圣诞树代码 # 小黄 2023/12/25import turtle as t # as就是取个别名&#xff0c;后续调用的t都是turtle from turtle import * import random as rn 100.0speed(20) # 定义速度 pensize(5) # 画笔宽度 screensize(800, 800, bgblack) # 定义背景颜色&#xff0c;可…

Python 为UnityAndroid端自动化接入Tradplus广告SDK

Python 为UnityAndroid端自动化接入Tradplus广告SDK Tradplus介绍常规接入进入Android开发文档选择渠道配置生成接入代码人工依赖下载官网同版本的 Unity插件 使用自动化工具接入首次 你需要打两个标记来定位运行工具 控制台会列出最新的十个Tradplus版本 任选其一然后拖入项目…

Android : 使用GestureOverlayView进行手势识别—简单应用

示例图&#xff1a; GestureOverlayView介绍&#xff1a; GestureOverlayView 是 Android 开发中用于识别和显示手势的视图组件。它允许用户在屏幕上绘制手势&#xff0c;并且应用程序可以检测和响应这些手势。以下是关于 GestureOverlayView 的主要特点&#xff1a; 手势识别…

单应性Homography估计:从传统算法到深度学习

目录 收起 一 图像变换与平面坐标系的关系 二 平面坐标系与齐次坐标系 三 单应性变换 四 关于OpenCV中的相关API 五 深度学习在单应性方向的进展 单应性原理被广泛应用于图像配准&#xff0c;全景拼接&#xff0c;机器人定位SLAM&#xff0c;AR增强现实等领域。这篇文章…