Flex Blazeds推送机制

前言:
对于数据实时性页面呈现非常强的业务,通过前台定时刷新这样的效率明显不行。下面通过flex技术来实现这个功能。
思路:
以告警数据为例,告警数据通过mq、socket等方式进入系统,在java服务器通过监听来监听消息队列数据,接收后推送到flex各个客户端。blazeDS采用amf协议。该协议可以传输Object, Array, Date, XML。由于AMF采用二进制编码,这种方式可以高度压缩数据,因此非常适合用来传递大量的资料。数据量越大,Flash Remoting的传输效能就越高,远远超过Web Service。至于XML, LoadVars和loadVariables() ,它们使用纯文本的传输方式,效能就更不能与Flash Remoting相提并论了

本例mq使用activeMq测试,推动到flex的方式采用adobe提供的java flex通信包blazeDS中提供的推送功能,

具体步骤:
一. 创建一个java flex使用blazeDS通信的工程,具体步骤在此不详细说明搭建的步骤。
搭建成功后导入activemq-all-5.1.0.jar,为后面接收activemq消息使用。
二. 配置:
在remoting-config.xml加入推送服务。
<destination id="serverpushserver">
<properties>
<source>
com.east.flex.serverpush.chart.ServerPushServer
</source>
</properties>
</destination>
1.服务发布 Java代码:ServerPushServer.Java
Java代码  复制代码  收藏代码
  1. package com.east.flex.serverpush.chart;   
  2.   
  3.   
  4. public class ServerPushServer {    
  5.     //ServerPushThread serverpushthread = new  ServerPushThread();   
  6.     MessageBrokFactory messageBrokFactory;   
  7.     public void controlThread(String str){   
  8.         if(str.equals("start")){   
  9.             try{   
  10.                 messageBrokFactory=new MessageBrokFactory();   
  11.                 messageBrokFactory.start();   
  12.             }catch (Exception e){   
  13.                  e.printStackTrace();   
  14.             }   
  15.                
  16.         //serverpushthread.start();   
  17.         }else{   
  18.             messageBrokFactory.stop();   
  19.             //serverpushthread.stop();   
  20.         }   
  21.     }   
  22. }  


2.消息处理事务: messageBrokFactory
具有功能:启动mq,并监听mq接收消息,消息推送到flex.三大功能。

