最近在做基于vCenter web client平台上的运行的一个插件项目,在做Java端到Flex端的数据推送过程中遇到了很多的问题。所以写下这篇文章总结下问题
相关文档使用
vCenter web client的插件开发中,数据通信使用了spring-flex库,详细的使用方法参见官方文档:
docs.spring.io/spring-flex… (访问可能需要vpn)
而spring-flex使用了Adobe的中间件库Blazeds, Blazeds的官方文档已经在Adobe的官方支持文档中被移除 了。现在我唯一找到的是Blazeds的示例文档:
阅读文档的方法:
1. 在sourceforge.net/adobe/blaze… 中下载blazeds-turnkey-4.0.xxxxx.zip 的压缩包
2. 下载完成后解开压缩包, 打开sampledb文件夹,运行startdb.bat脚本创建运行数据库
3. 打开tomcat\bin文件夹,运行startup.bat脚本,启动blazeds自带的tomcat6服务器
4. 打开网站:http://localhost:8400/
根据相关文档教程可以使用如下配置进行主动推送的配置:
flex端配置方法:
在war/src/main/webapp/WEB-INF/flex目录中添加文件messging-config.xml
内容如下:
true
.
在service-config.xml中添加channel(channels标签内)
true
4
0
10
5000
并在标签中添加
以使用messging-config.xml文件中的配置
Channel介绍:
AMFChannel 类支持使用 AMF 进行消息传送。您可以配置此 Channel 每隔一段时间对服务器轮询以充分利用服务器推送技术。您还可以在禁用轮询的前提下使用此 Channel 将 RPC 消息发送到远程目标,以调用其方法。
AMFChannel 依赖于 Flash Player 和 AIR 的本机网络服务,并由 NetConnection 类向 ActionScript 公开。此通道以独占方式使用 NetConnection,并为每个实例创建一个新 NetConnection。
使用 ServerConfig.getChannel() 方法在框架内创建通道。如果需要,可以直接构造通道并将其分配给 ChannelSet。
通道表示到远程端点的物理连接。默认情况下,通道可以跨目标共享。这意味着定向于不同目标的客户端可以使用同一 Channel 与这些目标进行通信。
在轮询模式下使用时,此 Channel 将基于配置文件中的 polling-interval-seconds 属性轮询服务器以查看是否有新消息,您可以通过设置 pollingInterval 属性更改此设置。默认值为 3 秒。若要启用轮询,必须连接此通道并将配置文件中的 polling-enabled 属性设置为 true,或者必须将此 Channel 的 pollingEnabled 属性设置为 true。 StreamingAMFChannel 类支持消息传送并提供与基 AMFChannel 不同的推送模型。流通道将打开与处于打开状态的服务器之间的内部 HTTP 连接(而不是从服务器轮询数据),以允许服务器将数据传送到无需轮询开销的客户端。
通过此通道发送给服务器的消息使用 NetConnection 发送,并且在操作期间使用内部的 HTTP 连接。消息发送并返回确认或错误消息后,通道将释放 NetConnection 使用的 HTTP 连接。虽然通道保持打开状态可以接收服务器推送的数据,但这些客户端到服务器的消息并不通过流 HTTP 连接发送。
虽然此类可扩展基 AMFChannel 来继承常规 AMF 处理,但它并不支持轮询。
注意: 这里添加的channel都是以Secure开头的(如SecureAMFChannel),而网上的教程和文档多数是使用不以Secure开头的Channel(如AMFChannel), 这两者之间唯一的区别是前者使用了Https协议后者使用Http协议。 我在vCenter web client中使用AMFChannel进行数据推送并不能成功,只能使用SecureAMFChannel才能成功推送,原因应该是vCenter web client屏蔽了http协议。
在Felx应用中需要接受数据推送的地方创建Consumer对象,订阅数据推送:
var consumer:Consumer = new Consumer();
consumer.destination = "data-feed";
consumer.subtopic = "serverInfo";
consumer.selector = "hostName = 1" // 筛选条件
var myStreamingAMF:SecureStreamingAMFChannel = new SecureStreamingAMFChannel("my-polling-secure-amf", "/"+MirrorHA.contextPath+"/messagebroker/streamingamfsecure");
var myPollingAMF:SecureAMFChannel = new SecureAMFChannel("my-polling-secure-amf", "/"+MirrorHA.contextPath+"/messagebroker/amfpollingsecure");
var channelSet:ChannelSet = new ChannelSet();
channelSet.addChannel(myPollingAMF);
// channelSet.addChannel(myStreamingAMF);
consumer.channelSet = channelSet;
consumer.addEventListener(MessageEvent.MESSAGE, messageHandler);
consumer.subscribe();
Src/main/webapp/METE-INF/MANIFSET.MF文件中Import-Package:中添加flex.messaging.services.messaging.adapters
常见错误:
当启动vCenter web clinent是弹出提示框说无法连接Web client,这时却发现flex端没有编译错误, 一般这种问题是服务器的导包问题, 最好检查.xml配置文件中使用的类在METE-INF/MANIFSET.MF中的Import-Port:中是否被导入
Java端配置:
1. 在src/main/resources/META-INF/MANIFSET.MF文件中的Import-Package:中添加flex.messaging, flex.messaging.messages, flex.messaging.util 这几个需要用的包
2. 发生消息代码:
MessageBroker msgBroker = MessageBroker.getMessageBroker("MirrorHA-broker");
ModelServerInfo serverInfo = new ModelServerInfo();
serverInfo.serverName = "123";
serverInfo.hostId = "00000";
String clientID = UUIDUtils.createUUID();
AsyncMessage msg = new AsyncMessage();
msg.setDestination("data-feed");
msg.setHeader("DSSubtopic", "serverInfo");
// 填加筛选条件
Map headers = new HashMap();
headers.put("hostName", "1");
msg.setHeaders(headers);
msg.setClientId(clientID);
msg.setMessageId(UUIDUtils.createUUID());
msg.setTimestamp(System.currentTimeMillis());
msg.setBody(serverInfo);
msgBroker.routeMessageToService(msg, null);
注:MessageBroker.getMessageBroker()
中的参数是Flex端的spring/bundlen-context.xml中的id。如果没有配置message-broker则参数直接用null(Vm web client插件项目默认创建的配置是有的)
以上配置,可以让VM web client的插件使用轮询的方式让服务端发送数据。使用StreamingAMF的方式会出现问题
比如:打开StreamingAMF的请求得不到响应数据
正常情况下使用StreamingAMF时会有3条Streaming的请求数据。 当Open请求得不到响应的时候就会只有两条。StreamingAMF连接建立就失败了 造成这个的原因是Blazeds4和tomcat的版本兼容问题,Blazeds4发布的时候使用的是Tomcat6,而使用Tomcat7之后的版本对Blazeds4不太兼容。而vCenter web client5.5使用的Virgo服务器使用正是基于Tomcat 7.0.32版。
StreamingAMF无法使用 解决办法:
原理参考:stackoverflow.com/questions/1…
1. 创建一个Virgo Bundle Project项目
查看图片
在里面创建包路径com.acme.filter,再在filter包内创建class
package com.acme.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class MessageBrokerHack implements Filter{
public void init(FilterConfig paramFilterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, new HttpServletResponseWrapper(
(HttpServletResponse) response) {
public void setHeader(String name, String value) {
if (!("Connection".equalsIgnoreCase(name) && "Close"
.equalsIgnoreCase(value))) {
super.setHeader(name, value);
}
}
});
}
public void destroy() {
}
}
MANIFEST.MF文件需要写明导入和导出的包:
Manifest-Version: 1.0
Bundle-Version: 1.0.0
Bundle-Name: MessageBrokerHack
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.acme.rosedata.MessageBrokerHack
Import-Package: javax.servlet,
javax.servlet.http
Export-Package: com.acme.filter
将该类文件制作成jar包:MessageBrokerHack.jar 注意:打包时要保留该MANIFEST.MF文件
并将该jar包放到vSphereWebClient/server/pickup目录下(或者vSphereWebClient/server/repsitory/user目录下),让web服务器加载这个jar(也可以直接将该bundle项目加入virgo runtime server中)
2. 在Flex端中的war/src/main/webapp/META-INF/MANIFEST.MF文件中的Import-Package中添加com.acme.filter
3. 在Flex端中的war/src/main/webapp/WEB-INF/web.xml中添加我们自定义的filter
MessageBrokerHack
com.acme.filter.MessageBrokerHack
MessageBrokerHack
/messagebroker/*
完成,重启项目即可
本文链接: www.bugcoding.com/entry/18
版权所有。转载时必须以链接形式注明作者和原始出处及本声明。