数据同步机制-轮询、长轮询、comet、Socket
背景
前面在做即时通讯相关业务的时候发现了一个有趣的点,即时通讯的实现方式是怎样的,仔细翻阅了一波文档发现在腾讯IM中他们使用的是普通轮询机制,在网易IM中他们使用的是可配置的(websocket、xhr-polling、flashsocket )三选一模式
探索点
基于上面的背景之下,想对websocket、xhr-polling、flashsocket三者进行一波学习了解,以及联想到早前使用comet实现单点登录的原理是什么,数据同步的发展历程是怎样的
发展历程
数据同步可以说应用场景十分普遍的一个需求,需要实时从服务端更新数据到客户端,随着技术的发展,历史长河中也出现了不同版本的实现方式
传统轮询
在web早期,并不是通过ajax请求去来刷新数据的,需要实现数据的同步都是通过设置mate来刷新实现,指示浏览器在指定秒数之后重新装载页面,从而支持简陋的轮询(polling)
例如,在HTML文件中加入<META HTTP-RQUIV="Refresh" CONTENT=10>,就是HTTP头标告知浏览器每十秒重载入一次文档
缺陷:
-
十分糟糕的用户体验,需要重新渲染DOM结构和数据
-
对服务器来说要命,以及宽带资源的浪费
AJAX轮询
ajax轮询机制可以说有着辉煌的历史,至今依旧很多地方使用着,用它实现数据同步的方式可简单分为两种
-
普通轮询(polling)
使用setIntervel模式,每隔一段时间就去请求一次服务器,查询数据是否有改变,从而进行增量式的更新
但是间隔多长时间去查询成了问题,因为性能和即时性造成了严重的反比关系,间隔太短,连续不断的请求会冲垮服务器,间隔太长,数据的更新就会出现很高的延迟
优点:
-
使用十分简单粗暴,不需要服务端做什么配置
-
相对传统轮询来说还是降低了宽带资源的浪费
缺点:
-
对服务器来说依旧有很大的压力,无法支撑大量用户
-
及时性较差,可能会有较高的延迟
-
第二次的新数据可能会被第一次的数据覆盖,虽然几率很小
-
-
长轮询(long-polling)
长轮询是对普通轮询的升级,普通轮询对于服务器来说亚历山大,过多请求直接可能压爆服务器,因为它并不管服务端是否有新数据啥的,始终隔一段时间就发起请求
基于此,延伸出了长轮询,方案是在客户端发起请求后如果服务端没有新数据需要返回给客户端,那么服务端将会把此请求挂起,即阻塞此次请求,等有数据需要返回给客户端时才进行相应,然后关闭此次请求,客服端接收到相应关闭此次请求后将再次发起一个新的请求,如此循环往复,来实现数据到同步
优点:
-
降低了同步延迟
-
可以支撑大量用户
-
降低了宽带资源的浪费
-
不会出现数据被覆盖的情况
缺点:
-
长期占用连接,无状态高并发功能丧失
-
链接中断几率不低
-
不能在同一个客户端开启超过两个的http长连接,受http协议限制
-
COMET
comet 有时也称反向Ajax或服务器端推技术(server-side push),其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据,精髓就在于用服务器与javascript来维持浏览器的长连接,同时完成服务器端事件的客户端端响应(客户端实时响应服务端的同步)
comet是长轮询的一个应用场景之一,但是comet的实现方式又不止长轮询一种
另一种实现comet机制:基于iframe及htmlfile流的方式(永久帧),iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间建立一条长链接,服务器向iframe传输数据(通常是HTML),内有负责插入信息的JavaScript),来实时更新页面
优缺点同步长轮询
FlashSocket
FlashSocket(经由Flash的套接口),它是WebSocket发展过程中的一个过渡产物,在初期的WebSocket并不被所有浏览器支持,这些库通常会提供同样的官方WebSocket API,但他们是通过把调用委托给一个包含在网站中的隐藏的Flash组件来实现的
优点:
-
FlashSocket透明地提供了WebSocket的功能,即使是在不支持HTML5 WebSocket的浏览器上也是如此
缺点:
-
其需要安装Flash插件
-
要求防火墙的843端口是打开的,这样Flash组件才能发出HTTP请求来检索包含了域授权的策略文件
-
如果客户端处在某个代理服务器的后面的话,到端口843的连接可能会被拒绝
属于过渡性产品,几乎已被淘汰
WebSocket
在HTML5中出现的WebSocket是一种比Comet还要新的反向Ajax技术,WebSocket启用了双向的全双工通信信道,许多浏览器(Firefox、Google Chrome和Safari)都已对此做了支持。连接是通过一个被称为WebSocket握手的HTTP请求打开的,其用到了一些特殊的报头,连接会保持在活动状态,可以使用JavaScript来写入和接收数据,就像是在使用一个原始的TCP套接口一样,而且WebSocket与http协议一样都是基于TCP来进行数据的传输的,属于对TCP数据传输的一种规范,所以它是可靠的协议
WebSocket伟大之处在于服务器和客户端可以在链接期间的任意时刻,相互推送信息,而且并不限于以Ajax或XHR方式通信,因为Ajax技术需要客户端发起请求,而webSocket服务器和客户端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允许跨域通信,webSocket URL的起始输入是ws://或是wss://
const ws = new WebSocket(“ws://echo.websocket.org”) ws.onopen = () => {ws.send(“Test!”) } ws.onmessage = function(evt){console.log(evt.data);ws.close()} ws.onclose = function(evt){console.log(“WebSocketClosed!”)} ws.onerror = function(evt){console.log(“WebSocketError!”)}
优点:
-
WebSocket功能强大、双向、低延迟,且易于处理错误
-
不会像comet长轮询那样有许多的连接
-
API容易使用,无需另外的层就可以直接使用
遗留点
-
套接字
-
Ajax与XHR的关系
-
wx传输过程