freeeyes 发表于 2010-9-14 19:34:40

ICE开发初级研究(三)

本帖最后由 freeeyes 于 2010-9-15 11:06 编辑

在ICE的Slice里面,还有两个关键词需要补充说明一下。
nonmutating和Idempotent关键字。nonmutating关键字,指的是指定接口操作不会被修改,说白了就是C++的const关键字。Idempotent关键字是指某个操作无论之行多少次,返回结果都是一样的。这个关键字标记的这个对象可以多次反复调用执行,在多线程下也是安全的。

interface UserItems extends Items {
       nonmutating int GetUserItemCount();//得到用户的Items的个数
       Idempotentbool use();    //使用Items
};

其实上面这个声明,nonmutating在C++里面翻译过来就是const,你完全可以这么替换的看代码,这样比较清晰。至于Idempotent关键字,我个人认为声明的标记意义比较大,至于实用我还没有找到更多的含义。
其实,这两个关键字,在多语言环境下还是多少有点问题的,比如,在python中,nonmutating就会报错,因为python里面没有const这个概念。所以,实用它,见仁见智,如果大家都用C++去写,那么不妨实用它,否则,可以忽略之。
在slice的语法上,有两种设计思路,一种是把Slice里面的对象全部类化,比如:

interface Item{
nonmutating string Itemname();
nonmutating string Itemnamedesc();
nonmutating string Itemicon();
nonmutating int Itemprice();
};
sequence<Item*> ItemList;

你也可以这么设计,把接口完全理解成接口,隐藏内部实现接口,不必要的计算过程,不暴露给ICE

struct Item
{
string strItemname;
string strItemnamedesc;
string strItemicon;
string strItemprice;
};

sequence<Item*> ItemList;

interface Item{
nonmutating ItemList GetItems();
};


前一种的设计思路是,完全把对象看成对象,作为一个类去理解,后一种是把数据结构和类接口完全分开,思路是这里的接口仅仅是完成对象传输的意义,至于如何取舍,这里要看不同的需求而定。
前两篇文章主要说的是slice语法,下面,我讲一些更有意思的东西。ICE给我们提供了大量的上层服务,更大的简化我们的代码开发量。
IceGrid
这个东西,其实说白了,就是一种网格对象管理器的概念,通过它,你可以方便的把你的对象分布部署到不同的远端,并且通过Grid实现网格的调用。你的客户端只需要访问Grid的节点,至于这个Grid节点后面的对象管理,客户端完全不必知道,Grid会提供算法给你所要的对象,并返回执行结果。
其实,Grid的强大在于它的对象管理,你可以通过ICE的一个工具,清晰的看到所有对象被调用的情况,以及使用日志,崩溃日志和资源使用情况。你可以不必启动你的对象,当有人调用你提供的对象,Grid会自动启动你的对象,这样最大限度的减少了内存占用的情况,不用的对象永远不会启动,只有用到的时候才会启动。
相对而言,配合ICE的Freeze工具,你可以实现一套非常强大的内存对象管理体系,至于Freeze,我会放在下一章去讲,这里先提一句它的特性,Freeze是一个对象管理器,你可以不断的把很多的对象放在里面,它会根据你的对象调用频率,把最频繁访问的对象放在内存里,不常用的对象序列化到硬盘上,并且绑定它自己的数据库进行对象使用频度管理。这个东西是不是很酷?对于大量比如登陆对象请求,你完全可以不用理会大量的用户申请,使用Freeze设计好管理规则,因为它会帮助你把你的内存降到合理的范围,不常用的对象不会占据你的内存,更强的是,你几乎不用写什么代码。还有ICEStorm组件,分布式的消息通知机制,这些东西配合起来,可以完成很多看似很复杂的程序。这里,先详细说说Grid的特性。
呵呵,话题说回来,继续说我的Grid。
在你的ICE路径下,bin下面有一个IceGridGUI.jar程序。
你要运行它,必须先下载一个Java的运行环境,然后启动它,你会看到一个非常不错的管理界面,对,就是它。
这是一个Java写的GUI监控工具,你可以连接到Grid服务器,并显示这个Grid下的所有node的状态。
好,第一步,我们怎么建立一个Grid?
首先,你先建立一个目录,比如,这个目录叫做GridServerCell
在里面,我要建立两个文件和一个目录。
ServerRun.bat
GridServer.config
再建立一个当前文件夹下建立一个目录。
GridData
好了,让我们开始Grid之旅,我相信,它会对你的程序非常有用。
先来看看,我的GridServer.config写了一些什么。

