长连接:ChatGPT流式响应背后的逻辑 | 京东物流技术团队

一、前言:

提起长连接,我们并不陌生,最常见的长连接非websocket莫属了。即使没有在项目中实际用过,至少也应该有所接触。长连接指在一次网络通信中,客户端与服务器之间建立一条持久的连接,可以在多次请求和响应中重复使用该连接。这种方式的优点是减少了连接建立和关闭的开销,提高了通信效率,但需要注意控制连接的数量,避免资源浪费。短连接则是每次请求和响应都建立一个新的连接,完成后立即关闭,需要频繁进行连接建立和关闭,效率相对较低。但是这种方式更加灵活,适用于请求量较小、请求频率不高的场景。

二、背景:

最近项目在引用chatgpt智能小助手,最开始采用的是当chatgpt回答完成后一次性返回答案。但这种方式受限于网络及服务较慢的原因导致用户需要等待较长时间,极大的降低了用户的使用体验。经过项目组成员商议决定采取答案逐字返回的形式,以便于用户能更快的得到反馈。

关于长连接技术,主要考虑两种方案websocket和sse

三、原理:

1.websocket概念:WebSocket是HTML5定义的新协议,实现了服务器与客户端之间的全双工通信。WebSocket连接一旦建立,客户端和服务器端处于平等地位,可以相互发送数据,不存在请求和响应的区别。

2、websocket优劣势:优势在于实现了双向通信,劣势在于服务器端的逻辑非常复杂。现在针对不同的后台语言有不同的插件可以使用。

3、sse概念:SSE(Server-Sent Events)是HTML5新增的功能,允许服务器将数据推送到客户端。与长轮询和短轮询不同,SSE不需要客户端先发送请求,而是在服务器端数据有更新时立即发送到客户端

4、sse优劣势:优势在于节约资源,提升应用性能。SSE可以实现只要服务器端数据有更新,就可以马上发送到客户端,不需要建立或保持大量的客户端发往服务器端的请求。另外,SSE的实现非常简单,并且不需要依赖其他插件。劣势在于不是双向通信,只能后台向前台推送。

5、相同点:都是基于tcp,都是可靠的传输协议

6、不同点

  • WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息
  • HTTP是单向的
  • WebSocket是需要浏览器和服务器握手进行建立连接的
  • 而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接

四、应用:

1、sse在chatgpt中的应用

前端代码

