现在的位置: 首页 > 综合 > 正文

消息推送(Server Push)

2013年10月05日 ⁄ 综合 ⁄ 共 4844字 ⁄ 字号 评论关闭

关键字:Server Push、Comet (web技术)、DWR+Spring实现Comet、web即时消息

1、服务器推送(Server Push)
在监控系统:后台硬件热插拔、LED、温度、电压发生变化; 即时通信系统:其它用户登录、发送信息; 即时报价系统:后台数据库内容发生变化; 此类应用需要服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求。
“服务器推送”技术在现实应用中有一些解决方案,本文将这些解决方案分为两类:一类需要在浏览器端安装插件,基于套接口传送信息,或是使用 RMI、CORBA 进行远程调用;而另一类则无须浏览器安装任何插件、基于 HTTP 长连接。
将“服务器推”应用在 Web 程序中,首先考虑的是如何在功能有限的浏览器端接收、处理信息:客户端如何接收、处理信息,是否需要使用套接口或是使用远程调用。客户端呈现给用户的是 HTML 页面还是 Java applet 或 Flash 窗口。如果使用套接口和远程调用,怎么和 JavaScript 结合修改 HTML 的显示。 客户与服务器端通信的信息格式,采取怎样的出错处理机制。 客户端是否需要支持不同类型的浏览器如 IE、Firefox,是否需要同时支持 Windows 和 Linux 平台。

推送技术的基础思想是将浏览器主动查询信息改为服务器主动发送信息。服务器发送一批数据,浏览器显示这些数据,同时保证与服务器的连接。当服务器需要再次发送一批数据时,浏览器显示数据并保持连接。以后,服务器仍然可以发送批量数据,浏览器继续显示数据,依次类推。

2、客户端拖拽(Client Pull)
在客户端拖曳技术中,服务器发送一批数据,在HTTP响应或文档头标记中插入指令,让浏览器“在5秒内再次装入这些数据”等。当指定的时间达到时,客户端就按照服务器的指示去做,或者刷新当前数据,或者调入新的数据。

客户端拖曳简单实现:
客户端拖曳的一个简单用法是使文档按固定周期自动重载。
<META HTTP-RQUIV=”Refresh” CONTENT=12>
那么它等效于:
Refresh:12

关于怎么使客户端自动申请其他URL的数据话,请使用如下:
<META HTTP-EQUIV=”Refresh” CONTENT=”12;URL=http://icools.yeah.net/”>
注意的是,此处的URL不能使用相对路径,必须全部指定。
其中时间间隔可以设置为0,这样浏览器在当前文档显示完毕后,以最快的速度载入新的数据!

3、技术差异
push和pull 这两种技术手段非常不同,但目的都是为了给最终用户方便的提供最新信息。

在服务器推送技术中,HTTP 连接一直保持着,直到服务器知道自己已结束发送数据并发送一个结束信号,或者客户端中断连接。
客户端拖曳技术中,并不保持HTTP连接,相反客户端被告知合时建立新连接,以及建立连接是获取什么数据。

在服务器推送中,奇妙之处在于“multipart/mixed”格式的MIME,它能够使一个报文(或HTTP响应)包含许多数据项。
客户端拖曳中,奇妙之处在于HTTP响应头标(或等效的HTML元素),它能告知客户端在指定的延时时间后执行何种动作。

在服务器推送通常效率要比客户端拖曳效率高,因为它不必为后续数据建立新的连接。由于始终保持连接,即使没有数据传输时也是这样,因此服务器必须愿意分配这些TCP/IP端口对于TCP/IP端口数有限的服务器这将是一个严重的问题。
客户端拖曳效率低,因为这必须每次为传送数据建立新的连接。但是它不必始终保持连接。实际情况中,建立HTTP连接通常需要花费相当多的时间,多达一秒甚至更多。因此从性能上考虑,服务器推送对于最终用户更有吸引力,特别是对于需要经常更新信息的情况下。

在服务器推送中相对比较容易控制。服务器每一次推送时都保持一个连接,但它又随时可以关闭其中的任何连接,而不需要在服务器上设置特殊的算法
客户端拖曳在同样的情况下要麻烦许多,它每次要与服务器建立连接,服务器为了处理将客户端拖曳请求与特定的最终用户匹配等情况,需要使用相当麻烦的算法。

如果实现服务器推送的CGI程序是使用Shell脚本语言编写的,有时会存在一些问题。例如,客户端最终用户中断连接,Shell程序通常不能注意到,这将使资源毫无用处的浪费掉,解决这一问题的办法是用Perl或者C来编写这类CGI程序,以使用户中断连接时能够结束运行。

如上所述,在服务器推送中,多个响应中连接始终保持,使服务器可在任何时间发送更多的数据。一个明显的好处是服务器完全能够控制更新数据的时间和频率。另外,这种方法效率高,因为始终保持连接。缺点是保持连接状态会浪费服务器端的资源。服务器推送还比较容易中断。

4、服务器端推送的实现

接下来就大概说说服务器推送技术
服务器在响应请求时,HTTP使用MIME报文格式来封装数据。通常一个HTTP响应只能包含一个数据块。但MIME有一种机制可用一个报文(或HTTP 响应)表示将多个数据块,这种机制就是成为“multipart/mixed”的标准MIME类型。
对于服务器推送,使用一个“multipart/mixed”类型的变种–multipart/x-mixed-replace。这里,“x-”表示属于实验类型。“replace”表示每一个新数据块都会代替前一个数据块。也就是说,新数据不是附加到旧数据之后,而是替代它。