Java代码  复制代码  收藏代码
  1. package com.east.flex.serverpush.chart;   
  2.   
  3. import javax.jms.JMSException;   
  4.   
  5. import javax.jms.Message;   
  6. import javax.jms.MessageListener;   
  7. import javax.jms.TextMessage;   
  8. import javax.naming.NamingException;   
  9.   
  10. import org.apache.log4j.Logger;   
  11.   
  12. import com.zznode.gixpert.provider.activemq.service.impl.ActiveMQAdapter;   
  13.   
  14. import flex.messaging.MessageBroker;   
  15. import flex.messaging.messages.AsyncMessage;   
  16. import flex.messaging.util.UUIDUtils;   
  17.   
  18.   
  19.   
  20. public class MessageBrokFactory {   
  21.       
  22.     private MessageBroker msgBroker;   
  23.       
  24.     private String clientId ;   
  25.        
  26.       
  27.       
  28.     private  static int port=61616;   
  29.       
  30.     private static String hostname = "localhost";   
  31.       
  32.     private  static String user = "";   
  33.       
  34.     private  static String password= "";   
  35.       
  36.     private String queuename="sendToFlex";   
  37.       
  38.     ActiveMQAdapter amqAdapter;   
  39.       
  40.     private static boolean  pattern;   
  41.       
  42.     private  static String durable="是";   
  43.       
  44.     private  static String sleepTime="否";   
  45.       
  46.     private  static String receiveTimeOut="否";   
  47.       
  48.        
  49.     private Logger logger = Logger.getLogger(ActiveMQAdapter.class);   
  50.   
  51.     public boolean sedMessage(String sub,Object message) {   
  52.         try{   
  53.             AsyncMessage msg = new AsyncMessage();   
  54.             msg.setDestination("serverpush");   
  55.             msg.setClientId(clientId);   
  56.             msg.setMessageId(UUIDUtils.createUUID());   
  57.             msg.setTimestamp(System.currentTimeMillis());   
  58.               
  59.             msg.setBody(message);   
  60.             msgBroker.routeMessageToService(msg, null);   
  61.             return true;   
  62.         }catch(Exception e){   
  63.             e.printStackTrace();   
  64.             return true;   
  65.         }   
  66.            
  67.     }   
  68.       
  69.     public void start(){   
  70.         try {   
  71.             //初始化flex消息组建   
  72.             msgBroker = MessageBroker.getMessageBroker(null);   
  73.             clientId = UUIDUtils.createUUID();   
  74.             //启动mq消息接收   
  75.             amqAdapter = new ActiveMQAdapter();   
  76.             //版本1.0只需要对hostname  port 起作用 有更高需求再另添加   
  77.             amqAdapter.setUrl("failover:(tcp://"+hostname+":"+port+"?wireFormat.maxInactivityDuration=0)");   
  78.            
  79.             amqAdapter.addMessageListener(queuename, pattern, new MyTestMessageListener());   
  80.         } catch (JMSException e) {   
  81.             String msg = "Cannot start AlarmCollectQueue.";   
  82.             logger.error(msg, e);   
  83.             System.out.println("set config ex"+e);   
  84.             e.printStackTrace();   
  85.         } catch (NamingException e) {   
  86.             String msg = "Naming context error.";   
  87.             logger.error(msg, e);   
  88.             System.out.println("set config ex"+e);   
  89.             e.printStackTrace();   
  90.         }   
  91.     }   
  92.       
  93.     public void stop() {   
  94.         amqAdapter.close();   
  95.     }   
  96.       
  97.     class MyTestMessageListener implements MessageListener {   
  98.            
  99.         public void onMessage(Message msg) {   
  100.             try{   
  101.                 //   
  102.                 String message=((TextMessage)msg).getText();   
  103.                 logger.info("recieve a message from: "+msg.getJMSDestination()+"  " +   
  104.                         "message text: "+message);   
  105.                 sedMessage("test",message);   
  106.             }catch(Exception e){   
  107.                 e.printStackTrace();   
  108.                 System.out.println("set config ex"+e);   
  109.             }   
  110.         }   
  111.     }   
  112.   
  113. }  

2.ActiveMq接收消息的代码见附件工程。在此不列出。
Flex端:本例以一个textarea文本来显示数据。告警数据具体可以使用datagrid

