基于ICE中间件的RPC通信的设计与实现Word格式.docx
《基于ICE中间件的RPC通信的设计与实现Word格式.docx》由会员分享,可在线阅读,更多相关《基于ICE中间件的RPC通信的设计与实现Word格式.docx(21页珍藏版)》请在冰豆网上搜索。
对于在slice文件中所定义的每个interface都会在框架中生成一个具体的抽象类class,而对于接口中每个操作都会在对应的抽象类中生成一个纯虚函数。
因此服务Servant的实现过程就是去继承此抽象类,然后具体地去实现这些纯虚函数即可。
如上述2-1中的demo.ice编译后生成框架中包含一个对应类RpcMethod:
classRpcMethod:
virtualpublic:
:
Ice:
Object
public:
virtualvoidaddXmlStringRpc(const:
std:
string&
const:
Current&
=:
Current())=0;
……
}
服务Servant的实现即继承上面的抽象类并实现其纯虚函数,具体来说:
classRpcMethodI:
publicRpcMethod{
virtualvoidrpcAddXmlString(const:
xml,const:
current){
//这里面是业务代码,即具体RPC方法的应用逻辑
……..
(2)服务端RPC通信环境的建立:
包括ICE通信器的建立、对象适配器的产生、服务Servant服务的注册等。
服务端RPC通信环境的建立分为如下几个步骤:
1服务端ICE通信器即Ice:
Communicator的建立:
通信器的一个实例是与服务器端一些运行资源关联在一起的,包括服务端线程池、日志记录器、对象适配器等。
②对象适配器即Ice:
ObjectAdapter的创建:
一个通信器可以有一个或多个对象适器,一个对象适配器则可以有一个或多个Servant服务。
它把Ice对象映射到到来请求的servant,并把请求分派给每个servant中的应用代码(也就是说,对象适配器实现了一个向上调用接口,把Iceruntime与服务器中的应用代码连接在一起)。
③Servant服务到对象适配器的注册:
每一个实现了的Servant服务必须注册到对象适配器中才能生效,每个对象适配器都会维护一个叫做活动Servant表的数据结构,活动映射表用于把对象标识映射到servant中,当客户把操作调用发给服务器时,请求的目标是特定的传输端点。
传输端点隐含地标识了请求所针对的对象适配器(因为同一个端点只能绑定到一个对象适配器)。
客户端以发送请求的代理含有对应的对象的标识,客户端runtime会在线路上随调用一起发送这个对象标识。
对象适配器继而使
用这个对象标识、在它的ASM中查找正确的servant,把调用分派给它,如下图所示:
图2-1把请求绑定到正确的Servant
④对象适配器的激活:
使用其active操作,让适配器变成活动状态,一旦activate被调用,Iceruntime就会开始把请求分派给适配器的servants.
上述步骤用代码描述如下:
//ice通信器的建立
Ice:
CommunicatorPtric=Ice:
initialize();
//对象适配器的创建,需要指定适配器的名字、协议(缺省为TCP/IP)、IP地址和端口
ObjectAdapterPtradapter
=ic->
createObjectAdapterWithEndpoints("
SimplePrinterAdapter"
"
default-p10000"
);
//实例化一个RpcMethodI对象,为我们的RpcMethod接口创建一个servant
ObjectPtrobject=newRpcMethodI;
//这里我调用适配器的add,告诉它有了一个新的servant;
传给add的参数是我们刚才实例化的//servant,再加上一个标识符。
在这里,"
SimpleRpcMethod1"
串是servant的名字(如果我们有
//多个servant,每个servant都可以有不同的名字,更正确的说法是,都有不同的对象标识)。
adapter->
add(object,ic->
stringToIdentity("
SimpleRpcMethod1"
));
//调用适配器的activate方法激活适配器,适配器在创建时是处于扣留状态(holding),一旦适配器被
//激活,服务器就会开始处理来自客户的请求。
activate();
//这个操作挂起发出调用的线程,直到通信器关闭为止(也就是说,直到在服务器中不再有操作在执行为止)。
这//样,你可以在销毁通信器之前,等待服务器空闲下来
ic->
waitForShutdown();
2.2.2服务器端类设计
(1)框架类:
这个类关键在于用slice语言定义好接口,然后用编译器生成对应的框架文件。
(2)服务实现类:
继承框架类中的抽象类,然后实现其纯虚方法,写具体的应用逻辑。
(3)服务端RpcServer类:
用ICE提供的API自己封装一个通用RpcServer类,使得各个模块能重用此代码。
(4)服务端RPC启动逻辑:
此部分使用RpcServer类建立好通信环境,并将
(2)中的服务实现类绑定到适配器,等待客户端请求到来。
附:
(RpcServer类设计)
#ifndefRPC_SERVER_H
#defineRPC_SERVER_H
#include<
Ice/Ice.h>
usingnamespacestd;
/************************************************************************/
/*用ICE提供的API自己封装一个通用RpcServer类,使得各个模块能重用此代码*/
classRpcServer{
private:
//ICE通信器
CommunicatorPtric;
//IC服务端的对象适配器
ObjectAdapterPtradapter;
public:
//初始化RpcServer类,adapaterName表示对象适配器的名字,protocolSocketString是协议(缺省为TCP/IP)、IP地址和端口的串化表示形式
//返回表示初始化环境成功,返回-1表示失败
intinitializeRpcServer(stringadapaterName,stringprotocolSocketString){
try
//初始化通信器
this->
ic=Ice:
//创建对象适配器
adapter=this->
ic->
createObjectAdapterWithEndpoints(adapaterName,protocolSocketString);
}
catch(constIce:
SocketException&
e){
cerr<
<
e<
endl;
cout<
"
[异常:
RpcServer:
initializeRpcServer]出现SocketException,创建对象适配器失败!
return-1;
catch(constIce:
Exception&
e){
cerr<
e<
endl;
initializeRpcServer]抛出异常!
}
return0;
//将具体的Servant服务绑定到对象适配器中,其中servantObject对象指针,而servantObjectName则指定servant在ASM表中的对象标识
//返回表示成功,返回-1表示失败
intbindServices(Ice:
ObjectPtrservantObject,stringservantObjectName){
try{
this->
adapter->
add(servantObject,ic->
stringToIdentity(servantObjectName));
}catch(constIce:
AlreadyRegisteredException&
e){
cerr<
cout<
servantObjectName<
[RpcServer:
bindServices]"
这个servant服务已经在适配器中注册过了!
return-1;
}catch(constIceUtil:
NullHandleException&
bindServices]使用了没有创建成功的对象适配器指针,抛出空异常!
Exception&
e)
{
bindServices]抛出异常!
}
return0;
//将对象适配器激活,即启动server,这里服务器开始接收客户端请求,成功则返回,失败则返回-1
intstartServer(){
try{
}catch(constIceUtil:
startServer]使用了没有创建成功的对象适配器指针,抛出空异常!
}catch(constIce:
startServer]抛出异常!
//销毁通信器,关闭server
voidstopServer(){
if(ic){
try{
ic->
destroy();
}catch(constIce:
cerr<
stopServer]抛出异常!
};
#endif
2.3客户端设计
2.3.1客户端功能设计
(1)客户端RPC通信的建立:
客户端RPC通信环境的建立分为如下几个步骤:
①客户端ICE通信器即Ice:
通信器的一个实例是与客户器端一些运行资源关联在一起的,包括客户端线程池等。
②获取远地Servant的代理:
使用通信器的stringToProxy创建一个代理,所用的参数是“SimpleRpcMethod1:
default–h192.168.1.6–p10000”,这个串包含的是远地Servant的对象标识、通信协议(默认default为TCP/IP)、服务器IP地址和端口。
(2)客户端调用逻辑:
直接使用远地代理直接调用远程方法即可。
2.3.2客户端类设计
(1)存根类:
这个类和服务器端框架类是一样的,关键在于用slice语言定义好接口,然后用编译器生成对应的存根文件。
(2)客户端RpcClient类:
用ICE提供的API自己封装一个通用RpcClient类,使得各个模块能重用此代码。
(3)客户端调用逻辑:
先有RpcFactory类,其中对每个远地方法定义一个静态方法,如
staticvoidrpc_add_xml_string(stringxml,InternetAddressaddress){……..}
在应用逻辑上,直接使用RpcFactory:
rpc_add_xml_string(xml,address)即可。
(RpcClient类设计)
#ifndef__RpcClient_h_
#define__RpcClient_h_
/*用ICE提供的API自己封装一个通用RpcClient类,使得各个模块能重用此代码*/
classRpcClient{
//客户端访问servant的代理总基类
ObjectPrxbase;
//初始化客户端ICE通信环境,成功返回,失败返回-1
intinitializeRpcClient(stringserverAddPro){
//根据提供的servant服务的端点及对象标识来获取客户端总代理
base=ic->
stringToProxy(serverAddPro);
}catch(constIce:
ex){
ex<
RpcClient:
initializeRpcClient]:
抛出异常!
//获得客户端总代理
ObjectPrxgetBase(){
returnthis->
base;
3、系统中RPC远程接口的设计与实现
3.1前端操作显示与后端调度服务软件之间接口
3.1.1传送完整计算拓扑(同步RPC)
接口基本描述:
接口名称
接口表示
接口简述
来源
目的地
传送计算
拓扑指令
cmTopologyAllRpc
前端操作显示软件向后端调度服务软件发送计算拓扑指令
前端操作显示软件
后端调度服务软件
接口详细表示:
voidcmTopologyAllRpc(stringtopologyAllXml)
输入参数:
stringtopologyAllXml:
前端软件生成的计算拓扑文件
返回参数:
无
3.1.2传送完整操作拓扑调度(同步RPC)
传送拓扑
调度指令
cmDeployAllRpc
前端操作显示软件向后端调度服务软件发送计算拓扑调度指令
voidcmDeployAllRpc(stringdeployAllXml)
stringdeployAllXml:
前端软件生成的拓扑调度指令
返回参数:
3.1.3获取全局操作拓扑(同步RPC)
获取全局
拓扑
cmGetTopologyRpc
前端操作显示软件向后端调度服务软件索取全局拓扑
stringcmGetTopologyRpc()
stringtopologyXml:
全局拓扑XML表示
3.1.4获取全局拓扑调度(同步RPC)
拓扑调度
cmGetDeployRpc
前端操作显示软件向后端调度服务软件索取全局拓扑调度
stringcmGetDeployRpc()
stringdeployXml:
全局拓扑调度XML表示
上面的3.1.1-3.1.4操作封装到一个接口HeadServerRpc中,用Slice描述如下:
moduledemo{
interfaceHeadServerRpc{
voidcmTopologyAllRpc(stringtopologyAllXml);
voidcmDeployAllRpc(stringdeployAllXml);
stringcmGetTopologyRpc();
stringcmGetDeployRpc();
3.1.5刷新全局拓扑(同步RPC)
cmTopologyUpdateRpc
后端调度服务软件向前端操作显示软件发送计算拓扑更新指令
voidcmTopologyUpdateRpc(stringtopologyAllXml)
全局拓扑表示
3.1.6刷新全局拓扑调度(同步RPC)
cmDeployUpdateRpc
后端调度服务软件向前端操作显示软件发送拓扑调度更新指令
voidcmDeployUpdateRpc(stringdeployAllXml)
全局拓扑调度表示
上面的3.1.5-3.1.6操作封装到一个接口RegionServerRpc中,用Slice描述如下:
interfaceRegionServerRpc{
voidcmTopologyUpdateRpc(stringtopologyAllXml);
voidcmDeployUpdateRpc(stringdeployAllXml);
3.2后端调度服务软件与订阅管理软件之间接口
3.2.1订阅查询通知
订阅管理软件将新的查询条件发送给集群管理后端调度服务软件。
发送订阅
查询条件
cmSubscribeSql
订阅管理软件向后端调度服务软件发送订阅条件
订阅管理软件
接口详细表示:
voidcmSubscribeSql(TypeEnumoperationType,stringreceiveAddressList,stringsubscribeSql,intflag)
TypeEnumoperationType,操作类型,ADD/DEL/MOD
stringreceiveAddressList,接收端的IP地址列表
Stringsql,订阅SQL
intflag主要用于标识update的SQL
上面的3.2.1操作封装到一个接口HeadServerRpc中,用Slice描述如下:
moduledemo