当前位置: 首页 > news >正文

B/S架构中的数据推送技术

B/S架构中服务器向浏览器推送数据在很多场合都有需求,比如实时的监控报警、实时的调度,等等。凡是对实时性要求越高的场景,越是需要服务器及时、准确地向浏览器推送数据。这里我们就讨论一下在B/S架构下,可以实现从服务器向浏览器推送数据的几种技术及其相应的特点。

基于HTTP协议

1. HTTP协议的特点

纯的HTTP协议在本质上是无状态、无连接的,它基于请求/响应的工作模式,使得浏览器在每次发生请求的时候和服务器建立连接,当接收到响应的时候断开连接;在这种情况下,要让服务器主动向浏览器发送数据是不可能的。

技术总是为需求服务的,在很多浏览器需要及时获取服务器数据更新的需要下,技术人员们变通地发明了一些基于HTTP协议的“伪”长连接技术,实现了服务器数据向浏览器的“准”推送。

2. 定时刷新

定时刷新是最粗糙的实现快速感知服务器数据变化的方法,原理就是不停地刷新页面从而显示最新的服务器端数据。定时刷新从技术上大体有两种实现方法:一是通过HTML的META标签设置页面刷新间隔,比如以下的标签会在浏览器中每隔10秒刷新当前页面:


这种方式会看到页面有明显的刷新,用户体验会比较差;与此相对应的另外一种方式就是AJAX,在JavaScript脚本中添加一个定时器,每隔一定时间向服务器发送一个AJAX请求,得到响应以后去更新页面的内容。以下JavaScript代码会每隔10秒发送一个AJAX请求去更新当前页面的部分内容:
setInterval(function(){sendAJAXRequest()},10000);

如图 1是定时刷新的模型图:

图 1 定时刷新的模型图


定时刷新这种模式相当于一个下级每隔一段时间打电话给上级,请示当前指示。当然,如果在这个时间段内发生了一些情况,他们之间是没办法沟通的,所以信息并不是“实时”的;另外,刷新间隔到底设置多少合适也是个问题,服务器的负担也比较大。

3. 轮询
轮询也是通过AJAX进行的,它与AJAX定时刷新的区别仅在于接收到AJAX响应以后的工作。定时刷新完全是浏览器主动的,在浏览器和服务器之间存在一定的断开间隔;而轮询这种方式会在AJAX响应中再次发送AJAX请求,也就是说当响应结束,浏览器和服务器之间一旦断开连接的时候,浏览器会再次发送请求建立连接。

如图 2是轮询的模型图:

图 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流模式的模型图:

图 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工作原理

如图 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();
}

图 7 发布/订阅模式的数据推送


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/毒蛇" );
}

图 8 点对点模式的数据推送


7. 实时监控Demo

这里通过消息模式实现了一个实时监控的演示。服务器端是使用.Net Stomp API写的控制台程序,Demo测试使用1000个监控目标,数据发送间隔0.5秒,数据推送到“realmonitor”频道。浏览器端使用Flex,监听“realmonitor”频道。

在服务器端,这个Demo中设置每100个目标信息拼装成一条消息,也就是说每0.5秒会发送10条消息。如果每条消息的信息(坐标和一些属性信息)大约50字节的话,每条消息大概5KB;每秒发送两次,总共大概100KB数据量会被推送。

图 9 Flex中实时监控效果


如图 9是在Flex中实现的实时监控效果。

相关文章:

  • C# split字符串 根据1个或多个空格
  • 基于PHP的Flex Socket安全策略设置
  • Windows Azure系列-- Azure Table的CRUD操作
  • [IE编程] 如何获得IE版本号
  • Windows Azure 系列-- Azure Queue的操作
  • Build the Hack CPU with Verilog
  • 使用Service Bus Topic 实现简单的聊天室
  • 使用Service Bus + SignalR 实现聊天室
  • 中移动OMS系统展望..
  • Asp.net MVC4 + signalR 聊天室实现
  • JSF的国际化
  • javascript 替换浏览器Tab的title实现消息通知提示
  • 很好很强大 中移动OMS开源操作系统使用感想
  • [Windows编程] 获取系统CPU 个数
  • 算法练习之DP 求LCM (最长公共子序列)
  • “大数据应用场景”之隔壁老王(连载四)
  • ECMAScript入门(七)--Module语法
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • java多线程
  • java取消线程实例
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • win10下安装mysql5.7
  • 从tcpdump抓包看TCP/IP协议
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • ------- 计算机网络基础
  • 解析带emoji和链接的聊天系统消息
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 模型微调
  • 前端相关框架总和
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • puppet连载22:define用法
  • Spring第一个helloWorld
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​虚拟化系列介绍(十)
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • (16)Reactor的测试——响应式Spring的道法术器
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (30)数组元素和与数字和的绝对差
  • (31)对象的克隆
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (补)B+树一些思想
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • *2 echo、printf、mkdir命令的应用
  • .net FrameWork简介,数组,枚举
  • .NET MVC之AOP
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • /usr/bin/env: node: No such file or directory
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @ConditionalOnProperty注解使用说明
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [C#]使用PaddleInference图片旋转四种角度检测