展现代码getMessageClient.mxml
Flex代码  复制代码  收藏代码
  1. <DIV class=quote_title>引用</DIV><DIV class=quote_div><PRE class=java name="code"><PRE class=java name="code"><PRE class=java name="code"><?xml version="1.0" encoding="utf-8"?>   
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">   
  3.      <mx:Script>   
  4.         <![CDATA[   
  5.             import com.east.flex.entity.Product;   
  6.         import mx.messaging.messages.IMessage;   
  7.         import mx.messaging.events.MessageEvent;   
  8.         import mx.utils.ArrayUtil;   
  9.         import mx.rpc.events.ResultEvent;   
  10.         import mx.collections.ArrayCollection;   
  11.         import mx.controls.Alert;   
  12.         import mx.messaging.ChannelSet;   
  13.         import mx.messaging.Consumer;   
  14.   
  15.         [Bindable]   
  16.         private var p:Product;   
  17.            
  18.         private var array:ArrayUtil;   
  19.            
  20.         [Bindable]   
  21.         private var expensesAC:ArrayCollection = null;   
  22.                
  23.         public var consumer2:Consumer = null;   
  24.               
  25.         public function messageHandler(event:MessageEvent):void   
  26.         {   
  27.             textArea.text =  event.message.body+textArea.text;   
  28.             trace("server push data to client..............");   
  29.         }   
  30.            
  31.            
  32.         public function remoteServerCallback(event:ResultEvent):void   
  33.         {   
  34.             trace("Server is start....");   
  35.             //Alert.show("Server is start....."+event.message);   
  36.         }   
  37.            
  38.         public function startServer(event:MouseEvent):void   
  39.         {   
  40. //          server.start();   
  41.             server.controlThread("start");   
  42.         }   
  43.            
  44.         public function stopServer(event:MouseEvent):void   
  45.         {   
  46. //          server.stop();   
  47.             server.controlThread("stop");   
  48.         }   
  49.         ]]>   
  50.     </mx:Script>   
  51.        
  52.     <mx:Consumer id="consumer" destination="serverpush" message="messageHandler(event)"/>   
  53.        
  54.     <mx:RemoteObject id="server" destination="serverpushserver"  result="remoteServerCallback(event)"/>   
  55.        
  56.     <!-- Define custom colors for use as fills in the AreaChart control. -->   
  57.     <mx:SolidColor id="sc1" color="blue" alpha=".3"/>   
  58.     <mx:SolidColor id="sc2" color="red" alpha=".3"/>   
  59.     <mx:SolidColor id="sc3" color="green" alpha=".3"/>   
  60.   
  61.     <!-- Define custom Strokes. -->   
  62.     <mx:Stroke id = "s1" color="blue" weight="2"/>   
  63.     <mx:Stroke id = "s2" color="red" weight="2"/>   
  64.     <mx:Stroke id = "s3" color="green" weight="2"/>   
  65.   
  66.     <mx:Panel title="LineChart and AreaChart Controls Example"    
  67.         height="100%" width="100%" layout="absolute">   
  68.   
  69.             <mx:TextArea id="textArea" width="1017" height="565">   
  70.                    
  71.             </mx:TextArea>   
  72.   
  73.            
  74.            
  75.         <mx:Button id="autoOk" label="AutoRefresh" x="1038" y="87" width="107" click="consumer.subscribe()" enabled="{!consumer.subscribed}"/>   
  76.         <mx:Button id="cancel" x="1038" y="135" width="107" label="Cancel Auto "  click="consumer.unsubscribe()" enabled="{consumer.subscribed}"/>   
  77.         <mx:Button id="cancel0" x="1038" y="187" width="107" label="Start Server"  click="startServer(event)"/>   
  78.         <mx:Button id="cancel1" x="1038" y="237" width="107" label="Stop Server"  click="stopServer(event)"/>   
  79.     </mx:Panel>   
  80. </mx:Application></PRE></PRE></PRE></DIV>  
