移动Agent平台分析比较


1.1 移动Agent平台分析比较 

虽然移动Agent的实质是移动代码与代码运行挂起时所处的状态,也就是对象从一台主机移动到另一台主机上,我们自己就能实现,例如在JAVA中可以通过JAVA的序列化机制来实现,在C++中我们也可以用DCOM来实现。但是要实现移动Agent,为了加快开发节省成本我们一般要选择一个成熟的移动Agent开发平台。移动Agent开发平台为我们开发基于移动Agent的程序提供了各种公共服务。按照现有的实现技术可以将移动Agent系统分为两类:一种是基于移动代码的,例如Telescript;另一种是基于远程对象的,例如Aglet。下面对当前较为成熟的移动Agent系统平台的分析与对比如下:

1.D’Agent

D’Agent(以前称为Agent TCL)是美国Dartmouth大学研究的移动Agent系统。它从支持单一语言TCL发展到目前支持TCL,JAVA和Scheme等多种语言。D’Agent能自动捕获和恢复移动Agent的完整状态,即意味这代理可以在任意点中断执行,然后移动到其它环境中继续执行。

通讯基础: D’Agent的高层通讯机制采用RMI,KiaML等不同的通讯方式,它的服务程序是多线程的,每个代理在单独的进程中执行,这种方式简化了实现,但增加了进程间的通讯开销。

容错服务:Agent可以存储在物理介质上,以防止意外。

安全服务:D’Agent用公钥系统来对Agent进行身份认证,用静态资源管理来管理Agent对资源的访问,不但可以授权访问某种资源,还可以限制使用。

通信服务:支持异步或同步通信模式。

生命周期服务:支持复制克隆和远程创建等操作。

2.Aglet

Aglet是由日本IBM公司用纯JAVA开发的移动Agent技术,并提供了实用的平台-----Aglet Workbench,让人们开发或执行移动Agent系统。到目前为止,Aglet是上述出现实例中最为成功和全面的系统之一,主要表现在以下几个方面:

(1)提供了一个简单而全面的移动Agent编程模型。

(2)为Agent间提供了动态而有效的通信机制。

(3)提供了一套详细且易用的安全机制。

Aglet这个词是由”Agent”和”applet”两个字合成的。简单地说,Aglet就是具有Agent行为的Java applet对象。但Aglet同时传送代码及其状态,而applet只传送代码。Aglet以线程的形式产生于一台机器上,可以随时暂停执行的工作,而后整个Agent可以被分派到另一个机器上,再重新启动执行任务。因为它占用的是线程,所以不会消耗太多的系统资源。

3.Concordia

Concordia系统也是基于JAVA语言开发的一个移动Agent系统,它由Agent Manager,Security Manager, Queue Manager,Event Manager和Service Bridge模块组成。在每个网络节点上,Concordia都在运行Java虚拟机上的服务器,负责Agent的移动,持久性,安全,通讯等工作。Concordia 注重系统的安全性和容错性,系统安全保护措施是双向的,既保护节点资源又保护移动Agent本身。Concordia 对Agent的权限限制主要由使用者决定,这是它和Aglet系统的一个区别。Concordia 的通讯利用现有的TCP/IP通讯服务,其通讯模块提供的是异步通讯模式,没有提供同步通讯模式,这是该系统的一个不足之处。

4.Voyager

Recursion公司的Voyager可以看成是一个增强了的对象请求代理(ORB),同其它移动Agent系统相比,Voyager与Java语言的结合更加紧密,既可用于开发移动Agent系统,也可用于创建传统的分布式系统。Voyager是一个纯Java分布式计算平台,可用来迅速生成高性能分布式应用程序,是代表当前技术水平的一个优秀的移动Agent开发平台。

5.Grasshoper

Grasshoper是目前第一个符合MASIF标准,也是目前唯一符合MASIF和FIPA标准的,基于JAVA的移动Agent系统。 Grasshoper环境包括代理处(Agency)和域注册器,通过专有的ORB(Grasshoper ORB)互联。Agency(相当于MASIF中的Place)是代理实际的运行环境,数个Agency结合构成域,还可以通过JAVA RMI和Socket连接进行通讯。整个通讯结构实现采用插件技术,具有很好的扩充性。在容错服务方面,系统崩溃之后可以从存储介质中恢复Agent的原来执行状态.安全身份证用X. X09证书实现,传输中的安全性由SSL来保证,访问控制通过用户定制的安全管理来完成,实现了数字鉴名。通讯服务支持异步或同步的通讯,动态消息机制和多点发送:生命周期支持复制远程创建和克隆等操作。

2.2 移动Agent支撑平台Aglet

1.Aglet系统框架

