Pushlet框架改进及其应用整合
2012-05-12李赛男余金山
李赛男 ,余金山
(1.华侨大学 计算机科学与计算学院,福建 厦门 361021;2.华侨大学 计算机科学与计算学院,福建 泉州 362011)
一些实时监控、在线即时通信、RIA的Web应用等系统状态发生变化时需要及时反馈数据给客户端。这种实时交互可以利用推技术来实现。随着Ajax技术的兴起,系统的实时性也出现新的解决方案——服务器推送(Comet[1])。服务器推送不同于以往的推技术,它是基于Web平台、通过Http长连接、无须安装插件的服务器向客户端推送数据的纯浏览器技术。
服务器推送是通过保持客户端与服务器端的Http连接,当服务器端状态发送变化时,将数据发送给客户端浏览器,由浏览器负责显示这些数据,然后连接继续被维持,等待下一次服务器推送[2]。
Pushlet是一种轻量级的服务器推送开源框架,相对于其他流行的推送框架如Dojo+Jetty、DWR等,Pushlet有以下优点:
(1)通用性。Pushlet框架是基于 Servlet实现的,可以在任何一种支持Servlet的服务器上运行。
(2)简单易用。Pushlet提供了一组简明用户接口,使用户能方便地使用Pushlet框架,而且客户端使用Java Script技术,可以很容易与已有的Web应用程序集成。
(3)可配置性。Pushlet使用属性文件配置框架中的各种组件,用户可以用自己开发的组件替换Pushlet提供的组件。
(4)扩展性。对于比较复杂的推送应用,用户可以自由扩展Pushlet框架。
(5)协议简单。Pushlet的客户端和服务器端交互采用的协议是经过简化的bayeux协议。
但是Pushlet主要关注Comet服务器端的实现,相对其在数据传输和客户端方面设计实现上存在一些不足:
(1)Pushlet使用的数据传输格式只能存储结构简单的消息数据。
(2)客户端只能连接一个Pushlet服务器。
针对上述不足,本文提出使用JSON格式存储服务器发送的数据,在创建Pushlet服务器连接方面,使用OOP思想把连接封装成类,以便多次创建连接对象连接多个Pushlet服务器。
1 Pushlet的主要技术
Pushlet是Comet的开源框架,它提供基于Ajax长轮询方式和基于iframe的流方式两种的服务器推送实现[3]。整个框架涉及服务器端以及客户端的实现。服务器端采用Servlet技术监听客户端请求,客户端采用JavaScript技术并实现跨浏览器实现。Pushlet服务器端框架和客户端框架基于 Pushlet协议,协议示意图分别如图1、图 2所示。
图1 Ajax长轮询模式的Pushlet交互协议
图2 streaming模式的Pushlet交互协议
Pushlet协议[4]组成:
(1)会话管理:客户端发送 “join”请求建立一个Pushlet会话,以后服务器通过这个会话管理该客户端的所有请求。客户端发送“listen”请求来监听并准备接收服务器端的数据。Pushlet还提供了一个快捷请求“joinlisten”合并这两步请求。客户端发送的“leave”请求用来断开会话。
(2)主题订阅:客户端通过“subscribe”请求向服务器订阅一个或多个主题,告诉服务器如果这个主题的状态发生改变了就告诉我。客户端也可以通过“unsubscribe”来取消一个或多个主题的订阅。
(3)消息发布:客户端可以通过发送“publish”请求让服务器广播或多播它的消息。
(4)数据推送:服务端通过发送“data”消息向客户端推送数据。
(5)心跳消息:在连接快超时时,服务器向发送“heartbeat”消息说明会话还存活,以防浏览器请求超时。
(6)刷新消息:在 Ajax长轮询的模式下,服务器每次有数据返回消息给客户端、发送心跳信号、返回listen-ack时,都必须再发送一条refresh消息给客户端,告诉客户端在多长时间后发送“refresh”请求重新建立连接以保持长Http连接。
为加强协议的可靠性,客户端向服务器端发送的控制请求,服务器都会返回相应的ack消息。Pushlet靠两条Http连接与服务器交互:一条是专门发送控制请求;另外一条则是专门接收数据的长连接,这个长连接是以“listen”请求开始的。
Pushlet整体框架如图3所示[5]。
图3 Pushlet整体框架图
2 Pushlet框架的不足与改进
2.1 数据传输格式的不足与改进
Pushlet框架中基于Ajax长轮询的客户端框架从服务器端获得的是XML格式的数据,其格式是<event消息字段="字段值".../>,具体示例如下:
Pushlet虽然使用了具有强大数据描述能力的XML来存储推送的数据,可是它只是简单地利用元素的属性来存储键/值对格式的消息数据,类似HTTP GET请求的 QueryString, 如 :p_event=join-listen-ack&p_mode=pull&p_time=1321791777&p_id=qegagopapu。 这种 键/值 对的数据格式只能存储简单信息,不易存储额外的复杂数据。如上述例子中从服务器获得的数据相当于服务器使用XML格式传送Pushlet协议的头部信息,而复杂的实际数据很难使用这种键/值的格式存储。
对于上述Pushlet的局限性,可以使用JSON进行数据传输。按照Ajax的定义,原则上应该采用传统的XML数据传输格式。可是XML是一种结构化的文档,在服务器和客户端均需要进行手工解析[6]。这种方案不仅存在解析时的复杂性问题,而且对于不同浏览器存在兼容性问题。此外,XML使用的标签会产生大量的数据冗余减低数据传输效率。相对地JSON是一种轻量级的数据交换格式,它是JavaScript规范的子集,本质上就是JavaScript的复合对象。所以JSON易于被浏览器解析和生成,也可以表示非常复杂的数据。故本文选择JSON作为数据传输格式,把服务器传送的数据使用JSON格式传输,具体如下:
2.2 客户端框架的不足与改进
基于Ajax长轮询的Pushlet客户端框架还有一个局限就是一个客户端只能和一个Pushlet服务交互。这个客户端框架使用JavaScript函数式编程,只能定义Window的一个全局变量建立一个会话与Pushlet服务端交互。为使客户端可以创建多个会话与多个Pushlet服务端交互,本文使用面向对象方法封装已有的框架创建会话类,这样就可以定义多个会话对象创建多个连接。
改进后客户端框架中各个类实例之间的交互如图4所示。
(1)Session: 会 话 管 理 类 , 包 含 Pushlet服 务 端 的URI、会话ID、会话状态。用户可以通过Session对象进行命令请求。对于接收到消息后的处理函数,则可以通过配置对象在创建Session实例时指定。
(2)Check:状态验证类,验证当前会话状态保证正确的协议时序。
(3)Control:消息路由类,根据接收到消息分发给相应的消息处理函数。
(4)Ajax:异步通信类,封装 Ajax功能直接与服务器端通信。
(5)PushletEvent:Pushlet事件类,负责解析事件消息和生成事件。
图4 改进后的客户端框架时序图
使用JSON进行数据交互,相应地在服务器端也需要有一个JSON数据发送器。Pushlet的服务器端框架提供了一个专门用于向客户端发送数据的ClientAdapter接口,这个JSON数据发送器就必须实现这个ClientAdapter接口。另外还需在Command类的createClientAdapter方法中增加一个判断来生成JSON数据发送器的实例。
3 在Web投票系统中应用
3.1 总体描述
以往大部分的Web投票系统都只是实现最基本的功能:发起投票和投票并评论,如QQ群社区的群投票。在有些决策性投票中,用户希望能看到投票的实时情况。为此用户必须时刻刷新页面才能看到投票的最新情况。本文应用改进的Pushlet框架技术实现的Web投票系统,是在基本的投票应用功能上增加显示实时投票情况的功能。
投票Web应用主要分5个模块:发起投票模块、投票查询模块、投票模块、登录/注册模块、网站状态模块。该应用只有注册用户才可以发起投票,投票可以分为匿名投票和实名投票。投票查询又分一般查询、过期投票查询、未过期投票查询、用户参与的投票和用户发起的投票。投票模块需要显示各个候选项的投票比例和用户的投票留言。网站状态模块则是显示网站的基本信息,如注册的用户、总发起投票的个数等。本应用的实现使用了SSH2框架,网站前台实现使用Ext JS框架,服务器推送部分使用Pushlet框架。投票Web应用的总体架构如图5所示。
图5 投票Web应用的架构
3.2 部分具体实现
为进一步说明改进的Pushlet框架技术的具体应用,下面给出系统的某些部分的实现。系统的实时性需求有如下两点:(1)当有用户注册或发起投票后,该应用的基本信息就会改变,这时服务器就需要推送该应用最新的基本信息给客户端;(2)当用户投票成功后,该项投票的候选项的票数比例会改变,而且也会有新的投票留言,这时服务器也需要推送该项投票的最新信息给客户端。
Pushlet通过主题来管理所有需要推送的数据。主题采用具有层次的树形结构,上层主题包含下层主题,类似文件系统的目录,如/system/time、/system/tem 就 表 示两个主题。如果订阅主题为“/system”,则表示同时订阅了/system下的所有子主题 (/system/time和/system/tem);如果订阅主题为“/”的根主题,则表示订阅了服务器里所有的主题。
该应用中主要有两个大主题:网站最新基本信息和投票最新信息,分别用“/vote/basic”和“/vote/info”表示主题。网站基本信息包括多个项目,如用户注册人数、发起投票总个数等,这些信息按项目名称划分主题:“/vote/basic/项目名称”。用户可能同时进行多项投票,投票最新信息按照投票 ID划分主题:“/vote/info/投票 ID”。每个客户端都必须订阅“/vote/basic”主题,在打开一个投票表单时需要订阅“/vote/info/该投票ID”主题。
图6是客户端与服务器直接交互的具体情况。当有新用户注册时,服务器会向其他客户端推送网站的注册用户数的基本信息。当有用户确定投票时,服务器也会推送投票的最新情况。
该应用的客户端是基于Ext JS框架并使用经典的MVC模式和命名空间来组织代码。Ext控件的配置和布局放在视图包,Ext的事件处理函数和Pushlet客户端框架放在控制包,Ext控件的Store和数据模型Model放在数据模型包。为与Ext异步调用的技术一致,Pushlet框架的客户端选用基于Ajax长轮询的方式。这里使用JSON数据方式传送,引用的框架库文件是改进后的框架库文件。该应用的服务器端则需要在调用相关逻辑层服务后调用Pushlet的分发函数,向客户端推送数据。具体服务器端组件间的交互如图7所示。
图6 客户端与服务器的交互
图7 服务器端各组件之间的交互
Pushlet框架在该应用中的集成步骤如下:
(1) 把 pushlet.jar复制到 WebRootWEB-INFlib下,并添加进classpath。
(2)把pushlet.properties和sources.properties复制到WebRootWEB-INF下。pushlet.properties是Pushlet的配置文件,本应用中没有用到数据源,需要把sources.activate的值设为false。
(3)把Pushlet改进后的客户端框架的文件Ajax-pus hlet-client-json.js复制到WebRoot下的一个lib文件中。
本文对Pushlet框架的一些不足做了改进。但是Pushlet的实现方式使服务器必须维护很多连接,因此对服务器性能要求很高。对此服务器可以选择经过性能改进的Jetty服务器。Pushlet这种长连接的推技术仅适合用于中小型的应用。本文中的投票Web应用也是基于一定群体用户的投票行为。
[1]Alex Russell.Comet: low latency data for the browser[EB/OL].[2006-06].http://alex.dojotoolkit.org/?p=545.
[2]孙清国,朱玮,刘华军,等.Web应用中的服务器推送技术研究综述[J].计算机系统应用,2008(11):116-120.
[3]陈航,赵方.基于服务器推送技术和XMPP的Web IM系统实现[J].计算机工程与设计,2010,31(5):925-928.
[4]BROECKE J V D.Pushlets-protocol specification[EB/OL].[2006-05-25].http://www.pushlets.com/doc/protocol-all.html.
[5]yxw246.Pushlet 2.0.3源码分析 (服务器端)[EB/OL].[2008-05-08].http://blog.csdn.net/yxw246/article/details/2418255.
[6]张涛,黄强,毛磊雅,等.一个基于 JSON的对象序列化算法[J].计算机工程与应用,2007,43(15):98-100.