引用
Java代码  复制代码  收藏代码
  1. <PRE class=java name="code"><PRE class=java name="code"><?xml version="1.0" encoding="utf-8"?>   
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">   
  3.      <mx:Script>   
  4.         <![CDATA[   
  5.             import com.east.flex.entity.Product;   
  6.         import mx.messaging.messages.IMessage;   
  7.         import mx.messaging.events.MessageEvent;   
  8.         import mx.utils.ArrayUtil;   
  9.         import mx.rpc.events.ResultEvent;   
  10.         import mx.collections.ArrayCollection;   
  11.         import mx.controls.Alert;   
  12.         import mx.messaging.ChannelSet;   
  13.         import mx.messaging.Consumer;   
  14.   
  15.         [Bindable]   
  16.         private var p:Product;   
  17.            
  18.         private var array:ArrayUtil;   
  19.            
  20.         [Bindable]   
  21.         private var expensesAC:ArrayCollection = null;   
  22.                
  23.         public var consumer2:Consumer = null;   
  24.               
  25.         public function messageHandler(event:MessageEvent):void  
  26.         {   
  27.             textArea.text =  event.message.body+textArea.text;   
  28.             trace("server push data to client..............");   
  29.         }   
  30.            
  31.            
  32.         public function remoteServerCallback(event:ResultEvent):void  
  33.         {   
  34.             trace("Server is start....");   
  35.             //Alert.show("Server is start....."+event.message);   
  36.         }   
  37.            
  38.         public function startServer(event:MouseEvent):void  
  39.         {   
  40. //          server.start();   
  41.             server.controlThread("start");   
  42.         }   
  43.            
  44.         public function stopServer(event:MouseEvent):void  
  45.         {   
  46. //          server.stop();   
  47.             server.controlThread("stop");   
  48.         }   
  49.         ]]>   
  50.     </mx:Script>   
  51.        
  52.     <mx:Consumer id="consumer" destination="serverpush" message="messageHandler(event)"/>   
  53.        
  54.     <mx:RemoteObject id="server" destination="serverpushserver"  result="remoteServerCallback(event)"/>   
  55.        
  56.     <!-- Define custom colors for use as fills in the AreaChart control. -->   
  57.     <mx:SolidColor id="sc1" color="blue" alpha=".3"/>   
  58.     <mx:SolidColor id="sc2" color="red" alpha=".3"/>   
  59.     <mx:SolidColor id="sc3" color="green" alpha=".3"/>   
  60.   
  61.     <!-- Define custom Strokes. -->   
  62.     <mx:Stroke id = "s1" color="blue" weight="2"/>   
  63.     <mx:Stroke id = "s2" color="red" weight="2"/>   
  64.     <mx:Stroke id = "s3" color="green" weight="2"/>   
  65.   
  66.     <mx:Panel title="LineChart and AreaChart Controls Example"    
  67.         height="100%" width="100%" layout="absolute">   
  68.   
  69.             <mx:TextArea id="textArea" width="1017" height="565">   
  70.                    
  71.             </mx:TextArea>   
  72.   
  73.            
  74.            
  75.         <mx:Button id="autoOk" label="AutoRefresh" x="1038" y="87" width="107" click="consumer.subscribe()" enabled="{!consumer.subscribed}"/>   
  76.         <mx:Button id="cancel" x="1038" y="135" width="107" label="Cancel Auto "  click="consumer.unsubscribe()" enabled="{consumer.subscribed}"/>   
  77.         <mx:Button id="cancel0" x="1038" y="187" width="107" label="Start Server"  click="startServer(event)"/>   
  78.         <mx:Button id="cancel1" x="1038" y="237" width="107" label="Stop Server"  click="stopServer(event)"/>   
  79.     </mx:Panel>   
  80. </mx:Application></PRE></PRE>  