Aglet的系统框架如图2.1所示:


                                    图2.1 Aglet的系统框架

 

      首先当一个正在执行的Aglet想要将自己迁移到远端时,会对Aglet Runtime层发出请求;接着Aglet Runtime层将Aglet的状态信息与代码转换成序列化的字节数组。这时如果成功,系统会将字节数组传送至ATCI(Agent Transport and Communication)接口,ATP是一个简单的应用层协议。接着,系统会将字节数组附上相关的系统信息,如系统名称以及Aglet的id等,并以比特流方式通过网络传至远程机器,远程机器通过ATCI层提供的ATP接口,接收到系统传来的字节数组及系统信息;最后,Aglet Runtime层对字节数组反序列化,得到Aglet的状态信息与代码,此时Aglet可以在远程机器上执行。

2.Aglet的生命周期

Aglet系统提供一个上下文环境(context)来管理Aglet的基本行为,包括创建(create)Agent、复制(clone)Agent、分派(dispatch)Agent到远端机器、召回(retract)远端的Agent、暂停(deactive)、唤醒(active)Agent,以及清除(dispose)Aglet等,其过程如图2.2所示:


                                         图2.2 Aglet的生命周期

 

3.Aglet工作台及Aglet的包结构

Aglet工作台是一个可视化环境,它被用来建立使用移动Agent的网络应用。目前它提供的工具包括:

(1)移动Agent的框架。

(2)ATP-----Agent传输协议。

(3)Tazza-----可视化地开发应用所需的个性化的移动Agent。

(4)JDBC-----用于访问DB2数据库。

(5)JoDax------访问单位的数据。

(6)Tahiti-----可视化Agent的管理页面。

(7)Fiji-----通过在WEB页面上对Agent实行生命周期控制。

Aglet包含如下几个包:

com.ibm.Aglet:这个包定义Aglet的一些接口以及提供管理Agent上下文环境,以及信息的发送和接收的常用方法。

com.ibm.Aglet.event:此包实现了对象模型中的生命周期。

com.ibm.Aglet.system:主要是管理Aglet运行层的一些函数。

com.ibm.Aglet.util:提供一些公共类,如letAudioClip。

com.ibm.Aglet.patterns:包含常见的消息传递模式,如Master-Slave、Notifier-Notification等。

3 Aglet实战

3.1 案例需求

分布式计算实现矩阵乘法。

在局域网中两台机器,一台为Master,一台为Slave。Master创建Matrix类,并创建Calculator类,发送到Slave机器上运行。Master机器将Slave机上运行完成后的Agent回收(结果),再和本机上的运行结果合并,并显示出最终结果。

3.2 程序实现

package examples.Matrix;

import com.ibm.aglet.*;

import com.ibm.aglet.event.*;

import com.ibm.aglet.util.*;

import java.lang.InterruptedException;

import java.io.Externalizable;

import java.io.ObjectInput;

import java.io.ObjectOutput;

import java.io.IOException;

import java.net.*;

import java.awt.*;

import java.awt.event.*;

import java.util.Enumeration;

/**作者:张华**/

public class Matrix extends Aglet {

transient MyDialog my_dialog = null; //没有串行化

URL dgp = null;//客户端地址

String message = null;

//矩阵初始化

int matone[][]=new int[10][10];

int mattwo[][]=new int[10][10];

int matthr[][]=new int[10][10];

boolean Flag;//设置标志量

int all = 0;

AgletProxy outer;//Agent客户机地址

//设置初始窗口

public void onCreation(Object init) {

Flag=true;

setMessage("Choose remote machine and GO!");//窗口显示信息

createGUI(); //创建窗口

}

//创建窗口

protected void createGUI(){

my_dialog = new MyDialog(this);

my_dialog.pack();

my_dialog.setSize(my_dialog.getPreferredSize());

my_dialog.setVisible(true);

}

//窗口显示信息

public void setMessage(String message){

this.message = message;

}

//处理信息

public boolean handleMessage(Message msg) {

if (msg.sameKind("Finish")) {

OutPut(msg);

} else if (msg.sameKind("startTrip")){

startTrip(msg);

} else{

return false;

};

return true;

}

//报告已经返回并销毁

public void OutPut(Message msg) {

setText("output begin");

while (Flag){

waitMessage(5*10);

};

my_dialog.msg.append("/n"+msg.getArg("answer").toString()+"/n");

}

public synchronized void startTrip(Message msg) { //到达远程机器

String destination = (String)msg.getArg(); // 得到远程机器地址

// 客户端得到 Agent 的内容

try{

outer=getAgletContext().createAglet(null,"examples.Matrix.Calculator",getProxy());

}catch(Exception e){setText("wrong!");};

try{

dgp=new URL(destination); //dgp 为客户端地址

}catch(MalformedURLException e){setText("wrong!");};

try{

outer.dispatch(dgp); // 发送到客户端

}catch(Exception e){setText("wrong!");};

matrixrun(); //本机上任务开始运行

}

//本机上程序

public void matrixrun(){

setText("matrixrun begin");

for (int x=0;x<10;x++){

for(int y=0;y<10;y++){

matone[x][y]=1;

mattwo[x][y]=1;

matthr[x][y]=0;

}

};

for (int x=0;x<5;x++){

for (int y=0;y<10;y++){

for (int z=0;z<10;z++){

matthr[x][y]=matthr[x][y]+matone[x][z]*mattwo[z][y];

}

}

};

Flag=false;

String result="";

for (int x=0;x<5;x++){

for (int y=0;y<10;y++){

result=result+"A["+x+"]["+y+"]="+matthr[x][y]+" ";

}

}

//打印本机结果

my_dialog.msg.append("The result shows down:"+"/n"+result+"/n"+"Local is over!");

setText("matrixrun over");

}

}

