反叛之冰:ZeroC ICE基础使用

时间:2020-09-30 05:29:46
【文件属性】:

文件名称:反叛之冰:ZeroC ICE基础使用

文件大小:152KB

文件格式:DOC

更新时间:2020-09-30 05:29:46

zeroc ice

1 系统环境 系统:Win7。 版本:JDK 1.8.0_91,ZeroC ICE 3.6.3。 2 基础 官网:https://zeroc.com 视频教程:https://www.chuanke.com/v6242976-184547-1010808.html 书籍:ZeroC Ice权威指南 高清 带索引书签目录 leader-us(著) 2.1 ICE基础 2.2 Slice 2.2.1 基本数据类型 类型 定义及范围 长度 bool true of false ≥ 1bit byte [-128, 127] or [0, 255] ≥ 8bit short [-2^15, 2^15-1] ≥ 16bit int [-2^31, 2^31-1] ≥ 32bit long [-2^63, 2^63-1] ≥ 64bit float ≥ 32bit double ≥ 64bit string variable-length 2.2.2 常量定义 用const修饰,如: const bool trueOrFalse = true; const byte b = 0x0f; const string msg = “hello”; const short s = 56; const double PI = 3.1416; enum Fruit {Apple, Orange}; (enum类型其实等价于int) const Fruit favoriteFruit = Orange; 2.2.3 复合数据结构定义 类型 含义说明 enum 枚举,如: enum Fruit {Apple, Orange} 或: enum Fruit {Apple = 5, Orange = 1} 实际上enum类型等价于int struct 结构体,保护多个属性数据,类似与JavaBean。 struct Student { int id; string name; } sequence 复合类型,支持 基本类型的集合 或者 复合类型的集合,如: sequence FruitPlatter; sequence FruitBanquet; (集合的集合) dictionary Map类型,类似于Java HashMap,如: dictionary StudentMap 例: struct TimeOfDay { shor hour; // 0 - 23 shor minute; // 0 - 59 shor second; // 0 - 59 }; 2.2.4 异常定义 exception Error {}; // 可定义空异常 exception RangeError { TimeOfDay errorTime; TimeOfDay minTime; TimeOfDay maxTime; }; 2.2.5 slice文件复用 使用#include关键字可引用其他slice文件: #include common.slice 2.2.6 接口和方法定义 使用interface来申明接口(语法上跟java定义接口语法类似,只是没有public关键字),如: interface Clock { TimeOfDay getTime(); void setTime(TimeOfDay time); } Idempotent关键词:用该关键词修饰方法,指明该方法是幂等的,即调用1次和调用2次其结果是一样的。添加Idempotent修饰的方法,可以让ICE更好地实现“自动恢复错误”机制,即在某个Ice Object调用失败的情况下,ICE会再次调用有Idempotent修饰的方法,透明恢复故障,而在客户端看来则调用正常,没有感觉到ICE做了自动故障恢复操作。 3 实例 参考:http://blog.csdn.net/xuzheng_java/article/details/24459181 所需jar包: ICE安装目录下lib目录里的ice-3.6.3.jar 3.1 Slice脚本 HelloWorldIDL.ice [["java:package:myice.demo"]] module test { interface HelloWorldIDL { string sayHello(string username); }; }; 说明:  slice文件必须以ice为后缀。  [["java:package:myice.demo"]]定义java父包路径,module表示模块名,真正生成的包路径为myice.demo.test。  module定义不能缺少。  在定义语句的结尾(如右花括号)需要以分号结尾。 3.2 生成通用服务类 slice2java --output-dir D:\iceoutput D:\slice\HelloWorldIDL.ice 3.3 Server端编写服务实现类  HelloWorldHandler.java package server; import Ice.Current; import myice.demo.test._HelloWorldIDLDisp; /** * 接口处理类,继承生成的_HelloWorldIDLDisp类 */ public class HelloWorldHandler extends _HelloWorldIDLDisp { private static final long serialVersionUID = 1L; /* * 在__current.ctx里可获取到客户端额外上送的参数 */ @Override public String sayHello(String username, Current __current) { return "Hello ZeroC ICE, [" + username + "]"; } }  HelloIceHandler.java package server; import Ice.Current; import myice.demo.test._HelloWorldIDLDisp; /** * 接口处理类,继承生成的_HelloWorldIDLDisp类 */ public class HelloIceHandler extends _HelloWorldIDLDisp { private static final long serialVersionUID = 1L; /* * 在__current.ctx里可获取到客户端额外上送的参数 */ @Override public String sayHello(String username, Current __current) { return "Hello ICE ASDFSDF, [" + username + "]"; } } 3.4 Server端注册服务并监听请求 package server; public class HelloWorldServer { public static void main(String[] args) { Ice.Communicator communicator = null; try { // 初始化ICE Communicator对象,args可以传一些初始化参数,如连接超时、初始化客户端连接池数量等 communicator = Ice.Util.initialize(args); // 创建ObjectAdapter(名称为helloWorldAdapter),使用缺省的通信协议(TCP/IP),端口为7890,用于监听请求 Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints("helloWorldAdapter", "default -p 7890"); // 创建服务端接口处理handler实例(ice里称为servant) HelloWorldHandler helloWorldHandler = new HelloWorldHandler(); /* * 将helloWorldHandler添加到ObjectAdapter中,并将helloWorldHandler关联到ID为"helloWorldHandler"的Ice Object * (此处ID相当于接口名称,全局唯一,client端通过该名称连接上来) */ adapter.add(helloWorldHandler, Ice.Util.stringToIdentity("helloWorldHandler")); adapter.activate(); // 激活ObjectAdapter // 在服务退出前,一直监听请求 communicator.waitForShutdown(); } catch (Exception e) { e.printStackTrace(); } finally { if (communicator != null) { communicator.destroy(); } } } } 3.5 Client发送请求并得到响应 package client; import myice.demo.test.HelloWorldIDLPrx; import myice.demo.test.HelloWorldIDLPrxHelper; public class HelloWorldClient { public static void main(String[] args) { Ice.Communicator communicator = null; try { // 初始化ICE Communicator对象,args可以传一些初始化参数,如连接超时、初始化客户端连接池数量等 communicator = Ice.Util.initialize(args); // 传入远程服务接口的名称、网络协议、IP和端口,创建一个Proxy对象 Ice.ObjectPrx base = communicator.stringToProxy("helloWorldHandler:default -p 7890"); /* * 通过checkedCast向下转型,获取HelloWorld接口的代理类(客户端) * 其中:HelloWorldIDLPrx和HelloWorldIDLPrxHelper为生成的类 */ HelloWorldIDLPrx helloWorldClient = HelloWorldIDLPrxHelper.checkedCast(base); if (helloWorldClient != null) { String result = helloWorldClient.sayHello("ZEROC ICE"); // 可额外传参到服务端,服务端在Current的ctx属性里可获取到传参值。如: // Map params = new HashMap(); // params.put("param1", "aaaaaaa"); // params.put("param2", "bbbbbbb"); // String result = helloWorldClient.sayHello("ZEROC ICE", params); System.out.println(result); } } catch (Exception e) { e.printStackTrace(); } finally { if (communicator != null) { communicator.destroy(); } } } } 3.6 运行 运行HelloWorldServer,启动服务。 运行HelloWorldClient,调用远程服务接口,控制台打印如下: Hello ZeroC ICE, [ZEROC ICE] 成功调用远程服务。 4 IceBox IceBox类似于Tomcat,里面可以加载多个服务器实例(应用)。本章节示范一个IceBox容器的开发过程。 所需jar包:icebox-3.6.3.jar 4.1 服务器实例编写 一个IceBox服务器实例继承自IceBox.Service接口: package icebox; import Ice.Communicator; import IceBox.Service; import server.HelloIceHandler; import server.HelloWorldHandler; /** * IceBox服务器实例,实现IceBox.Service接口 */ public class HelloWorldServer2 implements Service { private Ice.ObjectAdapter adapter = null; @Override public void start(String name, Communicator communicator, String[] arg2) { System.out.println("ice box helloworld starting..."); adapter = communicator.createObjectAdapter(name); // 创建服务端接口处理handler实例(ice里称为servant) HelloWorldHandler helloWorldHandler = new HelloWorldHandler(); HelloIceHandler helloIceHandler = new HelloIceHandler(); // 将Handler添加到ObjectAdapter中 adapter.add(helloWorldHandler, Ice.Util.stringToIdentity("helloWorldHandler2")); adapter.add(helloIceHandler, Ice.Util.stringToIdentity("helloIceHandler2")); adapter.activate(); // 激活ObjectAdapter System.out.println("ice box helloworld started."); } @Override public void stop() { adapter.destroy(); System.out.println("ice box helloworld stoped."); } } 4.2 配置文件编写 编写icebox.properties配置文件,建议放在classpath里,示例配置如下: #icebox instance properties begin IceBox.InstanceName=MyIceBox 1 IceBox.InheritProperties=1 IceBox.PrintServicesReady=MyAppIceBox 1 #icebox instance properties end #log define begin Ice.Trace.Network=1 Ice.Trace.ThreadPool=1 Ice.Trace.Locator=1 #log define end #server define begin IceBox.Service.HelloWorldServer2=icebox.HelloWorldServer2 prop1=1 prop2=2 prop3=3 IceBox.UseSharedCommunicator.HelloWorldServer2=1 HelloWorldServer2.Endpoints=tcp -h localhost -p 7890 #server define end 4.3 运行 4.3.1 启动IceBox容器  在eclipse里调试 运行IceBox容器,可通过java命令运行,也可在eclipse里调试: 在项目上右击->Debug As->Debug configurations,新建一个debug configuration,配置信息如下: Main->Name:根据需要填写,如IceBoxTest Main->MainClass:IceBox.Server Arguments->program arguments:--Ice.Config=icebox.properties 点击debug按钮,即可启动MainClass进行调试。  通过代码启动 package icebox; public class StartIceBox { public static void main(String[] args) { IceBox.Server icebox = new IceBox.Server(); icebox.main(new String[] {"--Ice.Config=icebox.properties"}); } } 4.3.2 运行客户端 运行章节3.5即可。 5 IceGrid IceGrid为ICE提供的分布式系统架构,由一个Ice Registry + N个Ice Grid Node组成。 5.1 Ice Registry Ice Registry(注册表)组件用于存储服务的Endpoint信息,支持主从同步,从节点可以分担查询请求,类似MySQL的读写分离,并防止单点故障。Registry以二进制文件形式存储运行期Ice服务注册信息。 IceBox可以注册到Registry上,客户端通过向Registry发送请求,得到具体的服务的Endpoint信息,然后建立起服务之间的直连TCP通道,此后的数据交互就在这个直连通道上完成。 本节示例配置一个Registry组件,并注册一个IceBox服务到Registry上,编写客户端通过该Registry来访问服务,此处Registry仅提供查询服务的功能。 5.1.1 启动Registry  配置文件 编写配置文件:icegridregistry.cfg IceGrid.InstanceName=MyIceGrid #默认名称是IceGrid IceGrid.Registry.Client.Endpoints=tcp -h 192.168.1.7 -p 4061 IceGrid.Registry.Server.Endpoints=tcp -h 192.168.1.7 IceGrid.Registry.Internal.Endpoints=tcp -h 192.168.1.7 IceGrid.Registry.Data=D:\Program Files (x86)\ZeroC\data\registry #路径需手动创建好 IceGrid.Registry.PermissionsVerifier=MyIceGrid/NullPermissionsVerifier IceGrid.Registry.AdminPermissionsVerifier=MyIceGrid/NullPermissionsVerifier IceGrid.Registry.DynamicRegistration=1  启动 进入ice安装目录下的bin子目录,启动registry,如: D:\Program Files (x86)\ZeroC\Ice-3.6.3\bin> icegridregistry --Ice.Config=D:\ZerocICE\publish\rsrc\icegridregistry.cfg 启动后,可在IceGrid.Registry.Data目录下看到生成的一堆二进制文件。 5.1.2 注册IceBox到Registry 注册IceBox到Registry,只需在原有的IceBox配置文件(4.1)上添加如下配置,启动IceBox即可: #iceboxregistry define begin Ice.Default.Locator=MyIceGrid/Locator:tcp -h 192.168.1.7 -p 4061 HelloWorldServer2.AdapterId=HelloWorldServer2 #iceboxregistry define end 其中: MyIceGrid为registry里定义的IceGrid.InstanceName属性值,其后的ip port为 registry的ip port。 HelloWorldServer2.AdapterId=HelloWorldServer2格式为:{serviceName}.AdapterId={adapterName},本例serviceName和adapterName均为IceBox配置里IceBox.Service.{serviceName}上的serviceName值。 5.1.3 Client发送请求并获得响应 修改3.5里的获取代理类的代码即可。完整代码如下: package client; import myice.demo.test.HelloWorldIDLPrx; import myice.demo.test.HelloWorldIDLPrxHelper; public class HelloWorldClient4IceGrid { public static void main(String[] args) { Ice.Communicator communicator = null; try { communicator = Ice.Util.initialize(new String[] {"--Ice.Default.Locator=MyIceGrid/Locator:tcp -h 192.168.1.7 -p 4061"}); Ice.ObjectPrx base = communicator.stringToProxy("helloWorldHandler2@HelloWorldServer2"); HelloWorldIDLPrx helloWorldClient = HelloWorldIDLPrxHelper.checkedCast(base); if (helloWorldClient != null) { String result = helloWorldClient.sayHello("fffkkk"); System.out.println(result); } } catch (Exception e) { e.printStackTrace(); } finally { if (communicator != null) { communicator.destroy(); } } } } 5.1.4 运行 启动IceBox服务,注册HelloWorldServer2到Registry。 运行HelloWorldClient4IceGrid,调用远程服务接口,控制台打印如下: Hello ZeroC ICE, [fffkkk] 成功调用远程服务。 5.2 IceGrid Node IceGrid Node为IceGrid集群里的节点,负责IceBox的装载和启停、采集主机的负载信息和执行控制器IceGrid Admin的指令。 IceGrid Node是IceBox的容器,IceBox是服务(如HelloWorldServer2)的容器。一个IceGrid Node可以部署多个IceBox实例,这些实例可以是同一个IceBox的多个实例也可以是多个不同IceBox的实例组合。IceGrid Node连同其上运行的IceBox实例的信息同步到了Registry中。 每个IceGrid Node都有唯一的名字,用来在IceGrid中标识其身份,可以在用一个服务器上部署多个IceGrid Node,只要确保其都有唯一的名字即可。每个IceGrid Node都有一个配置文件,定义了其启动参数。 5.2.1 启动IceGrid Node  配置文件 编写配置文件:icegridnode.cfg Ice.Default.Locator=MyIceGrid/Locator:tcp -h 192.168.1.7 -p 4061 # 指定Ice Registry信息 IceGrid.Node.Name=node1 IceGrid.Node.Endpoints=tcp -h 192.168.1.7 IceGrid.Node.Data=D:\Program Files (x86)\ZeroC\data\node1 # 所有目录需预先创建好 IceGrid.Node.Output=D:\Program Files (x86)\ZeroC\data\node1 Ice.StdErr=D:\Program Files (x86)\ZeroC\data\node1\stderr.log Ice.StdOut=D:\Program Files (x86)\ZeroC\data\node1\stdout.log  启动 进入ice安装目录下的bin子目录,启动registry,如: D:\Program Files (x86)\ZeroC\Ice-3.6.3\bin> icegridnode --Ice.Config=D:\ZerocICE\publish\rsrc\icegridnode.cfg 启动后,可在IceGrid.Node.Data目录下看到生成的一堆文件。 5.3 IceGrid集群  系统环境 CentOS 7,jdk1.8.0_91,zeroc ice 3.6.3  系统拓扑 服务器 节点类型 服务 192.168.1.210 Ice Registry 1个Ice Registry、1个IceBox 192.168.1.212 IceGrid Node 1个IceBox 192.168.1.213 IceGrid Node 1个IceBox  服务器安装ice CentOS下可安装Red Hat版本ICE: # cd /etc/yum.repos.d # wget https://zeroc.com/download/rpm/zeroc-ice-el7.repo # yum install ice-all-runtime ice-all-devel 5.3.1 icegridadmin使用 icegridadmin为IceGrid集群管理工具,用于部署或升级IceGrid、查看IceGrid节点状态、启停Node中的Server实例等。运行icegridadmin,需要先启动Registry和Node。  启动icegridadmin 进入ice安装目录下的bin子目录,运行如下命令: D:\Program Files (x86)\ZeroC\Ice-3.6.3\bin> icegridadmin -u test -p test --Ice.Default.Locator="MyIceGrid/Locator:tcp -h 192.168.1.7 -p 4061" 即可进入icegridadmin操作符模式。由于Registry在本地且没开启权限验证,所以可用test/test用户名及密码来访问 Registry注册表。 5.3.2 集群搭建(暂单服务器) 首先将程序包分发到各个服务器上,根据配置文件建立必要的目录。  IceBox代码 参照第3章和第4.1章节,完成IceBox服务器代码的编写。 此时不需要IceBox的配置文件,将由IceGrid自动生成。  启动Ice Registry 参考5.1.1章节,在192.168.2.10上启动icegridregistry服务: # icegridregistry --daemon --Ice.Config=/root/iceserver/rsrc/icegridregistry.cfg 启动后可使用一下命令查看启动后运行在后台的进程: # ps aux | grep ice 配置文件示例: [root@nn rsrc]# more icegridregistry.cfg IceGrid.InstanceName=MyIceGrid IceGrid.Registry.Client.Endpoints=tcp -h 192.168.1.210 -p 4061 IceGrid.Registry.Server.Endpoints=tcp -h 192.168.1.210 IceGrid.Registry.Internal.Endpoints=tcp -h 192.168.1.210 IceGrid.Registry.Data=/root/iceserver/data/registry IceGrid.Registry.PermissionsVerifier=MyIceGrid/NullPermissionsVerifier IceGrid.Registry.AdminPermissionsVerifier=MyIceGrid/NullPermissionsVerifier IceGrid.Registry.DynamicRegistration=1  启动IceGrid Node 参考5.2.1章节,启动icegridnode服务: # icegridnode --daemon --Ice.Config=/root/iceserver/rsrc/icegridnode.cfg 各个服务的配置可根据需要做微调,如节点目录。 配置文件示例: [root@nn rsrc]# more icegridnode.cfg # 指定Ice Registry信息 Ice.Default.Locator=MyIceGrid/Locator:tcp -h 192.168.1.210 -p 4061 IceGrid.Node.Name=node1 IceGrid.Node.Endpoints=tcp -h 192.168.1.210 IceGrid.Node.Data=/root/iceserver/data/node1 IceGrid.Node.Output=/root/iceserver/data/node1 Ice.StdErr=/root/iceserver/data/node1/stderr.log Ice.StdOut=/root/iceserver/data/node1/stdout.log  启动IceGrid集群 编写集群配置文件: myicegrid.xml CLASSPATH=/usr/java/jdk1.8.0_91/lib/tools.jar;/root/iceserver/lib/* 进入icegridadmin命令行: # icegridadmin -u test -p test --Ice.Default.Locator="MyIceGrid/Locator:tcp -h 192.168.1.210 -p 4061" 载入应用: >>> application add /root/iceserver/rsrc/myicegrid.xml 更新/重新载入: >>> application update /root/iceserver/rsrc/myicegrid.xml 启动服务(启动服务出错,待解决): >>> server start MyServer-1 常用命令: server list 查看启动的服务器 service list MyServer-1 查看MyServer-1上的服务 service describe MyServer-1 HelloWorldServer2 查看MyServer-1下HelloWorldServer2服务的描述 adapter list 查看所有Adapter node list 查看所有node 6 常见问题


网友评论