IceGrid.InstanceName=TestIceGrid
#
# The IceGrid locator proxy.
#
Ice.Default.Locator=TestIceGrid/Locator:default -h XXX.XXX.XXX.XXX -p 20000
#
# IceGrid registry configuration.
#
IceGrid.Registry.Client.Endpoints=default -p 20000
IceGrid.Registry.Server.Endpoints=default
IceGrid.Registry.Internal.Endpoints=default
IceGrid.Registry.Data=GridData
IceGrid.Registry.PermissionsVerifier=TestIceGrid/NullPermissionsVerifier
IceGrid.Registry.AdminPermissionsVerifier=TestIceGrid/NullPermissionsVerifier
IceGrid.Registry.SSLPermissionsVerifier=TestIceGrid/NullSSLPermissionsVerifier
IceGrid.Registry.AdminSSLPermissionsVerifier=TestIceGrid/NullSSLPermissionsVerifier

# Trace properties.
#
IceGrid.Node.Trace.Activator=1
#
# Dummy username and password for icegridadmin.
#
IceGridAdmin.Username=freeeyes
IceGridAdmin.Password=freeeyes

看着有点晕是吧,实话说,我第一次调试Grid的时候也头大,这么多的东西代表什么含义?不过进过分析,其实并不复杂。很多地方都是固定的。有些地方,需要我们手动写一下。
IceGrid.InstanceName=TestIceGrid
这句话顾名思义,给你的Grid设置一个名称,目前3.4.1这个名字对中文支持不是很好,我们还是使用英文吧,当有人链接你的这个grid节点,这里会返回你的节点名称。
Ice.Default.Locator=TestIceGrid/Locator:default -h XXX.XXX.XXX.XXX -p 20000
这里是设置你的Grid服务器的地址和端口,-h 后面跟着你的IP,-p后面是你的端口。这里要注意,-h 千万别写127.0.0.1这样的地址,因为这个IP是被外面访问的,所以这里必须是别的计算机能找到你的。TestIceGrid是你的服务器名称,以后这个东西不在重复描述。
IceGrid.Registry.Client.Endpoints=default -p 20000
这里指定的是客户端访问的地址和端口。
IceGrid.Registry.Data=GridData
这里GridData指的就是你刚才建立的目录,两个文件和一个目录名,还记得么?当然,你可以使用绝对路径,放在和配置文件不同的地方。因为Grid服务启动后,会记录一些信息和日志,这些东西会自动的写到这些目录下。当然,你必须保证你的这个目录是可以被访问到的,而且是可以写入的。至于ICE写了什么,我在以后给大家补全,这里到目前为止我也只看懂了一部分。
IceGrid.Node.Trace.Activator=1
这里指的是你的Grid节点node可以被激活的个数。
IceGridAdmin.Username=freeeyes
IceGridAdmin.Password=freeeyes
这里指定的是你Grid管理员的用户和密码,意思就是,别人要对你的Grid对象进行控制(在Grid运行过程中),必须要使用密码才能进行。
其他部分,你完全可以理解成固定的,如果要刨根问底,请看ICE的手册,这里不再这里写了。
在看看ServerRun.bat

icegridregistry --Ice.Config=GridServer.config

这是一个bat文件(windows下,linux下,你可以做一个sh脚本,一样的,鉴于大家windows系统较多,如果想实现,可以在自己的机器上做实验),--Ice.Config=GridServer.config 这里指定的就是你刚才写的GridServer.config文件。
行了,你的一个Grid服务器建立好了。看吧,不难的。
接下来,我来说说在一个Grid下如何建立节点。这里要理清一个概念,这里的节点,并不是一定要依赖你的对象的,节点可以是空的。当然,这样是没有意义的。你把你的ICE对象适配器注册到这个节点,就可以接受Grid的管理了。节点你可以分步在不同的机器上。
大家听到这里肯定要问,写了这么多,Grid到底是干啥的?
呵呵,对,当初研究到node,我才理解到Grid的强大,比如,举个例子,你有200个对象,分步在20台服务器上,假设,这200个对象都是相同的,那么,我怎么实现,客户端调用对象的时候,完全的分布式呢?当然,你非要说,我把这200个对象地址配置在客户端对象上,我也无话可说。不过,如果对于我客户端,我想达到,我给你一个地址,你只要访问这里,至于这200个对象在什么地方不是你客户端关心的事情,当我使用的时候,这个地址会自动根据负载状态给我分配一个空闲的服务器对象,怎么做?呵呵,如果你想到了这些,说明你已经陈述出Grid的作用了。对,Grid就是干这个使的。对于真正分布式的计算,你可以创立很多的Grid服务器,每个Grid服务器负责处理一类对象,那么这样做,将大大减低你的开发量。同时,Grid增加减少节点,对于客户端来说,可以完全不知道。多方便!这才是我想要的分布式服务!对于客户端,它只需要知道一系列的Grid地址,至于这个Grid后面的网格布局,不是客户端所关心的事情。这才是更棒的网格。
好了,说到这里,我想你已经开始兴奋了吧。
那么让我们看看,如何建立一个Grid服务器对象节点,当然,这个节点的代码是可复制的,并且可以大量的方便复制。
让我们建立一个节点的文件夹,当然,你可以不放在GridServer的机器上,你完全可以找一个别的机器,比如,你同事的机器。
在这个目录里面,你需要建立两个文件和一个文件夹。(这里是不是有点熟悉,对了,和上面的方法是一样的)
node.config
run.bat
还有一个目录
Node(当前文件夹,当然,你也可以放在别处,无所谓的)
让我们看看node.config在干些什么?