//MyDialog 窗口

class MyDialog extends Frame implements WindowListener, ActionListener{

private Matrix aglet = null;

//下面是一些GUI组件

private AddressChooser dest = new AddressChooser();

public TextArea msg =

new TextArea("",10,20,TextArea.SCROLLBARS_VERTICAL_ONLY);

private Button go = new Button("GO!");

private Button close = new Button("CLOSE");

//创建对话窗口

MyDialog(Matrix aglet) {

this.aglet = aglet;

layoutComponents();

addWindowListener(this);

go.addActionListener(this);

close.addActionListener(this);

}

//组件的布局

private void layoutComponents() {

msg.setText(aglet.message);

GridBagLayout grid = new GridBagLayout();

GridBagConstraints cns = new GridBagConstraints();

setLayout(grid);

cns.weightx = 0.5;

cns.ipadx = cns.ipady = 5;

cns.fill = GridBagConstraints.HORIZONTAL;

cns.insets = new Insets(5,5,5,5);

cns.weightx = 1.0;

cns.gridwidth = GridBagConstraints.REMAINDER;

grid.setConstraints(dest, cns);

add(dest);

cns.gridwidth = GridBagConstraints.REMAINDER;

cns.fill = GridBagConstraints.BOTH;

cns.weightx = 1.0;

cns.weighty = 1.0;

cns.gridheight = 2;

grid.setConstraints(msg, cns);

add(msg);

cns.weighty = 0.0;

cns.fill = GridBagConstraints.NONE;

cns.gridheight = 1;

Panel p = new Panel();

grid.setConstraints(p, cns);

add(p);

p.setLayout(new FlowLayout());

p.add(go);

p.add(close);

}

//事件的处理

public void actionPerformed(ActionEvent ae){

//对“go”按钮的处理

if("GO!".equals(ae.getActionCommand())){

aglet.setMessage(msg.getText());

msg.setText("");

try{

AgletProxy p = aglet.getProxy();

p.sendOnewayMessage(new Message("startTrip", dest.getAddress()));

}catch(Exception e) {

e.printStackTrace();

}

}

// 对“close”按钮的处理

else if("CLOSE".equals(ae.getActionCommand())){

setVisible(false);

}

}

public void windowClosing(WindowEvent we){

dispose();

}

public void windowOpened(WindowEvent we){

}

public void windowIconified(WindowEvent we){

}

public void windowDeiconified(WindowEvent we){

}

public void windowClosed(WindowEvent we){

}

public void windowActivated(WindowEvent we){

}

public void windowDeactivated(WindowEvent we){

}

}

//Calculator.java

package examples.Matrix;

import java.lang.InterruptedException;

import java.io.Externalizable;

import java.io.ObjectInput;

import java.io.ObjectOutput;

import java.io.IOException;

import java.net.*;

import java.util.Enumeration;

import com.ibm.aglet.*;

/**作者:张华**/

public class Calculator extends Aglet{

AgletProxy proxy=null;

int matone[][]=new int[10][10];

int mattwo[][]=new int[10][10];

int matthr[][]=new int[10][10];

public void onCreation(Object init){

setText("creation begin");

try{

proxy=(AgletProxy)init;

}catch(Exception e){setText("wrong!1");};

}

public void run(){

setText("Calculator begin");

for (int x=0;x<10;x++){

for(int y=0;y<10;y++){

matone[x][y]=1;

mattwo[x][y]=1;

matthr[x][y]=0;

}

};

for (int x=0;x<5;x++){

for (int y=0;y<10;y++){

for (int z=0;z<10;z++){

matthr[x+5][y]=matthr[x+5][y]+matone[x+5][z]*mattwo[z][y];

}

}

};

String result="";

setText("sendonewaymsg begin");

//客户端上从5开始

for (int x=5;x<10;x++){

for (int y=0;y<10;y++){

result=result+"A["+x+"]["+y+"]="+matthr[x][y]+" ";

}

};

//将结果返回到主机

try{

Message msg=new Message("Finish");

msg.setArg("answer",result);

System.out.println(msg.getArg("answer"));

this.proxy.sendOnewayMessage(msg);

}catch(Exception e){setText("wrong!2");};

}

}

