详细教你如何部署ICE服务(一)

详细教你如何部署ICE服务(一)这系列文章将会一步步教你如何部署一个ICE服务,如果你正在读这篇博客,我想你已经了解了什么是ICE(InternetCommunicationsEngine),以及如何去实现ICE服务,并且了解什么是ICE对象、ICE对象标识符、ICE对象适配器、ICE服务实现servant、ICE通信器等概念,当然如果你连什么是ICE都不知道,我不建议你继续读下去。先说一下ICE的基本组件:(1)

大家好,又见面了,我是你们的朋友全栈君。

这系列文章将会一步步教你如何部署一个ICE服务,如果你正在读这篇博客,我想你已经了解了什么是ICE(Internet Communications Engine)以及如何去实现ICE服务,并且了解什么是ICE对象、ICE对象标识符、ICE对象适配器、ICE服务实现servant、ICE通信器等概念,当然如果你连什么是ICE都不知道,我不建议你继续读下去。

先说一下ICE的基本组件:

(1) Slice工具:将Slice语言定义的接口编译成各种特定语言实现的代码,这属于开发环境的一部分

(2) ICE容器:IceBox、Ice Node、Ice Registry、Ice Grid、Ice Admin等组件,这些是用于部署和管理Ice服务,你可以在你的服务中选择其中的几项使用。

(3)ICE运行库:由ICE实现平台提供的一套API,不同的语言有不同的实现,如java使用的是jar包,c++使用的是.so文件,这套API需要被ICE服务的客户端和服务端调用

以实现底层通信。


我在写这系列博客时使用的开发环境如下:

eclipse 

Ice-3.3.1

jdk-1.6

CentOS release 5.11 (Final)

我们这里实现一个查询雇员信息的服务,用于演示Ice服务的部署方式。

(一)我们先在eclipse中创建一个java项目,并在项目下创建一个名为slice的文件夹,然后使用Ice 的Slice语言定义Ice服务接口 并将文件命名为query.ice,并将文件放入项目中的slice文件夹中

[["java:package:com.yujie.ice"]]
module info{

struct EmployeeInfo{
string name;
int age;
bool isLeave;
double salary;
string remark;
};
	interface QueryEmployee{
	EmployeeInfo query(EmployeeInfo msg);
	};

};

query.ice文件中定义了报名com.yujie.ice并用info进行包隔离最后生成的包名就是com.yujie.ice.info。

文件中定了一个EmployeeInfo结构体作为员工的信息结构体,定义了一个接口QueryEmployee,我们需要在自己的服务端代码中实现这个接口。

(二) 使用Slice工具将query.ice定义的接口 生成java实现的具体代码,我的eclipse已经安装了ICE 编译插件,直接编译这个java项目就可以生成相应的接口客户端和服务端的stub代码。如果你没有安装Slice2java 编译插件你可以使用类似slice2java –output-dir ../src/main/java/  query.ice这样的命令生成代码,前提是你已经设置了ICE相应的环境变量。

编译之后的项目目录如下所示:

详细教你如何部署ICE服务(一)

(三)实现ice服务端代码。

 /**
  * 继承服务端stub代码_QueryEmployeeDisp类 并实现query接口
  * @author yujie.wang
  *
  */
public class QueryEmployeeImpl extends _QueryEmployeeDisp{

	@Override
	public EmployeeInfo query(EmployeeInfo msg, Current __current) {
		// TODO Auto-generated method stub
		EmployeeInfo ei = new EmployeeInfo();
		ei.age = 23;
		ei.name = msg.name;
		ei.isLeave = false;
		ei.salary = 2000.0;
		ei.remark = "he is a good employee";
		return ei;
	}
}

我们这里要实现一个查询雇员信息的服务,返回一个雇员的的信息。

之后我们实现启动ICE服务端的代码,代码如下所示:

/**
 * 实现启动ICE服务端代码
 * @author yujie.wang
 *
 */
