基于HTTP协议
1. HTTP协议的特点
纯的HTTP协议在本质上是无状态、无连接的,它基于请求/响应的工作模式,使得浏览器在每次发生请求的时候和服务器建立连接,当接收到响应的时候断开连接;在这种情况下,要让服务器主动向浏览器发送数据是不可能的。
技术总是为需求服务的,在很多浏览器需要及时获取服务器数据更新的需要下,技术人员们变通地发明了一些基于HTTP协议的“伪”长连接技术,实现了服务器数据向浏览器的“准”推送。
2. 定时刷新
定时刷新是最粗糙的实现快速感知服务器数据变化的方法,原理就是不停地刷新页面从而显示最新的服务器端数据。定时刷新从技术上大体有两种实现方法:一是通过HTML的META标签设置页面刷新间隔,比如以下的标签会在浏览器中每隔10秒刷新当前页面:
<meta equiv="refresh" content="10" />
这种方式会看到页面有明显的刷新,用户体验会比较差;与此相对应的另外一种方式就是AJAX,在JavaScript脚本中添加一个定时器,每隔一定时间向服务器发送一个AJAX请求,得到响应以后去更新页面的内容。以下JavaScript代码会每隔10秒发送一个AJAX请求去更新当前页面的部分内容:
setInterval(function(){sendAJAXRequest()},10000);
如图 1是定时刷新的模型图:
定时刷新这种模式相当于一个下级每隔一段时间打电话给上级,请示当前指示。当然,如果在这个时间段内发生了一些情况,他们之间是没办法沟通的,所以信息并不是“实时”的;另外,刷新间隔到底设置多少合适也是个问题,服务器的负担也比较大。
3. 轮询
轮询也是通过AJAX进行的,它与AJAX定时刷新的区别仅在于接收到AJAX响应以后的工作。定时刷新完全是浏览器主动的,在浏览器和服务器之间存在一定的断开间隔;而轮询这种方式会在AJAX响应中再次发送AJAX请求,也就是说当响应结束,浏览器和服务器之间一旦断开连接的时候,浏览器会再次发送请求建立连接。
如图 2是轮询的模型图:
轮询这种模式相当于一个下级不停给上级打电话请示,上级指示下达以后挂了电话,下级可能去执行指示或者不执行,但是随即下级将再次给上级打电话继续请示。这种模式可以保证数据更新比较实时,但是服务器负担也是一个问题。
顺便提一下,轮询这种模式一般会在浏览器的XMLHttpRequest的readyState为4(响应数据传输结束)的时候调用回调函数,此时连接已经关闭;但是在Firefox中支持Streaming AJAX模式,也就是XMLHttpRequest的readyState为3(响应数据仍在传输)的时候调用回调函数,此时连接尚未关闭。
4. 基于iframe的流模式
iframe可以在当前页面中嵌入一个文档页面,如果把这个页面设为隐藏,并将其src属性设置为一个特殊的请求,数据将会源源不断地从服务器发送到浏览器。
比如以下的JSP页面,它将每隔10秒更新一个数输出到浏览器,不出意外它将会永远执行下去,浏览器和服务器之间的连接也永远不会关闭:
<% int i = 1; try { while (true) { out.print("
"+(i++)+"
");out.flush();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {}
}
} catch (Exception e) {}
%>
但是这样做有个很显然的不足,由于响应始终没有结束,因此浏览器里面的加载进度条会始终显示加载没有完成。当然,这也并不是没有办法解决,比如http://www.zeitoun.net/articles/comet_and_php/start就提供了IE、Opera、WebKit核心(Chrome/Safari)、Gecko核心(Firefox)等浏览器的解决方案。
如图 3是基于iframe流模式的模型图:
基于iframe的流模式相当于一个下级给上级打电话,上级不停发出指示,下级一边接收指示、一边执行。这种模式有着比较好的实时性,比如Gmail就是采用这种模式。
5. 开源框架Pushlets
Pushlets是一个实现了AJAX轮询和iframe流模式的开源框架(Java+JavaScript),对此有兴趣的可以参考:http://www.pushlets.com/,Pushlets采用LGPL许可。
基于消息
1. 基于消息的架构
使用消息可以实现松散耦合的分布式数据通讯。通过消息从服务器向浏览器推送数据一般需要一个消息中间件(Message Oriented Middleware,MOM),服务器将数据推送给消息中间件,消息中间件再将数据以消息的方式推送给浏览器。基于消息的架构有个特别大的优点,那就是不但可以实现服务器向单浏览器、服务器向多浏览器推送数据;还支持浏览器到浏览器之间的数据推送。这将会在预警、调度等场合有非常大的用武之地。
图 4和图 5分别是基于订阅/发布模式和点到点模式的消息传递示意。在B/S架构中,服务器可以发布消息,所有订阅该主题的浏览器都会接受到该消息,这就实现了从服务器向多浏览器的数据推送;浏览器或者服务器也可以向特定的对象发送消息,消息将在一个消息队列中被发送,对方浏览器就可以收到该消息,这就实现了服务器向某特定浏览器或者浏览器之间的数据推送。
2. Java消息服务(JMS)
JMS是一组公开的Java API,它定义了与消息相关的接口和语义,目前JMS已经成为J2EE中的重要组成部分。
如图 6是JMS工作原理。当有客户端连接到JMS服务器的时候,JMS的连接工厂会根据连接类型来创建一个虚拟连接,这个连接会具体负责消息的传递;在这个连接建立完成后,会产生一个会话,会话中保存了消息生产者或消息消费者的信息;消息的消费者会对感兴趣的消息目的地(队列或主题)建立一个监听,消息的生产者则负责把消息发送到这个目的地上。
另外JMS还有一些值得一提的特点,比如支持事务性会话、可以设置消息的持久性、设置消息的优先级、允许消息过期、可以构建长期订阅等。这些特性在各种企业级应用环境下都有可能提高应用的功能或性能。
实现JMS的商业中间件有IBM MQSeries、BEA WebLogic JMS等;开源中间件有OpenJMS、Apache ActiveMQ等。
3. ActiveMQ
ActiveMQ是Apache基金会的著名开源项目,目前Release版本5.2完整支持JMS1.1和J2EE 1.4规范。ActiveMQ采用Apache 2.0许可发布。ActiveMQ的优势在于其支持集群部署、支持多种应用层协议和诸多客户端开发语言等特点。
ActiveMQ主要支持以下协议:
OpenWire
REST
Stomp
WS Notification
XMPP
AMQP
下面这里将使用ActiveMQ和Stomp协议来演示各种方式的数据的推送。
4. Stomp协议
Stomp是一种简单、实现容易的协议,因此支持非常广泛,这里采用Stomp协议的主要原因也是因为其支持的客户端开发语言最多,在各种环境下都有用武之地。这些开发语言主要包括:
ActionScript 3
C
C++
.Net
Delphi
Perl
PHP
Python
Ruby
下面主要用到了ActionScript和.Net语言。
5. 发布/订阅模式的实现
发布/订阅模式适用于广播性质的数据推送。比如在实时监控系统中,当我们的指令中心需要向所有监控目标发送信息的时候,这种模式就比较适合。为了简单起见,这里的服务器端和浏览器端都使用了ActionScript实现。
在浏览器端,我们需要订阅服务器主题。比如所有的接收指令的目标都需要监听“Alarm”频道,那么在浏览器中的代码应该如下:
private function sub():void
{
var ch:ConnectHeaders = new ConnectHeaders();
stomp.connect("localhost", 61613, ch);
stomp.subscribe( "/topic/Alarm" );
}
private function onStompMessage(event:MessageEvent):void
{
var byteArray:ByteArray = event.message.body;
var str:String = byteArray.toString();
}
6. 点对点模式的实现
点对点模式适合类似调度的功能场景。比如在监控系统中,当某个指令需要下达给具体某个目标的时候,就需要点对点模式的数据推送。
实现点对点模式的数据推送需要知道数据发送的目的地,以下代码演示了如何从指令中心“党中央”发送指令到“毒蛇”的过程:
private function sendMsg():void
{
var destination:String = "/queue/毒蛇";
stomp.sendTextMessage(destination, “注意隐蔽”);
}
当然,“毒蛇”需要监听所有发送给他的消息:
private function login():void
{
var ch:ConnectHeaders = new ConnectHeaders();
stomp.connect("localhost", 61613, ch);
stomp.subscribe( "/queue/毒蛇" );
}
7. 实时监控Demo
这里通过消息模式实现了一个实时监控的演示。服务器端是使用.Net Stomp API写的控制台程序,Demo测试使用1000个监控目标,数据发送间隔0.5秒,数据推送到“realmonitor”频道。浏览器端使用Flex,监听“realmonitor”频道。
在服务器端,这个Demo中设置每100个目标信息拼装成一条消息,也就是说每0.5秒会发送10条消息。如果每条消息的信息(坐标和一些属性信息)大约50字节的话,每条消息大概5KB;每秒发送两次,总共大概100KB数据量会被推送。
如图 9是在Flex中实现的实时监控效果。
2 条评论:
总结的太好了,学习ing
谢谢啊,受益匪浅噢
发表评论