#
# The IceGrid locator proxy.
#
Ice.Default.Locator=TestIceGrid/Locator:default -h XXX.XXX.XXX.XXX -p 20000

#
# IceGrid node configuration.
#
IceGrid.Node.Name=node_test
IceGrid.Node.Endpoints=default
IceGrid.Node.Data=Node

#
# Trace properties.
#
IceGrid.Node.Trace.Activator=1

Ice.Default.Locator=TestIceGrid/Locator:default -h XXX.XXX.XXX.XXX -p 20000
这行代码指的是你Grid服务器地址,你这个节点会注册到这个Grid管理器中去。
IceGrid.Node.Name=node_test
IceGrid.Node.Endpoints=default
IceGrid.Node.Data=Node
第一个节点名称,第二个是当前节点的地址(一般默认是default),最后一个是制定Node的目录路径(就是刚才建立的Node文件夹)。
好了,一个节点建立完成了。
那么你会问,如何把我的对象适配器绑定给这个node呢?答案是一个xml文件。
你建立一个GridNode.xml

<icegrid>
<application name="Test">
    <node name="node_Test">
      <server id="TestServer" exe="python" activation="on-demand">
       <option>mynode.py</option>
<adapter name="UserAdapter" endpoints="tcp" register-process="true">
   <object identity="Test" type="::Test::TestICE" property="Identity"/>
</adapter>
      </server>
    </node>
</application>
</icegrid>

这就是这个节点的配置文件<node name="node_Test">

这里的node_Test必须是是你的IceGrid.Node.Name=node_test里面指定的名称。
      <server id="TestServer" exe="python" activation="on-demand">
       <option>mynode.py</option>
这的exe="python" 指的是你的运行文件是一个python文件(这里你可以改成C++)
<option>mynode.py</option>
这个mynode.py就是你的类,如果是C++,你这里应该是mynode.exe。
<object identity="Test" type="::Test::TestICE" property="Identity"/>
这里identity="Test"是客户端要访问你的这个对象的代理名称,type="::Test::TestICE"指的是你的slice文件对应的<模块名>::<接口类>(具体请参见《ICE初级研究一》里面的ice文件)
好了,配置到这里,大功告成。
这个XML,是你的节点配置文件,每个节点通过这个xml来决定,通过<node name="node_Test">来关联你的节点配置文件。告诉节点你要在这个节点上绑定怎样的对象。
最后,当所有的Node启动以后,你需要在IceGridGUI读取这个xml,将你的这个xml合并到你的Node里面。这样做,Grid就能找到你的节点对应的对象位置了。Grid第一次启动,你的对象并不会被启动,只有当有请求到达的时候,Grid会通过这个配置文件找到你的对象,并启动起来,最大的节省你服务运行时的内存。
运行一下你的ServerRun.bat
再运行一下你的节点run.bat
最后运行你的IceGridGUI.jar

点击OK,如果显示出来了你的节点,那么祝贺你,你的Grid写成功了。

freebird92 发表于 2010-9-17 16:51:00

文章不错, 关注中, 请继续写下去。

zkliuym 发表于 2010-10-9 13:46:37

继续,期待下文

zkliuym 发表于 2010-10-27 16:21:11

下文 ... 下文 ...

freeeyes 发表于 2010-10-28 18:29:28

最近忙着填充框架,等有时间我继续写。
页: [1]
查看完整版本: ICE开发初级研究(三)