服务器推送技术

20 篇文章 0 订阅

服务器推送技术是最近在项目中有可能要用到的一项技术,所以提前研究了一下。

考虑这样一个场景,在各类WEB应用中,如果有其他用户更改了某位用户正在关注的任何消息,则用户希望得到通知。如果一个 Web 站点显示动态数据,如股价等,那么所有用户都必须立即得到关于变更的通知。

这些场景本身属于一类称为 “服务器推送” 的问题。通常,服务器是中心实体,服务器将首先获得关于所发生的任何更改的通知,服务器负责将此类更改通知所有连接的客户端。但遗憾的是,HTTP 是客户端-服务器通信的标准协议,它是无状态的,而且在某种意义上来说,也是一种单向的协议。HTTP 场景中的所有通信都必须由客户端发起,至服务器结束,然而我们所提到的场景的需求则完全相反。对于服务器推送来说,需要由服务器发起通信,并向客户端发送数据。HTTP 协议并无相关配置,Web 站点应用程序开发人员使用独创的方法来绕过这些问题,

目前来说,服务器推送(PUSH)机制大致分为几种:

1. 短轮询

客户端以固定(或可配置)的时间间隔与服务器联系,查找是否有新的更新可用。在大多数时候,这些轮询纯粹是浪费,因为服务器没有任何更新。这种方法不是没有代价的,它有两大主要问题:

首先,这种方法非常浪费网络资源,

其次,因为轮询有一定的时间间隔,因此客户端不会获得实时的更新。

2. 长轮询

长轮询是用于更新服务器数据的另外一种方法。这种方法的理念就是客户端建立连接,服务器阻塞连接(通过使请求线程在某些条件下处于等待状态),有数据可用时,服务器将通过阻塞的连接发送数据,随后关闭连接。客户端在接收到更新后,立即重新建立连接,服务器重复上述过程,以此实现近于实时的通信。然而,长轮询具有以下缺陷:
一般的浏览器默认允许每台服务器具有两个连接。在这种情况下,一个连接始终是繁忙状态。因而,UI 只有一个连接(也就是说,能力减半)可用于为用户请求提供服务。这可能会导致某些操作的性能降低。
仍然需要打开和关闭 HTTP 连接,如果采用的是非持久连接模式(keepAlive=false),那么这种方法的代价可能极高。
这种方法近于实时,但并非真正的实时。(当然,某些外部因素总是不可控的,比如网络延时,在任何方法中都会存在这些因素。)

3. 流传送

流通道(streaming channel)与长轮询大致相同,差别在于服务器不会关闭响应流。而是特意保持其处于打开状态,使浏览器认为还有更多数据即将到来。但是,流通道也有着自己的缺陷:
最大的问题就是数据刷新(flushing)。

如果发现套接字将打开较长的时间,某些浏览器实现可能会自行决定关闭套接字。在这种情况下,通道需要重新建立。

通常,第一个问题可通过为每个流响应附加垃圾有效载荷来解决,使响应数据足以填满缓冲区。第二个问题可通过 “保持活动” 或按固定间隔 “同步” 消息来欺瞒浏览器,使浏览器认为数据是以较慢的速率传入的。

下面介绍一些常用的实现推送的技术。

1. Comet

Comet 有时也称反向 Ajax 或服务器端推技术(server-side push)。其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据。听起来简单,但是如果熟悉 Web 应用程序,尤其是 HTTP 协议,那么您就会知道,这绝不简单。实现 Comet 风格的 Web 应用程序,同时保证在浏览器和服务器上的可伸缩性,这只是在最近几年才成为可能。

对于 Apache Tomcat,若要使用 Comet,主要需要做两件事。首先,需要对 Tomcat 的配置文件 server.xml 稍作修改。默认情况下启用的是更典型的同步 IO 连接器。现在只需将它切换成异步版本,如下 所示。

<!-- This is the usual Connector, comment it out and add the NIO one -->
   <!-- Connector URIEncoding="utf-8" connectionTimeout="20000" port="8084" 
protocol="HTTP/1.1" redirectPort="8443"/ -->
<Connector connectionTimeout="20000" port="8080" protocol="org.apache.
coyote.http11.Http11NioProtocol" redirectPort="8443"/>

然后,创建一个实现 org.apache.catalina.CometProcessor 接口的 servlet。CometProcessor 接口要求实现 event 方法。这是用于 Comet 交互的一个生命周期方法。Tomcat 将使用不同的 CometEvent 实例调用。通过检查 CometEvent 的 eventType,可以判断正处在生命周期的哪个阶段。当请求第一次传入时,即发生 BEGIN 事件。READ 事件表明数据正在被发送,只有当请求为 POST 时才需要该事件。遇到 END 或 ERROR 事件时,请求终止。

具体的例子,请参照这个地址。

而目前常用的Comet框架有:

CometD:是一个Dojo Fondation的项目,它提供了 Bayeux protocol 的javascript、java、perl、python及其他语言的实现。在CometD的站点里同时提供了Sun,IBM,BEA等公司的Comet的实现的产品的链接。


2. HTML5

HTML5提供了两种符合W3C标准的推送方式:SSE和Web Socket。

先介绍一下SSE(Server-sent-envets),以PHP服务端为例,

客户访问的页面是

sse.htm

<!DOCTYPE html>  
<html>  
<body>  
  <script>  
    var source = new EventSource('source.php');  
    source.onmessage = function(event){  
      var text = event.data;  
      window.webkitNotifications.createNotification('', 'Alert', text).show();  
    }  
  </script>  
</body>  
</html>

服务端推送消息的脚本是

source.php

header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");

mysql_connect("localhost", "user", "pass");
mysql_select_db("eventstream");

$q = mysql_query("select textnotif from notification where read='0'");
$r = mysql_fetch_array($q);

$notif = $r[textnotif];

if($notif != ""){  
    echo "data: ".$notif.PHP_EOL;  
}

SSE实现了从服务器到客户端的单向推送消息的功能,目前浏览器Chrome,Safari都可以支持。具体还有哪些浏览器支持,可以点这里查看。

而WEB Socket提供了一个双向的消息通道。WebSocket 是通过 HTTP 协议的初始握手阶段然后升级到 Web Socket 协议以支持实时数据通信。WebSocket 协议设计了更为轻量级的 Header。

这里可以参考到一个使用WebSocket技术的实例。而目前网上关于WebSocket的内容还是比较多的。

由于WebSocket具有双向沟通的优势,因此可以实现聊天室、游戏、股票交易等等需要双向通讯的应用上。而SSE虽然只能实现从服务器向客户端的单向推送,但是它可以自动重新链接,具备EventID等优势,因此也有用武之地。

而另外一个可作参考的轻量级的服务器推送框架是Pushlets,它提供了从HTTP Push到DHTML,以及Pushlets框架的具体实现实例。

参考:

1.使用 Java 实现 Comet 风格的 Web 应用 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值