0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

轮询、SSE 和WebSocket哪个更好

jf_78858299 来源:超级架构师 作者:南极真君 2023-02-22 10:39 次阅读

构建实时Web应用程序有点挑战,我们需要考虑如何将数据从服务器发送到客户端。能够“主动”实现这一功能的技术已经存在了很长时间,并且仅限于两种通用方法:客户端请求或服务器请求。

实现这些的几种方法:

  1. 长/短轮询(客户端拉动)
  2. WebSockets(服务器推送)
  3. 服务器发送的事件(服务器推送)
  • 客户端拉取-客户端以一定的定期间隔向服务器请求更新
  • 服务器推送-服务器正在主动将更新推送到客户端(客户端拉取的反向操作)

图片

让我们以一个简单的用例来比较以上技术,然后选择合适的技术。

范例:

我们的示例用例非常简单。我们需要开发一个仪表板Web应用程序,该应用程序可以流转来自(GitHub / Twitter / .. etc)等网站的活动列表。这个应用程序的目的是从上面列出的各种方法中选择合适的一种。

1.使用轮询:

轮询是一种技术,客户端通过该技术定期向服务器请求新数据。我们可以通过两种方式进行轮询:短轮询和长轮询。简单来说,短轮询是基于AJAX的计时器,它以固定的延迟进行调用,而长轮询则基于Comet(即,当服务器事件发生时,服务器将无延迟地将数据发送到客户端)。两者都有优点和缺点,并根据用例进行调整。有关深入的详细信息,请阅读StackOverflow社区给出的答案。

让我们看看一个简单的客户端长轮询代码段的外观:

/* Client - subscribing to the github events */

subscribe: (callback) => {

const pollUserEvents = () => {

$.ajax({

method: 'GET',

url: 'http://localhost:8080/githubEvents',

success: (data) => {

callback(data) // process the data

},

complete: () => {

pollUserEvents();

},

timeout: 30000

})

}

pollUserEvents()

}

这基本上是一个长轮询功能,它像往常一样第一次运行,但是它设置了三十(30)秒的超时,并且在每次对服务器进行Async Ajax调用之后,回调都会再次调用Ajax。

AJAX调用可在HTTP协议上运行,这意味着默认情况下,对同一域的请求应进行多路复用。我们发现这种方法存在一些陷阱。

多路复用(轮询响应实际上无法同步)

轮询需要3次往返(TCP SIN,SSL和数据)

超时(如果连接保持空闲时间太长,代理服务器将关闭连接)

您可以在这里阅读更多关于现实世界的挑战。

2.使用WebSockets:

WebSocket只是客户端和服务器之间的持久连接。这是一种通过单个TCP连接提供全双工通信通道的通信协议。

RFC 6455声明WebSocket“旨在在HTTP端口80和443上工作,并支持HTTP代理和中介”,从而使其与HTTP协议兼容。为了实现兼容性,WebSocket握手使用HTTP升级标头将HTTP协议更改为WebSocket协议。HTTP和WebSocket都位于OSI模型的应用程序层,因此依赖于第4层的TCP。

图片

有一个MDN文档详细解释了WebSocket,我也建议您阅读它。

让我们看看一个非常简单的WebSocket客户端实现的样子:

$(function () {

// if user is running mozilla then use it's built-in WebSocket

window.WebSocket = window.WebSocket || window.MozWebSocket;

const connection = new WebSocket('ws://localhost:8080/githubEvents');

connection.onopen = function () {

// connection is opened and ready to use

};

connection.onerror = function (error) {

// an error occurred when sending/receiving data

};

connection.onmessage = function (message) {

// try to decode json (I assume that each message

// from server is json)

try {

const githubEvent = JSON.parse(message.data); // display to the user appropriately

} catch (e) {

console.log('This doesn't look like a valid JSON: '+ message.data);

return;

}

// handle incoming message

};

});

如果服务器支持WebSocket协议,它将同意升级,并将通过响应中的Upgrade标头传达此信息。

让我们看看如何在Node.JS(服务器)中实现:

const express = require('express');

const events = require('./events');

const path = require('path');

const app = express();

const port = process.env.PORT || 5001;

const expressWs = require('express-ws')(app);

app.get('/', function(req, res) {

res.sendFile(path.join(__dirname + '/static/index.html'));

});

app.ws('/', function(ws, req) {

const githubEvent = {}; // sample github Event from Github event API https://api.github.com/events

ws.send('message', githubEvent);

});

app.listen(port, function() {

console.log('Listening on', port);

});

一旦我们从GitHub事件API获得数据,就可以在建立连接后将其流式传输到客户端。对于我们的场景,这种方法也有一些陷阱。

  • 使用WebSockets,我们需要自己处理许多由HTTP处理的问题。
  • WebSocket是用于传输数据的另一种协议,它不会通过HTTP / 2连接自动多路复用。在服务器和客户端上实现自定义多路复用有点复杂。
  • WebSocket是基于帧的,而不是基于流的。当我们打开网络标签。您可以看到WebSocket消息在frame中列出。

图片

有关WebSocket的详细信息,请查看这篇很棒的文章,在这里您可以阅读有关碎片以及如何在后台进行处理的更多信息。

3.使用SSE:

SSE是一种机制,一旦建立了客户端-服务器连接,服务器就可以将数据异步推送到客户端。然后,只要有新的“大块”数据可用,服务器就可以决定发送数据。可以将其视为单向发布-订阅模型。

它还提供了一个标准的JavaScript客户端API,称为EventSource,已在大多数现代浏览器中实现,作为W3C的HTML5标准的一部分。 Polyfills可用于不支持EventSource API的浏览器。

图片

我们可以看到Edge和Opera Mini落后于此实现,对于SSE而言,最重要的案例是针对移动浏览器设备,因为这些浏览器没有可行的市场份额。Yaffle是事件源的众所周知的pollyfill。

由于SSE是基于HTTP的,因此它很自然地与HTTP / 2相适应,并且可以结合使用以实现两者的最佳选择:HTTP / 2处理基于多路复用流的有效传输层,而SSE为应用程序提供API以实现 推。因此,开箱即用地通过HTTP / 2实现多路复用。连接断开时会通知客户端和服务器。通过使用消息维护唯一的ID,服务器可以看到客户端错过了n条消息,并在重新连接时发送了未完成消息的积压。

让我们看看示例客户端实现的外观:

const evtSource = new EventSource('/events');

evtSource.addEventListener('event', function(evt) {

const data = JSON.parse(evt.data);

// Use data here

},false);

此代码段非常简单。它连接到我们的源并等待接收消息。现在,示例NodeJS服务器将如下所示。

// events.js

const EventEmitter = require('eventemitter3');

const emitter = new EventEmitter();

function subscribe(req, res) {

res.writeHead(200, {

'Content-Type': 'text/event-stream',

'Cache-Control': 'no-cache',

Connection: 'keep-alive'

});

// Heartbeat

const nln = function() {

res.write('\\n');

};

const hbt = setInterval(nln, 15000);

const onEvent = function(data) {

res.write('retry: 500\\n');

res.write(event: event\\n);

res.write(data: ${JSON.stringify(data)}\\n\\n);

};

emitter.on('event', onEvent);

// Clear heartbeat and listener

req.on('close', function() {

clearInterval(hbt);

emitter.removeListener('event', onEvent);

});

}

function publish(eventData) {

// Emit events here recieved from Github/Twitter APIs

emitter.emit('event', eventData);

}

module.exports = {

subscribe, // Sending event data to the clients

publish // Emiting events from streaming servers

};

// App.js

const express = require('express');

const events = require('./events');

const port = process.env.PORT || 5001;

const app = express();

app.get('/events', cors(), events.subscribe);

app.listen(port, function() {

console.log('Listening on', port);

});

我们从这种方法中获得的主要好处是:

  • 实施更简单,数据效率更高
  • 开箱即用地通过HTTP / 2自动多路复用
  • 将客户端上数据的连接数限制为一个

如何在SSE,WebSocket和Polling中进行选择?

经过漫长而详尽的客户端和服务器实施之后,SSE似乎是我们解决数据交付问题的最终答案。也有一些问题,但是可以解决。

可以利用服务器发送事件的应用程序的一些简单示例:

  • 实时股价流图
  • 重要事件的实时新闻报道(发布链接,推文和图片)
  • 由Twitter的流API提供的实时Github / Twitter仪表板墙
  • 监视服务器统计信息(如正常运行时间,运行状况和正在运行的进程)的监视器。

但是,SSE不仅是其他提供快速更新的方法的可行替代方案。在某些特定情况下,例如在SSE被证明是理想解决方案的情况下,每个人都可以胜过其他人。考虑一个像MMO(大型多人在线)游戏这样的场景,该场景需要来自连接两端的大量消息。在这种情况下,WebSockets将压制SSE。

如果您的用例需要显示实时的市场新闻,市场数据,聊天应用程序等,例如在我们的案例中,依靠HTTP / 2 + SSE将为您提供有效的双向通信渠道,同时又能获得留在其中的好处HTTP世界。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Web
    Web
    +关注

    关注

    2

    文章

    1253

    浏览量

    69110
  • 服务器
    +关注

    关注

    12

    文章

    8750

    浏览量

    84678
收藏 人收藏

    评论

    相关推荐

    Django3如何使用WebSocket实现WebShell

    websocket 服务。 大致看了下觉得这不够有趣,翻了翻 django 的官方文档发现 django 原生是不支持 websocket 的,但 django3 之后支持了 asgi 协议可以自己实现
    的头像 发表于 11-17 09:58 4227次阅读

    一文详解WebSocket协议

    WebSocket出现之前,一个Web应用(即时聊天、多人协作)的客户端和服务端之间常见的双向数据交换方式有短轮询、长轮询SSE(Server-Sent Events,服务器发送事
    的头像 发表于 01-07 11:26 6662次阅读
    一文详解<b class='flag-5'>WebSocket</b>协议

    sse指令集

    sse指令集 SSE(Streaming SIMD Extensions,单指令多数据流扩展)指令集是Intel在Pentium III处理器中率先推出的。其实,早在PIII正式推出之前
    发表于 12-25 10:59 1509次阅读

    什么是SSE/SIMD/Speculative execut

    什么是SSE/SIMD/Speculative execution? SSE(Streaming SIMD Extensions,单一指令多数据流扩展) 英特尔开发的第二代SIMD指令集,有70条指令,
    发表于 02-04 11:14 517次阅读

    什么是Superscalar/SSE/SQRT

    什么是Superscalar/SSE/SQRT   Superscalar: (超标量体系结构)在同一时钟周期可以执行多条指令流的处理器架构。 SSE: (Streami
    发表于 02-04 11:27 594次阅读

    基于SSE的FDTD程序设计李太全

    基于SSE的FDTD程序设计_李太全
    发表于 03-17 08:00 1次下载

    什么是WebSocket?进行通信解析 WebSocket 报文及实现

    一般情况下全为 0。当客户端、服务端协商采用 WebSocket 扩展时,这三个标志位可以非0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用 WebSocket 扩展,连接出错。
    的头像 发表于 05-15 16:59 9629次阅读
    什么是<b class='flag-5'>WebSocket</b>?进行通信解析 <b class='flag-5'>WebSocket</b> 报文及实现

    Python如何爬取实时变化的WebSocket数据

    Python 中的网络请求库非常多,Requests 是最常用的请求库之一,它可以模拟发送网络请求。但是这些请求都是基于 HTTP 协议的。在面对 WebSocket 的时候 Requests 就发挥不料作用了,必须使用能够连接 WebSocket 的库。
    的头像 发表于 03-11 09:31 3469次阅读
    Python如何爬取实时变化的<b class='flag-5'>WebSocket</b>数据

    WebSocket有什么优点

    WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。HTML5开始提
    的头像 发表于 02-15 15:53 8191次阅读
    <b class='flag-5'>WebSocket</b>有什么优点

    什么是SSE MMX和SSE的区别

    说到SSE,首先要弄清楚的一个概念是SIMD(单指令多数据流,Single Instruction Multiple Data),是一种数据并行技术,能够在一条指令中同时对多个数据执行运算操作,增加处理器的数据吞吐量。
    的头像 发表于 03-22 15:21 1.5w次阅读
    什么是<b class='flag-5'>SSE</b> MMX和<b class='flag-5'>SSE</b>的区别

    WebSocket工作原理及使用方法

    它有很多名字; WebSocketWebSocket协议和WebSocket API。从首选的消息传递应用程序到流行的在线多人游戏,WebSocket在当今最常用的Web应用程序中是
    的头像 发表于 05-05 22:12 7773次阅读
    <b class='flag-5'>WebSocket</b>工作原理及使用方法

    CMOS和CCD哪个视觉效果更好

    电子发烧友网站提供《CMOS和CCD哪个视觉效果更好.zip》资料免费下载
    发表于 01-31 09:27 0次下载
    CMOS和CCD<b class='flag-5'>哪个</b>视觉效果<b class='flag-5'>更好</b>

    鸿蒙上WebSocket的使用方法

    WebSocket 是一种网络通讯协议,很多网络开发工作者都需要它。本文介绍在 OpenHarmony 上 WebSocket 协议的使用方法。
    的头像 发表于 03-08 14:17 1590次阅读

    气动执行器与电动执行器:哪个更好

    气动执行器与电动执行器:哪个更好
    的头像 发表于 03-13 16:30 4542次阅读
    气动执行器与电动执行器:<b class='flag-5'>哪个</b><b class='flag-5'>更好</b>?

    websocket协议的原理

    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。 WebSocket通信协议于2011年被IETF
    的头像 发表于 11-09 15:13 867次阅读
    <b class='flag-5'>websocket</b>协议的原理