一、什么是ICE?
ICE简介
ICE官网:https://zeroc.com/
Internet Communications Engine,或称Ice,是ZeroC开发的一个面向对象的中间件平台,其实就是一个分布式的RPC框架,进行系统间通信。
ICE的主要优点是高性能,跨语言,跨平台,面向对象,开源等等,提供面向对象的远程过程调用、网格计算和发布/订阅功能,并有基于GPL的双许可协议和一个私有许可协议。
ICE推荐书籍:《ZeroC Ice权威指南》
ICE有哪些优势?
多平台支持
Ice通过与编程语言无关的中立语言Slice(Specification Language froIce)来描述服务的接口,从而达到对象接口与其实现想分离的目的。
性能高
在各个RCP框架的性能对比中ice的tps遥遥领先,而且并发越高tps比其他越高,其次thrift,dubbo和grpc则差了很多。Grpc最差估计跟用了HTTP2有关。
二、安装配置
安装
下载地址:
这里我下载的是3.6版本

配置环境变量
下载安装完成之后要进行环境变量配置。
ICE_HOME = C:\Program Files (x86)\ZeroC\Ice-3.6.5
PATH=%ICE_HOME%\bin


检测是否安装成功:
cmd打开dos窗口: slice2java -v,有版本号说明成功。

三、IDEA下新建ICE文件
pom.xml加入坐标
<dependencies>
<dependency>
<groupId>com.zeroc</groupId>
<artifactId>ice</artifactId>
<version>3.6.5</version>
</dependency>
</dependencies>
新建ice目录和ice文件
1、新建slice文件夹,并标记为源码目录。

然后创建包路径,最后再创建Hello.ice文件

2、安装插件
创建完成后以文件形式打开,会自动提示安装IDEA ice插件

安装插件 Frozen Idea