3.3 代码分析

在实现中,我们采用了主从(master-slave)模式,这是aglet支持的众多模式中的一种,它充许主aglet把任务派发(dispatch)给从aglet,从aglet携带代码与状态移动到指定的目的主机上,与当地数据资源结合进行计算后,再将计算后的结果返回给主aglet

1.首先,通知主Agent向某个从Agent发送调用命令。

//主Agent的代理

AgletProxy p = aglet.getProxy();

//向主Agent发送消息,

p.sendOnewayMessage(

new Message("AgletClient1", “atp://localhost:82”));

Aglet与Aglet之间的通信,是使用消息传递的方式来传递消息对象的。此外,基于安全上的考虑,Aglet并非让外界直接存取其信息,而是透过一个代理(proxy)提供相应的接口与外界沟通。这样做有一个好处,即Aglet的所在位置会透明化,也就是说Aglet想要与远端的Aglet沟通时,只在本地主机的上下文环境中产生对应远端Aglet的代理,并直接与代理沟通即可,不必直接处理网络连接与通信的问题。

2.进入消息循环。

public boolean handleMessage(Message msg)

{

if (msg.sameKind("Finish"))

{

processRosponseResult(msg);

}

else if (msg.sameKind("AgletClient1"))

{

processAgletClient1(msg);

}

else

{

return false;

};

return true;

}

无论是主Agent还是从Agent都要继承自Agent类,并且要覆盖超类Agent类的消息循环处理函数handleMessage(),比如说现在收到的消息为AgletClient1,那么将要执行processAgletClient1(msg)方法。

3.在消息处理函数中,首先从环境(Context)中取得从Agent在本地的代理,然后将从Agent派发到目的主机上。


                                            图3.1 消息处理方法

 

4.从Agent与当地主机上的数据资源结合经过计算,并通过消息返回计算结果。


                                           图3.2 从Agent代码片断

3.4 运行程序

1) 从网上下载Aglet框架。我下载的是:aglets-2.0.2.jar

2)解压: jar xvf aglets-2.0.2.jar ( 注意:不能安装在中文目录下 )

3) 执行ANT命令:

4)设置Java policy:


5)设置环境变量:

AGLETS_HOME= E:/java/aglets2.02

AGLETS_PATH=%AGLETS_HOME%

PATH=%PATH%;%AGLETS_HOME%/bin

6) 将编译后的代码放到 %AGLETS_HOME%/public 目录下去,如下图:


7)启动Aglet (默认用户名是anonymous, 默认密码是:aglets)

启动后的Agent平台如下图所示:

8)创建主Agent (也就是Matrix类),点击“Create”按钮后如下图:


在上图中的Aglet name处输入Matrix类的全路径名(包名加类名),然后点击Create按钮,如下图:


9)将从Aglet发送到Slave机器上去执行运行,并回收结果。

在Adress处输入从Aglet的地址:atp://localhost:4434

( 注意:因为我的是本机,所以写的是 localhost, 确保从 Agent 机器上开启 Aglet 服务 )

运行后的结果如下图所示:


10) OK

4 移动Agent技术在JEE集群统一管理中的应用设想

移动Agent的代码是可以在各个域机器上移动,并结合本地机器资源进行计算的。

1)采用移动Agent的master-slave结构可以实现集群的集中式管理。比如说,在集群主结点机器上部署一个应用之后(相当于Aglet中的主Agent), 完全可以由从Agent将应用转换成字节流之后再移动到集群各从节点机器中自动部署,这样,这可以让用户部署集群应用时只部署在一台机器上就行了,提高了用户体验。

2)如果集群主结点想要了解各从结点的各类信息(如应用本身的状态信息、JVM的堆信息、甚至操作系统的内存CPU利用率等信息)都可以通过发送从Agent到从结点机器上采集信息后再返回得到。

3)如果主结点想要控制从结点(如启、停等等),在定义好协议之后,都可以通过从Agent代码移动到从结点机器上执行协议规定的相关操作即可。

4)如果移动Agent与ALI命令行框架相结合,所有管理操作都将可以在命令行中完成。

你可能感兴趣的:(论文)