slice: ice提供了本身的接口定義語言。用來定義rpc的接口和對象。java
ice.object: rpc調用的接口必須繼承自ice.Objectnode
servant:ice.Object的實例化對象叫作servant,rpc調用的就是servant對象,所以servant須要線程安全安全
endpoints:客戶端rpc調用servant的地址服務器
icebox:servant的容器app
icenode:icebox的容器less
registry:註冊中心,負責管理icenode的註冊,負責和發佈。
dom
步驟:
eclipse
啓動registrytcp
啓動node,註冊到registryide
將代碼部署到node服務器上
將應用描述文件應用到registry上,node上將自動啓動application
registry配置文件一個:registry.cfg
node配置文件n個:node1.cfg, node2.cfg
應用描述文件app.xml
配置文件詳情:
registry.cfg
# grid實例名 IceGrid.InstanceName=SzcIceGrid #客戶端鏈接到註冊中心的地址 IceGrid.Registry.Client.Endpoints=tcp -p 4061 IceGrid.Registry.Server.Endpoints=tcp IceGrid.Registry.Internal.Endpoints=tcp IceGrid.Registry.PermissionsVerifier=SzcIceGrid/NullPermissionsVerifier IceGrid.Registry.AdminPermissionsVerifier=SzcIceGrid/NullPermissionsVerifier #註冊中心數據保存路徑,須要手動建立文件夾 IceGrid.Registry.Data=/data/shizc/Desktop/ice/registry IceGrid.Registry.DynamicRegistration=1 Ice.Admin.InstanceName=AdminInstance Ice.Admin.ServerId=Admin
node1.cfg
# 註冊中心地址 Ice.Default.Locator=SzcIceGrid/Locator:tcp -h 192.168.7.7 -p 4061 #node名 IceGrid.Node.Name=node1 IceGrid.Node.Endpoints=tcp #node存儲路徑 IceGrid.Node.Data=/data/shizc/Desktop/ice/nodes/node1 IceGrid.Node.Output=/data/shizc/Desktop/ice/nodes/node1 IceGrid.Node.CollocateRegistry=0 #IceGrid.Node.Trace.Replica=2 #IceGrid.Node.Trace.Activator=3 #IceGrid.Node.Trace.Adapter=3 #IceGrid.Node.Trace.Server=3
node2.cfg
# 註冊中心地址 Ice.Default.Locator=SzcIceGrid/Locator:tcp -h 192.168.7.7 -p 4061 IceGrid.Node.Name=node2 IceGrid.Node.Endpoints=tcp IceGrid.Node.Data=/data/shizc/Desktop/ice/nodes/node2 IceGrid.Node.Output=/data/shizc/Desktop/ice/nodes/node2 IceGrid.Node.CollocateRegistry=0 #IceGrid.Node.Trace.Replica=2 #IceGrid.Node.Trace.Activator=3 #IceGrid.Node.Trace.Adapter=3 #IceGrid.Node.Trace.Server=3
app.xml
<icegrid> <application name="FileSystemApp"> <properties id="MultiThreaded" > <property name="Ice.PrintStackTraces" value="1" ></property> <property name="IceSSL.Trace.Security" value="2" ></property> <property name="Ice.ThreadPool.Client.Size" value="2" ></property> <property name="Ice.ThreadPool.Client.SizeMax" value="50" ></property> <property name="Ice.ThreadPool.Server.Size" value="10" ></property> <property name="Ice.ThreadPool.Server.SizeMax" value="100" ></property> <property name="IceBox.InheritProperties" value="1" ></property> <property name="Ice.Override.ConnectTimeout" value="5000" ></property> <property name="Ice.Override.Timeout" value="10000" ></property> <property name="IceBox.Trace.ServiceObserver" value="1" ></property> <property name="Ice.Default.LocatorCacheTimeout" value="300" ></property> <property name="Ice.BackgroundLocatorCacheUpdates" value="1" ></property> </properties> <!-- 配置模板 --> <server-template id="FileSystemServerIceBoxTemplate"> <parameter name="index" default="0"></parameter> <!-- exe指定java啓動 --> <icebox id="FileSystemServerIceBox${index}" exe="java" activation="on-demand" > <properties> <properties refid="MultiThreaded" /> </properties> <option>-Xmx512M</option> <!-- icebox啓動main方法 --> <option>IceBox.Server</option> <!-- 開發的代碼路徑 --> <env>CLASSPATH=.:/usr/share/java/*:/data/shizc/Desktop/ice/bin</env> <!-- entry指定icebox啓動的service, replica-group指定endpoints組 --> <service name="FilesystemService" entry="service.FilesystemService"> <adapter name="FilesystemService" id="FilesystemService${index}" endpoints="default" replica-group="FilesystemServiceRep" ></adapter> </service> </icebox> </server-template> <replica-group id="FilesystemServiceRep"> <load-balancing type="round-robin" n-replicas="0" /> <!-- 指定servant的名字 --> <object identity="RootDir" type="::filesystem::Directory"></object> <object identity="iamfile" type="::filesystem::File"></object> </replica-group> <!-- 每一個node定義2個icebox --> <node name="node1"> <server-instance template="FileSystemServerIceBoxTemplate" index="11"></server-instance> <server-instance template="FileSystemServerIceBoxTemplate" index="12"></server-instance> </node> <node name="node2"> <server-instance template="FileSystemServerIceBoxTemplate" index="21"></server-instance> <server-instance template="FileSystemServerIceBoxTemplate" index="22"></server-instance> </node> </application> </icegrid>
icegridregistry --Ice.Config=registry.cfg
icegridnode --Ice.Config=node1.cfg
icegridnode --Ice.Config=node2.cfg
icegridadmin --Ice.Config=node1.cfg
登錄後
application add app.xml
定義slice:
[["java:package:com.asto"]] module filesystem{ interface Node{ string name(); }; exception GenericError{ string reason; }; sequence<string> Lines; interface File extends Node{ Lines read(); void write(Lines text) throws GenericError; }; sequence<Node*> NodeSeq; interface Directory extends Node{ NodeSeq list(); }; interface FileSys{ Directory* getRoot(); }; };
經過eclipse插件或命令slice2java轉換成java類
實現Directory接口和File接口
package servant; import java.util.ArrayList; import java.util.List; import java.util.UUID; import com.asto.filesystem.NodePrx; import com.asto.filesystem.NodePrxHelper; import com.asto.filesystem._DirectoryDisp; import Ice.Current; public class DirectoryI extends _DirectoryDisp { public static Ice.ObjectAdapter _adapter; public String _name; public DirectoryI _parent; public List<NodePrx> _content = new ArrayList<NodePrx>(); public DirectoryI(String _name, DirectoryI _parent) { super(); this._name = _name; this._parent = _parent; Ice.Identity theId = Ice.Util.stringToIdentity(_parent == null ? "RootDir" : UUID.randomUUID().toString()); _adapter.add(this, theId); // 自身的代理 NodePrx theNode = NodePrxHelper.uncheckedCast(_adapter.createProxy(theId)); // 把本身添加到父目錄的子節點中 if (_parent != null) { _parent.addChild(theNode); } } @Override public NodePrx[] list(Current __current) { System.out.println("[DirectoryI]invoke list @" + Thread.currentThread().getName()); NodePrx[] retList = new NodePrx[_content.size()]; retList = _content.toArray(retList); return retList; } @Override public String name(Current __current) { System.out.println("[DirectoryI]invoke name @"+ Thread.currentThread().getName()); return _name; } void addChild(NodePrx child) { System.out.println("[DirectoryI]invoke addChild @"+ Thread.currentThread().getName()); _content.add(child); } }
package servant; import java.util.UUID; import com.asto.filesystem.GenericError; import com.asto.filesystem.NodePrx; import com.asto.filesystem.NodePrxHelper; import com.asto.filesystem._FileDisp; import Ice.Current; public class FileI extends _FileDisp { public static Ice.ObjectAdapter _adapter; public String _name; public DirectoryI _parent; public String[] _lines; public FileI(String _name, DirectoryI _parent) { super(); this._name = _name; this._parent = _parent; assert(_parent != null); String identiyName = UUID.randomUUID().toString(); if("README".equalsIgnoreCase(_name)){ identiyName = "iamfile"; } System.out.println("FileI'identiy:"+identiyName); Ice.Identity theId = Ice.Util.stringToIdentity(identiyName); _adapter.add(this, theId); NodePrx theNode = NodePrxHelper.uncheckedCast(_adapter.createProxy(theId)); _parent.addChild(theNode); } @Override public String[] read(Current __current) { System.out.println("[FileI]invoke read @"+ Thread.currentThread().getName()); return _lines; } @Override public void write(String[] text, Current __current) throws GenericError { System.out.println("[FileI]invoke write @"+ Thread.currentThread().getName()); _lines = text; } @Override public String name(Current __current) { System.out.println("[FileI]invoke name @"+ Thread.currentThread().getName()); return _name; } }
這2個接口的實現類中都包含了一個Ice.ObjectAdapter, servant要經過adapter對外提供服務。
在構造方法中,將自身的實例(servant)添加進adapter中。
實現Icebox的的Service接口,
package service; import com.asto.filesystem.GenericError; import Ice.Communicator; import IceBox.Service; import servant.DirectoryI; import servant.FileI; public class FilesystemService implements Service { private Ice.ObjectAdapter _adapter; @Override public void start(String name, Communicator communicator, String[] args) { _adapter = communicator.createObjectAdapter(name); DirectoryI._adapter = _adapter; FileI._adapter = _adapter; DirectoryI root = new DirectoryI("/", null); FileI file = new FileI("README", root); String[] text = new String[] { "This file system contain a collection of poetry." }; try { file.write(text); } catch (GenericError e) { System.err.println(e.reason); } DirectoryI coleridge = new DirectoryI("Coleridge", root); file = new FileI("Kubla_Khan", coleridge); text = new String[] { "In Xanadu did Kubla Khan", "A stately pleasure-dome decree:", "Where Alph, the sacred river, ran", "Through caverns measureless to man", "Down to a sunless sea." }; try { file.write(text); } catch (GenericError e) { System.err.println(e.reason); } _adapter.activate(); System.out.println("FileSystemServer adapter activate @" + Thread.currentThread().getName()); } @Override public void stop() { System.out.println(getClass().getName() + " _adapter destroy @" + Thread.currentThread().getName()); if(_adapter != null){ _adapter.destroy(); } } }
FileSystemService在app.xml中配置到Icebox中。
client調用:
public static void main(String[] args){ Ice.Communicator ic = null; try{ ic = Ice.Util.initialize(args); // Ice.ObjectPrx basePrx = ic.stringToProxy("iamfile"); // FilePrx detailPrx = FilePrxHelper.checkedCast(basePrx); Ice.ObjectPrx basePrx = ic.stringToProxy("RootDir"); DirectoryPrx detailPrx = DirectoryPrxHelper.checkedCast(basePrx); if(detailPrx == null){ System.err.println("filePrx is null"); System.exit(1); } String name = detailPrx.name(); System.out.println("fileName is :" + name); }catch(Exception e){ e.printStackTrace(); }finally{ if(ic != null){ ic.shutdown(); ic.waitForShutdown(); ic.destroy(); } } }
client運行須要添加一個配置文件,指定registry地址
client.cfg
Ice.Default.Locator=SzcIceGrid/Locator:tcp -h 192.168.7.7 -p 4061
在運行client的時候指定配置文件
java com.client.Client --Ice.Config=client.cfg
參考了《ZeroC Ice權威指南》和 http://blog.csdn.net/lihuayong/article/details/9901417