public class QueryEmployeeServer {
	public static void main(String [] args){
		int state = 0;
		Ice.Communicator communicator = null;
		try {
			//初始化ice通信器communicator,可以使用args传入一下ice初始化的参数如超时时间,线程池大小等
			communicator = Ice.Util.initialize(args);
			//创建一个名为queryEmployeeAdapter的适配器并且默认使用tcp协议  服务部署在10.4.30.81机器上 服务开启10006监听端口
			Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints("queryEmployeeAdapter","default -p 10006");
			// 创建服务端代码实现servant
			QueryEmployeeImpl servant = new QueryEmployeeImpl();
			// 将servant与ice对象标识符建立映射关系,并添加到ice对象适配器中
			adapter.add(servant, Ice.Util.stringToIdentity("queryServer"));
			// 激活对象适配器
			adapter.activate();
			System.out.println("QueryEmployeeServer adapter activate");
			// 服务在退出之前一直保持监听状态
			communicator.waitForShutdown();
		} catch (Exception e) {
			// TODO: handle exception
			state = 1;
			System.out.println(e);
		} finally{
			if(communicator != null){
				communicator.destroy();
			}
		}
		System.out.println("state: "+ state);
	}
}

(四) 实现客户端代码

/**
 * 实现客户端调用接口代码
 * @author yujie.wang
 *
 */
public class QueryEmployeeClient {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Ice.Communicator communicator = null;
		try {
			//初始化ice通信器communicator,可以使用args传入一下ice初始化的参数如超时时间,线程池大小等
			communicator = Ice.Util.initialize(args);
			// 传入远程服务单元的 ice对象标识符  协议默认tcp 主机 已经服务监听端口
			Ice.ObjectPrx op = communicator.stringToProxy("queryServer:default -h 10.4.30.81 -p 10006");
			// 检查通用客户端代理op 是不是queryServer对象标识符所关联的ice对象的代理
			QueryEmployeePrx qp = QueryEmployeePrxHelper.checkedCast(op);
			if(qp == null){
				throw new Exception("qp == null");
			}
			// 构造传入参数
			EmployeeInfo ei = new EmployeeInfo();
			ei.name = "yujie.wang";
			// 调用接口
			EmployeeInfo result = qp.query(ei);
			if(result == null){
				throw new Exception("result == null");
			}
			// 输出服务端返回结果
			System.out.println(result.remark);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
	}

}

(五) 服务部署

当然你可以直接在eclipse里运行服务端启动ice服务的main方法,但是为了延续后面的服务部署思路,我这里打算将代码打成jar包,通过一个简单的shell脚本来运行这个main方法。

