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);
};
相关推荐
变与不变8068 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半9 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck9 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.9 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子9 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常9 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常9 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋9 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
鸿蒙开发10 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos
屏什么录10 小时前
录屏超过两小时就卡顿崩盘?从参数调优到代码实现,一文彻底搞定长时间录屏
前端·音视频开发