数据推送方式- polling vs Websocket vs SSE

本文介绍了实时Web应用程序的三种主要技术:long polling、WebSocket和Server-Sent Events(SSE)。内容包括它们的工作原理、优缺点及适用场景。WebSocket提供双向通信,适合需要大量双向消息传递的场景;SSE则是单向推送,易于实现且与HTTP/2兼容,适用于股票价格、新闻报道等实时更新的场景;而polling则根据需求分为long和short,适合更新频率较低的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们可以使用以下三种方式来创建一个实时的web应用程序

  1. Long polling or short polling(client pull)
  2. WebSocket(server push)
  3. Server-Sent Events(server push)

client pull: 客户端以一定的间隔来请求server来获取更新数据

server push:
服务器主动向客户端推送更新

long polling

这里简单说一下 short polling 和 long polling 的区别, poll是客户端代码中每隔一段时间访问一次server(for 循环访问)long polling 是用 Transfer-Encoding: chunked (也是 http comet)的方式 设置一个超长的超时时间,每当服务端有更新则用这个链接 一个chunk 一个chunk 返回给客户端数据。

http comet 除了使用long polling 还用 iframe

Using WebSockets

websocket 本质上就是一个贯穿 client & server的一个链接,websocket协议在一条tcp链接上提供了全双工的通信信道。

RFC 6455 上注明,websocket 是一个被设计在http 80 & 433 端口上的并且兼容http代理和中介的协议, 这使得 websocket 基本上完全兼容http协议, 为了实现完全兼容性,websocket 握手协议使用http 的 Upgrade 请求头 去将http协议换成websocket协议,

http 协议 和 websocket 协议都是建立在tcp协议之上的 七层协议

client:

$(function () {
    window.Websocket = window.Websocket || window.MozWebSocket;
    const connection = new WebSocket('ws://localhost:8080/githubEvents');
    connection.onopen = function(){}
    connection.onerror = function(error){}
    connection.onmessage = function(message){}
    
})

server:

const express = require('express')
const event = 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){});
app.ws('/', function(ws, req){
    const githubEvent = {}
    ws.send('message', githubEvent)
})
app.listen(port, function(){})

some pitfalls

  • 如果使用websocket, 我们得处理很多http帮我们自动处理的东西
  • websocket是一种用于传输数据的协议,它并不会兼容http/2的链接, 在客户端&服务端自己实现多路复用有些复杂
  • websocket 是基于frame的, 并不是基于流的。

Using SSE

SSE 是一种可以让服务端在已建立的链接上 push data 到客户端的协议,可以被考虑成 单向发布-订阅的模型,它并不像websocket一样是双向数据协议, 只是从服务器向客户端推数据这一单项的数据流, 是在HTML5 中新加入的。

通过实现 javascript EventSource来编写客户端。

由于SSE是基于http的, 所以SSE可以天然支持HTTP/2, SSE可以和HTTP/2 结合使用。 HTTP/2 处理基于多路复用流的高效传输层, SSE 则为应用进程提供api来启动推送功能

client:

const evtSource = new EventSource('/evnets')

evtSource.addEventListener('event', function(evt) {const data = JSON.parse(evt.data)}, false);

我们使用Python的generator 来进行数据推送, 因为它可以不断生产出数据来进行推送, 与SSE的场景十分吻合。

server in flask

@route("/events")
def stream():
    def eventStream():
        while True:
            # Poll data from the database
            # and see if there's a new message
            if len(messages) > len(previous_messages):
                yield "data: 
                    {}\n\n".format(messages[len(messages)-1)])"
    
    return Response(eventStream(), mimetype="text/event-stream")

SSE 主要有以下三点好处

  • 更简单的实现方法和更高效的数据传输效率
  • 可以集成HTTP/2 实现多路复用(一个浏览器与server只使用一个http链接)
  • 可以限制客户端上的连接数

我们应该如何选择 SSE, WebSocket and polling

按照上面的例子来看, 我们似乎可以认为SSE是最适合的,但是SSE也存在一些问题等待我们解决。

以下是我们可以使用SSE的几个例子

  • 流媒体股票价格实时图表
  • 实时重要新闻的报道(发布链接,推送文和图片)
  • 由twitter或者是github的流媒体推送的实时仪表盘
  • 各种系统监控

也有一些SSE不适合的场景, 比如像MMO(大型多人在线)游戏这样的场景, 它需要来自链接两端大量的消息(全双工)这时 websocket 则占据完全优势。

如果你的使用场景是 实时显示市场新闻,股市数据,聊天记录之类的, 那么 HTTP/2 + SSE 将会给你提供非常高效的数据传输方式

参考: https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值