OpenAI是如何实现流式传输的?盘点主流轮询的实现方式

轮询是指客户端定期向服务器查询是否有新的数据更新,是一种常见的实现客户端与服务器数据同步的技术。主要有以下几种轮询方式:

  1. 短轮询(Short Polling)

这是最简单的一种轮询方式。客户端通过setInterval或类似的定时器每隔一段时间向服务器发送一次请求,服务器立即返回响应数据(无论数据是否有更新)。这种方式实现简单,但缺点是无论服务器数据是否更新,请求都会被发送,导致服务器压力较大,资源浪费。

javascript 复制代码
function poll() {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', '/data', true);
  xhr.onload = function() {
    if (xhr.status === 200) {
      // 处理响应数据
      handleData(xhr.responseText);
      // 继续轮询
      setTimeout(poll, 5000); // 5秒后继续轮询
    }
  }
  xhr.send();
}

poll(); // 启动轮询

短轮询适用于对实时性要求不太高,数据更新频率较低的场景,比如定期获取天气预报、股票行情等。

  1. 长轮询(Long Polling)

长轮询技术可以减少不必要的请求,降低服务器压力。客户端发送Ajax请求到服务器后,服务器将请求挂起,直到有新的数据更新才返回响应,客户端收到响应后再次发送新的请求。

这种方式的关键是服务器端要保持请求状态,一旦有新数据就触发响应。连接无法一直保持,需要重新建立新连接。

javascript 复制代码
const http = require('http');

const pendingRequests = [];

const server = http.createServer((req, res) => {
  if (req.url === '/subscribe' && req.method === 'GET') {
    // 将响应挂起
    pendingRequests.push(res);

    // 监听客户端断开连接
    req.on('close', () => {
      pendingRequests.splice(pendingRequests.indexOf(res), 1);
    });
  } else {
    res.statusCode = 404;
    res.end('Not found');
  }
});

// 每隔一段时间向所有挂起的响应推送数据
setInterval(() => {
  const message = { time: new Date().toLocaleTimeString() };
  pendingRequests.forEach((res) => {
    res.write(`data: ${JSON.stringify(message)}\n\n`);
  });
}, 5000);

server.listen(3000, () => console.log('Server is running on http://localhost:3000'));

长轮询适用于偶尔的服务器数据实时更新推送,比如网页操作的实时更新、在线客服实时消息等。

  1. WebSocket

WebSocket是一种全双工的通信协议,可以在单个TCP连接上进行全双工通信,实现服务器主动推送数据给客户端,也允许客户端随时向服务器发送数据。

WebSocket连接建立后,会以两条单向通道的形式工作,服务端和客户端可以随时主动发送数据给对方,全程只建立一次TCP连接,无需像HTTP每次发送请求都建立新连接。

javascript 复制代码
const socket = new WebSocket('ws://example.com/data');

socket.onopen = function() {
  console.log('WebSocket连接已建立');
};

socket.onmessage = function(event) {
  handleData(event.data);
};

socket.onerror = function(error) {
  console.error('WebSocket连接发生错误:', error);
};

WebSocket非常适合需要双向通信的实时场景,如即时通讯、协同编辑、游戏、金融实时报价等,可以最大程度节约服务器资源和带宽。

  1. Server-Sent Events(SSE)

SSE(Server-Sent Events,服务器发送事件)是一种基于HTTP的服务器端向客户端推送数据的技术,OpenAI使用SSE实现了流式传输效果。相比传统的轮询方式,它有以下优点:

  • 服务器推送 传统轮询需要客户端定时向服务器发起请求,而SSE是服务器主动向客户端推送数据,减少了客户端不必要的请求,节省了带宽和服务器资源。

  • 单向通信 SSE是单向通信,即只能由服务器向客户端推送数据,无需客户端发起请求。这种单向通信模型更加高效。

  • 实时性 服务器可以实时地将数据推送给客户端,而不需要等待客户端的轮询。这对于需要实时更新数据的应用非常有用,如在线聊天、实时报价等。

  • 自动重连 如果连接断开,浏览器会自动重新连接到服务器,确保数据流的连续性。

  • 简单 SSE使用HTTP协议,易于开发和部署,且兼容大多数现代浏览器。

SSE的应用场景包括:在线聊天、股票行情更新、社交网络更新、用户在线状态更新、服务器监控等需要服务器实时向多个客户端推送数据的场景。

以下是一个简单的Node.js服务器使用SSE推送数据的示例:

javascript 复制代码
const http = require('http');

const server = http.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  const sendEvent = (data) => res.write(`data: ${JSON.stringify(data)}\n\n`);

  sendEvent({ message: 'Hello from Server-Sent Events!' });

  const intervalId = setInterval(() => sendEvent({ time: new Date().toLocaleTimeString() }), 1000);

  req.on('close', () => {
    console.log('Client disconnected');
    clearInterval(intervalId);
  });
});

server.listen(3000, () => console.log('Server listening on port 3000'));

在浏览器中,可以使用EventSource对象订阅服务器推送的事件:

javascript 复制代码
const eventSource = new EventSource('http://localhost:3000');

eventSource.onmessage = (event) => {
  console.log('Received event:', event.data);
};
相关推荐
Darling02zjh39 分钟前
GUI图形化演示
前端
Channing Lewis41 分钟前
如何判断一个网站后端是用什么语言写的
前端·数据库·python
互联网搬砖老肖1 小时前
Web 架构之状态码全解
前端·架构
showmethetime1 小时前
matlab提取脑电数据的五种频域特征指标数值
前端·人工智能·matlab
左钦杨2 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
NaclarbCSDN3 小时前
Java集合框架
java·开发语言·前端
进取星辰3 小时前
28、动画魔法圣典:Framer Motion 时空奥义全解——React 19 交互动效
前端·react.js·交互
不爱吃饭爱吃菜4 小时前
uniapp微信小程序-长按按钮百度语音识别回显文字
前端·javascript·vue.js·百度·微信小程序·uni-app·语音识别
程序员拂雨5 小时前
Angular 知识框架
前端·javascript·angular.js
GoodStudyAndDayDayUp5 小时前
gitlab+portainer 实现Ruoyi Vue前端CI/CD
前端·vue.js·gitlab