下面是实际使用的“multipart/x-mixed-replace”类型:
Content-type:multipart/x-mixed-replace;boundary=ThisRandomString
–ThisRandomString
Content-type:text/plain
第一个对象的数据
–ThisRandomString
Content-type:text/plain
第二个(最后一个)对象的数据。
–ThisRandomString–
使用这一技术的关键是,服务器并不是推送整个“multipart/x-mixed-replace”报文,而是每次发送后数据块。

HTTP连接始终保持,因而服务器可以按自己需要的速度和频率推送新数据,两个数据块之间浏览器仅需在当前窗口等候,用户甚至可以到其他窗口做别的事情,当服务器需要发送新数据时,它只是源传输管道发送数据块,客户端相应的窗口进行自我更新。

在服务器推送技术中,“multipart/x-mixed-replace”类型的报文由唯一的边界线组成,这些边界线分割每个数据块。每个数据块都有自己的头标,因而能够指定对象相关的内容类型和其他信息。由于“multipart/x-mixed-replace”的特性是每一新数据块取代前一数据对象,因而浏览器中总是显示最新的数据对象。
“multipart/x-mixed-replace”报文没有结尾。也就是说,服务器可以永远保持连接,并发送所需的数据。如果用户不再在浏览器窗口中显示数据流,或者浏览器到服务器间的连接中间(例如用户按“STOP”按钮),服务器的推送才会中断(人们使用服务器推送的典型方式)。

当浏览器发现“Content-type”头标或到达头标结束处时,浏览器窗口中的前一个文档被清除,并开始显示下一个文档。发现下一个报文边界时,就认为当前数据块(文档)已经结束。总之,服务器推送的数据由一组头标(通常包括“Content-type”)、数据本身和分割符(报文边界)三部分组成。浏览器看到分割符时,它保持状态不变,直到下一个数据块到达。

NCSA HTTPD用户在内容类型中不能使用空格,包括边界参数。NCSA HTTPD只能将不带空格字符的字符串作为内容类型。如果在内容类型行中存在空格(冒号后面的空格除外),空格后的任何文本都会被删除。
下面的示例是正确的:
Content-type: multipart/x-mixed-replace;boundary=ThisRandomString
而下例则不能正常工作,因为它在中间有空格:
Content-type: multipart/x-mixed-replace; boundary=ThisRandomString
服务器推送的另一个优点是它可以针对单个内联图象进行。包括图象的文档可以由服务器定时或定周期进行更新。而实现这一点非常简单:只需使IMG元素的SRC属性指向推送一系列图象的URL即可。

如果服务器推送用于单个内联图象,文档中的图象就会一次次被新推送来的图象所代替,而文档本身不需变化(假设文档没有进行服务器推送)。这样,WEB页面中有限的动画就可以为静态画面所代替。

5、Server Push使用环境
Server Push。一般和Ajax结合。用来做模拟Real-Time的网站。
实现方式有多种,可以用Java Applet, Flash或者Siverlight, JavaFX, FLEX都有内置的API。但是这些方法都需要客户端有Flash等插件,所以最好的方法还是用Long Polling的方式。

目前来看,校内网,Facebook的聊天,还有Google GMail的聊天都是用Push的。但大部分客服聊天用的是Poll的方式,比如美国最大的股票上市客服公司LivePerson。

目前据我所知,Servlet 2.5标准没有规定Server Push,即Asynchronous的API。所以各个不同的Java EE服务器都有自己的不同标准。

1. Tomcat servlet container中,用CometEvent的class来实现,而且一个Servlet class必须首先implement CometProcessor这个interface。
例子和讲解,是Apache官方的!http://tomcat.apache.org/tomcat-6.0-doc/aio.html

2. Resin服务器,也就是校内网用的服务器。大概是用com.caucho.servlet.cometCometController来实现。

http://www.caucho.com/resin/doc/resin-comet.xtp是官方的教程

3. WebSphere,也就是IBM的application server,是价格最贵的。可以用WebSphere Application Server Feature Pack for Web 2.0。
中文教程:http://www.ibm.com/developerworks/cn/web/wa-lo-w2fpak-comet/

4.甲骨文的WebLogic好像也有,不过没找到教程。

5、开源而又能和各种服务器良好兼容,那就是Pushlet。感觉他们源代码写的水平有限,当然是和Apache的源代码相比。
教程http://www.pushlets.com/。

在未来Servlet 3.0 API标准中,规定了Asynchronous Event,也就是对Server Push的支持。

http://jcp.org/aboutJava/communityprocess/edr/jsr315/index.html

目前我只知道未来的Tomcat 7一定会遵循Servlet 3.0标准。

文章

http://baike.baidu.com/view/2668625.htm

http://hi.baidu.com/zhenyk/blog/item/02a9d21f652d2765f724e47e.html

Tools

http://en.wikipedia.org/wiki/Comet_(programming)

http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

工具

http://cometdproject.dojotoolkit.org/

http://groups.google.com/group/cometd-dev/

抱歉!评论已关闭.