Java代码  复制代码  收藏代码
  1. <PRE class=java name="code"><?xml version="1.0" encoding="utf-8"?>   
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">   
  3.      <mx:Script>   
  4.         <![CDATA[   
  5.             import com.east.flex.entity.Product;   
  6.         import mx.messaging.messages.IMessage;   
  7.         import mx.messaging.events.MessageEvent;   
  8.         import mx.utils.ArrayUtil;   
  9.         import mx.rpc.events.ResultEvent;   
  10.         import mx.collections.ArrayCollection;   
  11.         import mx.controls.Alert;   
  12.         import mx.messaging.ChannelSet;   
  13.         import mx.messaging.Consumer;   
  14.   
  15.         [Bindable]   
  16.         private var p:Product;   
  17.            
  18.         private var array:ArrayUtil;   
  19.            
  20.         [Bindable]   
  21.         private var expensesAC:ArrayCollection = null;   
  22.                
  23.         public var consumer2:Consumer = null;   
  24.               
  25.         public function messageHandler(event:MessageEvent):void  
  26.         {   
  27.             textArea.text =  event.message.body+textArea.text;   
  28.             trace("server push data to client..............");   
  29.         }   
  30.            
  31.            
  32.         public function remoteServerCallback(event:ResultEvent):void  
  33.         {   
  34.             trace("Server is start....");   
  35.             //Alert.show("Server is start....."+event.message);   
  36.         }   
  37.            
  38.         public function startServer(event:MouseEvent):void  
  39.         {   
  40. //          server.start();   
  41.             server.controlThread("start");   
  42.         }   
  43.            
  44.         public function stopServer(event:MouseEvent):void  
  45.         {   
  46. //          server.stop();   
  47.             server.controlThread("stop");   
  48.         }   
  49.         ]]>   
  50.     </mx:Script>   
  51.        
  52.     <mx:Consumer id="consumer" destination="serverpush" message="messageHandler(event)"/>   
  53.        
  54.     <mx:RemoteObject id="server" destination="serverpushserver"  result="remoteServerCallback(event)"/>   
  55.        
  56.     <!-- Define custom colors for use as fills in the AreaChart control. -->   
  57.     <mx:SolidColor id="sc1" color="blue" alpha=".3"/>   
  58.     <mx:SolidColor id="sc2" color="red" alpha=".3"/>   
  59.     <mx:SolidColor id="sc3" color="green" alpha=".3"/>   
  60.   
  61.     <!-- Define custom Strokes. -->   
  62.     <mx:Stroke id = "s1" color="blue" weight="2"/>   
  63.     <mx:Stroke id = "s2" color="red" weight="2"/>   
  64.     <mx:Stroke id = "s3" color="green" weight="2"/>   
  65.   
  66.     <mx:Panel title="LineChart and AreaChart Controls Example"    
  67.         height="100%" width="100%" layout="absolute">   
  68.   
  69.             <mx:TextArea id="textArea" width="1017" height="565">   
  70.                    
  71.             </mx:TextArea>   
  72.   
  73.            
  74.            
  75.         <mx:Button id="autoOk" label="AutoRefresh" x="1038" y="87" width="107" click="consumer.subscribe()" enabled="{!consumer.subscribed}"/>   
  76.         <mx:Button id="cancel" x="1038" y="135" width="107" label="Cancel Auto "  click="consumer.unsubscribe()" enabled="{consumer.subscribed}"/>   
  77.         <mx:Button id="cancel0" x="1038" y="187" width="107" label="Start Server"  click="startServer(event)"/>   
  78.         <mx:Button id="cancel1" x="1038" y="237" width="107" label="Stop Server"  click="stopServer(event)"/>   
  79.     </mx:Panel>   
  80. </mx:Application></PRE>  
