为分布式做准备吧——从Ajax到WebSocket


当需要前端频繁的请求后端数据的时候,比如说数据的实时显示,这种情况下产生问题的核心原因是:服务器知道数据什么时候更新,但浏览器不知道。
这种情况下,即使对于强大的Ajax,也是一个难以解决的问题。

解决方案1:频繁轮询

当我们手中只有ajax工具的时候,我们往往会选择这样的解决方式:
通过设定定时器,以一个固定的频率(比如1秒/次)将ajax请求打到服务器查询新的数据。如果后端有数据,则返回新数据,如果没有,就返回空。

这样的协议在请求不需要那么频繁并且用户量小的时候,勉强能用。很明显,该协议有大量的请求被浪费了,并且服务器做出了大量无效的响应。

解决方案2:长轮询

长轮询其实是频繁轮询的一个妥协,他与频繁轮询一样,也是需要前端不断的打请求,但是如果服务器没有新数据,那么服务器对前端的请求不做响应。

该方法会出现下面三个问题:

  1. 如果浏览器在服务器响应之前,有新数据发送到服务器怎么办?
    浏览器必须创建一个新的并行请求,或者终止当前请求然后创建新的请求。
  2. TCP和HTTP连接都指定了连接超时,所以服务器和客户端必须周期性的关闭和重建连接。
  3. HTTP/1.1规范中存在着强制的连接限制。浏览器最多只允许同时创建两个到相同主机名的连接。如果一个连接长期连接到服务器等待数据推送,那么它将减少一般可用于从服务器抓去web页面、图形和其他资源的连接。

在过去几年,长轮询得到了广泛的应用,通常被称为Comet。

解决方案3: 分块编码

持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界;而对于持续连接,这种方法显然不奏效。有时,尽管我已经发送完所有数据,但浏览器并不知道这一点,它无法得知这个打开的连接上是否还会有新数据进来,只能傻傻地等了。
为了不让浏览器等待,响应对象一般使用一个Content-Length:n头来告知浏览器这个数据有多长。浏览器可以通过 Content-Length 的长度信息,判断出响应实体已结束。
Content-length引入的新问题:由于 Content-Length 字段必须真实反映实体长度,但是对于动态生成的内容来说,在内容创建完之前,长度是不可知的。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。
我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界——分块编码(Transfer-Encoding: chunked)。

分块编码非常类似于长轮询,它利用了HTTP/1.1的特性:服务器可以在不声明内容长度的情况下响应请求。
响应在不使用Content-Length:n头时,可以使用Transfer-Encoding:chunked头。这样将告诉浏览器 响应对象将被“分块发送”。

利用这一特性,在开始的时候创建一个连接,只用于接受服务器发送的时间,来自服务器的每一个块都是一个新事件,它们将出发JavaScript XMLHttpRequest对象的onreadystatechange时间处理器的调用。

尽管不如长轮询那么频繁,但是连接仍然需要更新。

解决方案4: Applet和Adobe Flash

在演变的过程中,人们渐渐意识到这些解决方法所做的其实是**通过单个连接来模拟全双工通信。**简单来说,Ajax和XMLHttpRequest无法完成该任务,一个更流行尽管更短命的解决方案是Java Applet或者Adobe Flash。

开发者将创建一个含有1个像素的普通透明Applet或者Flash影片,并内嵌在网页中,然后这个插件将创建出连接到服务器的TCP Socket连接(而不是Http连接)。这种方式消除了HTTP协议中的制约限制。

该协议在单个连接上实现了真正的全双工通信,并消除了例如超时和兵法连接限制这样的问题,但也带来了很高的代价:使用第三方插件。
很显然,这两种技术在今天已经被淘汰了。

WebSocket

HTTP升级特性包含了如下一点:
最终我们可以使用任意的协议。
这意味着,在HTTP升级特性 在握手完成后,就可以不再使用HTTP连接,而是使用一个持久的、全双工的TCP Socket连接。
理论上讲这是行得通的,但是浏览器不会让JavaScript开发者随意使用TCP栈,所以就需要指定某些协议,因此就产生了WebSocket协议。

WebSocket连接首先将使用非正常的HTTP请求以特定的模式访问一个URL。URL模式ws和wss分别对应于HTTP的http和https。通过一个Connection:websocket头告诉服务器把连接升级称为WebScoket协议——一个全双工持久的通信协议。

WebScoket协议的实现方式有许多优点:

  • 因为连接在端口80(ws)或者443(wss)上创建,与HTTP使用的端口相同,几乎所有的防火墙都不会阻塞WebSocket连接。
  • 因为它使用HTTP握手,该协议可以集成到网络浏览器和HTTP服务器中。
  • 心跳机制。
  • WebSocket连接关闭时将发送一个特殊的关闭消息,其中可以包含原因代码和用于解释连接被关闭原因的文本。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值