3、Hello.ice 输入一下内容
[["java:package:com.test.ice.service"]] // 定义java包名 父结构
module demo //模块包名
{
interface Hello //接口服务名称
{
string sayHello(string s); //具体的方法
};
};
四、使用slice2java编译ice文件生成java代码
打开cmd窗口进入Hello.ice目录下执行以下命令:
slice2java .\Hello.ice --output-dir ..\src\main\java
报错:slice2java: error: cannot create directory `..\src\main\java/com': No such file or directory
原因:目标生成的文件路径不对
正确的路径如下:
slice2java .\Hello.ice --output-dir ..\..\..\..\..\java
执行后生成10个文件

五、增加三个类 HelloI Client Server
代码如下:
Hellol.java
package com.test.ice.service.demo;
import Ice.Current;
import java.util.logging.Logger;
public class HelloI extends _HelloDisp {
private static final long serialVersionUID = -3966457693815687559L;
private Logger log = Logger.getLogger(this.getClass().getSimpleName());
public String sayHello(String s, Current __current) {
log.info("具体的服务接口实现类中的sayHello方法被调用了。。。");
return "Hello " + s;
}
}
Client.java
package com.test.ice.service.demo;
import Ice.Communicator;
import Ice.ObjectPrx;
import Ice.Util;
import java.util.logging.Logger;
/**
* @program: IceDemo
* @description:
* @author: Liu Tao
* @create: 2021-10-06 18:38
**/
public class Client {
private static Logger log = Logger.getLogger(Client.class.getSimpleName());
public static void main(String[] args) {
log.info("客户端启动...");
// 通信器
Communicator ic = null;
// 初始化这个通信器
ic = Util.initialize(args);
// 根据地址生成一个服务代理对象
// HelloIce -- 服务端那边自己定义的名字
ObjectPrx proxy = ic.stringToProxy("HelloIce:default -p 1888");
// 转换成HelloService类型的代理服务
HelloPrx hello = HelloPrxHelper.checkedCast(proxy);
//调用方法
String s = hello.sayHello("World!");
System.out.println(">>"+s);
}
}
Server.java
package com.test.ice.service.demo;
import Ice.Communicator;
import Ice.Identity;
import Ice.ObjectAdapter;
import Ice.Util;
import java.util.logging.Logger;
public class Server {
private static Logger log = Logger.getLogger(Server.class.getSimpleName());
public static void main(String[] args) {
// 通信器
Communicator ic = null;
// 初始化这个通信器
ic = Util.initialize(args);
// 创建ice适配器,将服务调用地址和服务映射起来
// "HelloServiceAdapter"是适配器名, "default -p 1888"是服务调用的地址
ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("HelloServiceAdapter","default -p 1888");
// 将服务的具体实现类servant交给这个适配器
Object servant = new HelloI();
// "HelloIce"--服务接口在ice中注册名,转成唯一标识identity
Identity id = Util.stringToIdentity("HelloIce");
adapter.add((Ice.Object) servant, id);
// 激活这个适配器
adapter.activate();
log.info("server服务容器启动成功。。。");
}
}
六、启动程序
先启动server

报错:内部错误 (java.lang.UnsupportedClassVersionError): org/xblackcat/frozenidea/jps/ModelSerializerExtension has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
解决:升级JDK版本为11,重新启动。

再启动Client


以上的代码是同一台电脑之间调用,如果需要跨服务器之间调用,或者无论其他什么语言的客户端调用,只需要获取远程服务代理的时候加上ip即可。default默认采取tcp协议,所以下边的代码其实等同于上边我们调用本地机器的代码。
Ice.ObjectPrx base = ic.stringToProxy("HelloIce:tcp -h 127.0.0.1 -p 10000");
下面是一个更完整的案例代码
client.java
package com.test.ice.service.demo;
import Ice.Communicator;
import Ice.ObjectPrx;
import Ice.Util;
import java.util.logging.Logger;
public class Client {
private static Logger log = Logger.getLogger(Client.class.getSimpleName());
public static void main(String[] args)
{
int status = 0;
// Communicator实例
Communicator ic = null;
try
{
// 调用Ice.Util.Initialize()初始化Ice run time
ic = Util.initialize(args);
// 根据servant的名称以及服务器ip、端口获取远程服务代理
ObjectPrx base = ic.stringToProxy("SimplePrinter:default -p 12121");
// 将上面的代理向下转换成一个Printer接口的代理
HelloPrx hello = HelloPrxHelper.checkedCast(base);
// 如果转换成功
if (hello == null)
{
throw new Error("Invalid proxy");
}
// 调用这个代理,将字符串传给它
String s = hello.sayHello("World!");
System.out.println(s+"<<");
} catch (Ice.LocalException e)
{
e.printStackTrace();
status = 1;
} catch (Exception e)
{
e.printStackTrace();
status = 1;
} finally
{
if (ic != null)
{
ic.destroy();
}
}
System.exit(status);
}
}
Server.java
package com.test.ice.service.demo;
import Ice.Communicator;
import Ice.Identity;
import Ice.ObjectAdapter;
import Ice.Util;
import java.util.logging.Logger;
/**
* @program: IceDemo
* @description:
* @author: Liu Tao
* @create: 2021-10-06 18:40
**/
public class Server {
private static Logger log = Logger.getLogger(Server.class.getSimpleName());
public static void main(String[] args)
{
int status = 0;
// Communicator实例,是ice run time的主句柄
Communicator ic = null;
try
{
// 调用Ice.Util.Initialize()初始化Ice run time
System.out.println("初始化ice run time...");
//args参数可传可不传
ic = Util.initialize(args);
// 创建一个对象适配器,传入适配器名字和在10000端口处接收来的请求
System.out.println("创建对象适配器,监听端口12121...");
ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 12121");
// 实例化一个PrinterI对象,为Printer接口创建一个servant
System.out.println("为接口创建servant...");
Object servant = new HelloI();
// 调用适配器的add,告诉它有一个新的servant,传递的参数是刚才的servant,这里的“SimplePrinter”是Servant的名字
System.out.println("对象适配器加入servant...");
adapter.add((Ice.Object) servant, Util.stringToIdentity("SimplePrinter"));
//调用适配器的activate()方法,激活适配器。被激活后,服务器开始处理来自客户的请求。
System.out.println("激活适配器,服务器等待处理请求...");
adapter.activate();
//这个方法挂起发出调用的线程,直到服务器实现终止为止。或我们自己发出一个调用关闭。
ic.waitForShutdown();
} catch (Ice.LocalException e)
{
e.printStackTrace();
status = 1;
} catch (Exception e)
{
e.printStackTrace();
status = 1;
} finally
{
if (ic != null)
{
ic.destroy();
}
}
System.exit(status);
}
}
评论区