接下来 我们将java项目进行编译,之后将编译后的class代码通过jar -cvf  yujie-ice-test1.jar ./* 命令打成yujie-ice-test1.jar包。

我在服务器上写了一个非常简单的容器IceServer用于启动这个ice服务,该容器的目录结构如下所示:

详细教你如何部署ICE服务(一)

bin目录下面有如下两个文件:

env.sh

#!/bin/sh
if [ -z "$JAVA_HOME" ]; then
        JAVA_HOME="/data/web/jdk"
fi
echo "JAVA_HOME:$JAVA_HOME"
if [ -z "$SERVER_HOME" ]; then
        BIN_DIR=`readlink -f "$0"`
        echo "BIN_DIR:$BIN_DIR"
        BASE_DIR=`dirname "$BIN_DIR"`
        echo "BASE_DIR:$BASE_DIR"
        SERVER_HOME="`cd $BASE_DIR/.. && pwd`"
else 
        echo "SERVER_HOME IS NOT EMPTY"
fi

echo "SERVER_HOME:$SERVER_HOME"

startIceServer.sh

#!/bin/sh
. ./env.sh

APP_HOME=$SERVER_HOME/lib
APP_MAINCLASS=com.yujie.ice.server.QueryEmployeeServer

CLASSPATH=$APP_HOME
echo $CLASSPATH
for i in "$APP_HOME"/*.jar;do CLASSPATH="$CLASSPATH":"$i";done
echo $CLASSPATH
$JAVA_HOME/bin/java -Xms1000M -Xmx1000M -Xmn500M -XX:PermSize=128m -XX:MaxPermSize=256m -cp  $CLASSPATH  $APP_MAINCLASS 

lib目录下面分别是ICE  平台API jar包和我们自己服务的jar包。

现在我们用startIceServer.sh脚本来启动服务端代码

sh startIceserver.sh &

详细教你如何部署ICE服务(一)

最后我们在本地运行客户端调用代码输出如下:

详细教你如何部署ICE服务(一)

(六)该部署方式总结

优点:直接使用服务端main函数启动,没有引入ice其他容器组件,客户端和服务端直接通过tcp建立连接,是一个十分轻量级的服务。

确定:客户端直接写死了服务的Endpoint信息,及其不灵活;服务端部署方式简单粗暴 不易运维,无法实现负载均衡、故障恢复

这种部署方式只是简单粗暴的演示,完全不能作为工业级的部署方案。

下一节我们将实现另一种部署方案,该方案会解决该种部署方式的一些问题。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138731.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月30日 下午10:16
下一篇 2022年5月30日 下午10:16


相关推荐

  • 补码的加减法运算_简述补码减法运算的规则

    补码的加减法运算_简述补码减法运算的规则补码的加减法运算本文内容参考自王达老师的《深入理解计算机网络》一书<中国水利水电出版社>一、补码加法:1、补码的加法运算两个机器数相加的补码可以先通过分别对两个机器数求补码,然后再相加得到,在采用补码形式表示时,进行加法运算可以把符号位和数值位一起进行运算(若符号位有进位,导致了益出,则直接舍弃),结果为两数之和的补码形式。示例1:求两个十进制数的和35+18。首先,规…

    2025年11月12日
    5
  • win10启动文件丢失或损坏如何解决_miflash出现灾难性故障

    win10启动文件丢失或损坏如何解决_miflash出现灾难性故障原本昨天一切正确的电脑,今天打开电脑想新建一个文件夹的时候,竟无法成功,提示【一个意外错误使你无法创建该文件夹。如果你继续受到此错误,可以使用错误代码来搜索有关此问题的帮助。错误0x8000FFFF:灾难性故障】。小编真的是无奈啊,还能怎么办,上网搜索呗,出现的这个问题的磁盘还是之前的机械硬盘,以为已经把磁盘重新格盘,删除分区,重建分区,应该是没有问题了把,结果出现了几次问题都在这个机械硬盘里…

    2026年3月8日
    3
  • 操作系统实验三 进程调度[通俗易懂]

    实验三进程调度一、实验目的1、理解有关进程控制块、进程队列的概念。2、掌握进程优先权调度算法和时间片轮转调度算法的处理逻辑。二、实验内容与基本要求1、设计进程控制块PCB的结构,分别适用于优先权调度算法和时间片轮转调度算法。2、建立进程就绪队列。3、编制两种进程调度算法:优先权调度算法和时间片轮转调度算法。三、实验报告要求1、优先权调度算法和

    2022年4月18日
    100
  • ManagementObject 中WMI的一些参数(Win32_NetworkAdapterConfiguration)

    ManagementObject 中WMI的一些参数(Win32_NetworkAdapterConfiguration)TheWin32_NetworkAdapterConfigurationclasshasthefollowingproperties.ArpAlwaysSourceRouteDatatype:booleanAccesstype:Read-only IfTRUE,TCP/IPtransmitsAddressResolutionProtocol(ARP

    2022年10月2日
    9
  • kotlin的Map集合

    kotlin的Map集合kotlin的Map集合只读Map可变的MapmutableMapOfkotlin的Map分为:只读Map。可变的MutableMap(MutableMap、HashMap、LinkedHashMap)。只读Map意味着我们创建出来的map是不可变的,即我们只能使用无法改变我们map中的数据,我们只能获取集合中的数据而无法对集合中的数据进行新增和修改。/***…

    2022年5月18日
    37
  • k2p openwrt路由部署阿里云aliyun-ddns[通俗易懂]

    k2p openwrt路由部署阿里云aliyun-ddns[通俗易懂]之前一直有想法入手一个NAS,用于存储项目文件、照片及电影。本来想买个群晖218的,可喜的是赶上了星际蜗牛矿难(被骗的人好可怜,感同身受……),闪电下了一个D款的小蜗牛。星际蜗牛矿机安装群晖NAS的过程我就不说了,很简单,有需要的可以参照下面的文章。https://post.smzdm.com/p/adwl92zk/?send_by=8903307869家里的路由器是K2P同学帮刷的open…

    2022年5月23日
    89

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号