Java代码  复制代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">   
  3.      <mx:Script>   
  4.         <![CDATA[   
  5.             import com.east.flex.entity.Product;   
  6.         import mx.messaging.messages.IMessage;   
  7.         import mx.messaging.events.MessageEvent;   
  8.         import mx.utils.ArrayUtil;   
  9.         import mx.rpc.events.ResultEvent;   
  10.         import mx.collections.ArrayCollection;   
  11.         import mx.controls.Alert;   
  12.         import mx.messaging.ChannelSet;   
  13.         import mx.messaging.Consumer;   
  14.   
  15.         [Bindable]   
  16.         private var p:Product;   
  17.            
  18.         private var array:ArrayUtil;   
  19.            
  20.         [Bindable]   
  21.         private var expensesAC:ArrayCollection = null;   
  22.                
  23.         public var consumer2:Consumer = null;   
  24.               
  25.         public function messageHandler(event:MessageEvent):void  
  26.         {   
  27.             textArea.text =  event.message.body+textArea.text;   
  28.             trace("server push data to client..............");   
  29.         }   
  30.            
  31.            
  32.         public function remoteServerCallback(event:ResultEvent):void  
  33.         {   
  34.             trace("Server is start....");   
  35.             //Alert.show("Server is start....."+event.message);   
  36.         }   
  37.            
  38.         public function startServer(event:MouseEvent):void  
  39.         {   
  40. //          server.start();   
  41.             server.controlThread("start");   
  42.         }   
  43.            
  44.         public function stopServer(event:MouseEvent):void  
  45.         {   
  46. //          server.stop();   
  47.             server.controlThread("stop");   
  48.         }   
  49.         ]]>   
  50.     </mx:Script>   
  51.        
  52.     <mx:Consumer id="consumer" destination="serverpush" message="messageHandler(event)"/>   
  53.        
  54.     <mx:RemoteObject id="server" destination="serverpushserver"  result="remoteServerCallback(event)"/>   
  55.        
  56.     <!-- Define custom colors for use as fills in the AreaChart control. -->   
  57.     <mx:SolidColor id="sc1" color="blue" alpha=".3"/>   
  58.     <mx:SolidColor id="sc2" color="red" alpha=".3"/>   
  59.     <mx:SolidColor id="sc3" color="green" alpha=".3"/>   
  60.   
  61.     <!-- Define custom Strokes. -->   
  62.     <mx:Stroke id = "s1" color="blue" weight="2"/>   
  63.     <mx:Stroke id = "s2" color="red" weight="2"/>   
  64.     <mx:Stroke id = "s3" color="green" weight="2"/>   
  65.   
  66.     <mx:Panel title="LineChart and AreaChart Controls Example"    
  67.         height="100%" width="100%" layout="absolute">   
  68.   
  69.             <mx:TextArea id="textArea" width="1017" height="565">   
  70.                    
  71.             </mx:TextArea>   
  72.   
  73.            
  74.            
  75.         <mx:Button id="autoOk" label="AutoRefresh" x="1038" y="87" width="107" click="consumer.subscribe()" enabled="{!consumer.subscribed}"/>   
  76.         <mx:Button id="cancel" x="1038" y="135" width="107" label="Cancel Auto "  click="consumer.unsubscribe()" enabled="{consumer.subscribed}"/>   
  77.         <mx:Button id="cancel0" x="1038" y="187" width="107" label="Start Server"  click="startServer(event)"/>   
  78.         <mx:Button id="cancel1" x="1038" y="237" width="107" label="Stop Server"  click="stopServer(event)"/>   
  79.     </mx:Panel>   
  80. </mx:Application>  

使用操作:

在第一次打开的页面点击startserver.这个共是启动监听,注意只需要在第一次打开点击了就行,其他打开的页面不需要。再次点击
然后点击autorefesh,用来启动自动显示数据,注意autorefesh这不是自动刷新请求数据。是推动上来的数据。
其他打开的页面都只要点击autorefesh即可。

启动一个acitmvemq在提供的页面发送数据,可以一次发送几千条数据。同事打开几个页面来测试下下过。


[color=red]优化:[/color]
项目最近开始运行发现客户端web非常耗费cpu,非常头疼,当然这与我的数据量肯定是有关系的,我后台推送到前台的数据大约每秒100条。消息量少时streaming没有问题。
后来经过了多种情况的测试,最后发现把streaming设置为polling方式轮询推送占用的cpu资源一下子降了下来。后来吧轮询时间这只为0.3s效果比streaming还好。streaming方式是,消息上来的太快,表格显示时非常闪眼睛,用户没法操作,相反设为polling后这种现象降低了。
总结steaming耗费cpu大的原因是,flex执行死循环时比java执行死循环耗资源打多了。也就是对于一直占用cpu不释放。steaming方式消息量大了也跟执行死循环一样,一直在执行不释放cpu.
下面是改造后的配置
Java代码  复制代码  收藏代码
  1. <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">   
  2.            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>   
  3.            <properties>   
  4.                <polling-enabled>true</polling-enabled>   
  5.                <polling-interval-seconds>0.2</polling-interval-seconds>   
  6.                  
  7.            </properties>   
  8.        </channel-definition>  

你可能感兴趣的:(Flex Blazeds推送机制)