1import { fetchEventSource } from '@microsoft/fetch-event-source' 2let answerContent = '' 3fetchEventSource('/chatgptApi/chatgpt_qa_stream', { 4 method: 'POST', 5 headers: { 6 'Content-Type': 'application/json' 7 }, 8 body: JSON.stringify({ messages }), 9 async onopen(response) { 10 if (response.ok && response.status === 200) { 11 console.log('连接成功') 12 } else { 13 console.log('连接异常') 14 } 15 }, 16 async onmessage(event) { 17 // 表示整体结束 18 if (event.data === '[DONE]') { 19 console.log('结束') 20 return 21 } 22 if (event.data) { 23 const data = JSON.parse(event.data) 24 answerContent += data.content 25 } 26 }, 27 async onerror(error) { 28 console.error('Error:', error) 29 }, 30 async onclose() { 31 console.log('关闭连接') 32 } 33 }) 34 35 36 37

后端代码

1const http = require('http'); 2const yun = express(); 3const eventServer = http.createServer((req, res) => { 4 res.writeHead(200, { 5 'Content-Type': 'text/event-stream', 6 'Cache-Control': 'no-cache', 7 'Connection': 'keep-alive', 8 'Access-Control-Allow-Origin': "*", 9 'Access-Control-Allow-Headers': 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With', 10 'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS' 11 }); 12 setInterval(() => { 13 // 事件要用两个\n结束 14 res.write('data: The server time is: ' + new Date() + '\n\n'); 15 }, 1000); 16 req.connection.addListener('close', () => { 17 console.log('SSE connection closed!'); 18 }, false); 19}).listen(4001); 20 21 22 23

2、websockt在即时聊天中的应用

前端代码

1// 创建WebSocket对象 2let ws = new WebSocket('ws://localhost:8888') 3 4// 连接成功后的回调函数 5ws.onopen = function (params) { 6 console.log('客户端连接成功') 7 // 向服务器发送消息 8 ws.send('hello') 9}; 10 11// 从服务器接受到信息时的回调函数 12ws.onmessage = function (e) { 13 console.log('收到服务器响应', e.data) 14}; 15 16// 连接关闭后的回调函数 17ws.onclose = function(evt) { 18 console.log("关闭客户端连接"); 19}; 20 21// 连接失败后的回调函数 22ws.onerror = function (evt) { 23 console.log("连接失败了"); 24}; 25// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,这样服务端会抛异常。 26window.onbeforeunload = function() { 27 ws.close(); 28} 29 30 31 32

后端代码

1/ 引入插件 2const ws = require('nodejs-websocket') 3// 只要有用户链接,函数就会执行,会给当前链接的用户创建一个connect对象 4const server = ws.createServer((connect)=>{ 5 console.log('连接成功') 6 // console.log(connect) 7 // 注册text事件 ,接收用户传递过来的数据 8 connect.on('text',data=>{ 9 console.log('接收客户端数据---->', data) 10 // 给所有用户发送消息 11 broadcast(server,data+"--返回数据") 12 }) 13 // 连接断开,触发事件close 14 connect.on('close',()=>{ 15 console.log('用户链接断开--close') 16 }) 17 // 用户链接断开 18 connect.on('error',err=>{ 19 console.log('err', err) 20 }) 21 22}).listen(3001,()=>{ 23 console.log('websocket服务启动成功了') 24}) 25 26// 给所有人发消息 27function broadcast(server,msg){ 28 server.connections.forEach(element => { 29 element.send(msg) 30 }); 31} 32 33 34 35

五、效果:

sse在chatgpt案例中的应用

作者:京东物流 田雷雷

来源:京东云开发者社区 自猿其说Tech

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

java.io.EOFException   at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer

如题,网上找了相关资料查明是websocket连接超时的问题。使用了反向代理,因此超过60S没有数据传输的连接会断开。把代理的那个超时时间设置长一点,无限长。你开什么玩笑!那还代理个啥玩意。解决方法一:后台写个定时程序每<60s频率给前端的socket发个消息就好了。importorg.springframework.context.a

Python与MySQL如何保持长连接

Python与MySQL如何保持长连接介绍在python后端开发中,时常会与数据库交互,重复的断开、连接会大大消耗数据库资源。所以一般都是定义全局变量,来弥补这个缺陷。但是Python与Mysql长连接的过程中,如果长时间没有交互,它是会断开的。再次执行sql语句是就会

IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理

1、前言一个安全的信息系统,合法身份检查是必须环节。尤其IM这种以“人”为中心的社交体系,身份认证更是必不可少。一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是整个IM系统都是以长连接为中心:身份鉴权、数据收发、文件传送等等)。但当前主流的IM(尤其新一代的移动端IM)中,都是“长”(指TCP或UDP长连接)、“短”(是指H

Linux应急响应(二):捕捉短连接

0x00前言​短连接(shortconnnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。在系统维护中,一般很难去察觉,需要借助网络安全设备或者抓包分析,才能够去发现。0x01应急场景​

MySQL性能优化必知:长连接、短连接、连接池

!(https://oscimg.oschina.net/oscnet/b28f90bfd78b4050ad8c40ae2bb9abe3.png)当数据库服务器和客户端位于不同的主机时,就需要建立网络连接来进行通信。客户端必须使用数据库连接来发送命令和接收应答、数据。通过提供给客户端数据库的驱动指定连接字符串后,客户端就可以和数据库建立连接了