ICE使用总结

客户端的slice-to-c++映射

slice标识符会映射到相同的c++标识符,如果一个slice的标识符与某个c++关键字一样,那么对应的c++
标识符会加上前缀  _cpp_


命名空间的映射是一样的


接口映射:

    要调用一个远地操作,要调用本地类实例的成员函数,这个实例代表的是远地的对象。
	这使得映射变得容易,使用也直观。
	
	举例:
	
	interface Simple {
         void op();
    };
	
	例如上述slice接口,映射到c++
	
	namespace IceProxy {
         class Simple : public virtual IceProxy::Ice::Object {
         public:
          void op();
          void op(const Ice::Context &);
          // ...
                                                             };
                        }
						
	typedef IceInternal::ProxyHandle<IceProxy::Simple> SimplePrx;
	
	如上所示,上述slice生成一个类simple和一个类代理SimplePrx
	
    c++程序会一般直接使用这个代理句柄,而不会使用这个类
	
操作的映射
	
	
    对于接口的每一个操作,代理类都有一个对应的同名成员函数,要调用某一个操作,
    要通过代理句柄调用它。

    例如,对于接口:

    module Filesystem {
       interface Node {
            nonmutating string name();
                      };
                       // ...
                      }; 	

    生成如下代理:
        
		
    namespace IceProxy {
        namespace Filesystem {
             class Node : virtual public IceProxy::Ice::Object {
        public:
             std::string name();
             // ...
                       };
					  
				
        typedef IceInternal::ProxyHandle<Node> NodePrx;


         // ...
                      }
         // ...
                       }
					   
	    最终的调用方法是:
		
		NodePrx node = ...;      //initiallize proxy
		string name = node->name();   // Get name via rpc
	
	    操作分为普通的,idempotent和nonmutating操作
		
		idempotent表示安全的对数据进行多次修改
		
		nonmutating表示对数据不做任何修改
		
		
传递参数:
    
	slice的出入参数通过值和const引用
	
	传出参数通过引用
	
类映射:

    例如如下类:
	
	    class TimeOfDay {
             short hour; // 0 - 23
             short minute; // 0 - 59
             short second; // 0 -59
             string format(); // Return time as hh:mm:ss
                        };
    
	    最终生成的代码:
		
		    class TimeOfDay : virtual public Ice::Object {
            public:
               Ice::Short hour;
               Ice::Short minute;
               Ice::Short second;
               virtual std::string format() = 0;
               virtual bool ice_isA(const std::string &);
               virtual const std::string & ice_id();
               static const std::string & ice_staticId();
               static const Ice::ObjectFactoryPtr & ice_factory();
			};
			typedef IceInternal::Handle<TimeOfDay> TimeOfDayPtr;
	
    类操作:

        在生成的类中,类上的操作被映射到纯虚函数,这意味着,如果类
		函数操作,必须从生成的类派生一个类
		
		例如:
		
		class TimeOfDayI : virtual public TimeOfDay {
            public:
            virtual std::string format() {
            std::ostringstream s;
            s << setw(2) << setfill('0') << hour;
            s << setw(2) << setfill('0') << minute;
            s << setw(2) << setfill('0') << second;
            return s.c_str();
                                        }
                                                    };
    类工厂:
	
	    对于接口
		
		    interface Time {
                 TimeOfDay get();
                           };
		需要告知ice要怎么实例化TimeOfDay,就需要一个工厂,
		
        我们必须向Ice run time 提供一个工厂,这个工厂知道TimeOfDay 抽象类
		有一个TimeOfDayI 具体实现。Ice::Communicator 接口为我们提供了所需的操作
        		
	    具体的代码如下:
		
		Ice::CommunicatorPtr ic = ...;
        ic->addObjectFactory(new ObjectFactory, "::TimeOfDay");
		
	类的智能指针:

        对于Slice类<class-name>,编译器会生成叫作<class-name>Ptr 的C++ 智能
        指针。		

服务端的slice-to-c++映射

Ice run time 的主要进入点是本地接口 Ice::Communicator来表示。

第一步要调用 Ice::initialize初始化,同理在离开main函数的时候,需要调用destory

上述的ICE初始化方法可以用Ice::Application类来替代

示例代码

int main(int argc,char* argv[])
{
    int status = 0;
	Ice::CommunicatorPtr ic;
	try{
	    ic = Ice::initialize(argc.argv);
	}
	catch(const Ice::Exception &e)
	{
	    cerr<< e <<endl;
		status = 1;
	}
	...
}

 
Ice::Service类

   
骨架类:

    在客户端,接口映射到代理类,在服务器端,接口映射到骨架类
	
    module Filesystem{
        interface Node
	    {
	        nonmutating string name();
	    };
    };
	
	编译器为这个接口生成这样的定义:
	
	namespace Filesystem
	{
	    class Node : virtual public Ice::Object {
            public:
                virtual std::string name(const Ice::Current & =
                Ice::Current()) const = 0;
         // ...
                                                };
	}

  • 和客户端一样,Slice 模块映射到名字相同的C++ 名字空间,所以骨架类
  • 定义会放在名字空间Filesystem 中。
  • 骨架类的名字与Slice 接口的名字(Node)相同。
  • 对于Slice 接口中的每个操作,骨架类都有一个对应的纯虚成员函数。
  • 骨架类是抽象基类,因为它的成员函数是纯虚函数。
  • 骨架类继承自Ice::Object (这个类形成了Ice 对象层次的根)。
  
Servant类

    要给Ice对象提供实现,必须创建servant类,继承对应的骨架类,
	例如,为Node接口创建servant
	
	class NodeI : public virtual Filesystem::Node
	{
	public:
	    NodeI(const std::string &);
		virtual std::string name(const Ice::Current &)const;
	private:
	    std::string _name;
	}
	
	参数传递所遵循的规则和客户端一样
	
对象的体现:

    要实现Ice对象的体现,需要遵循如下步骤:

    1.实例化servant类

    2. 为这个servant 所体现的Ice 对象创建标识。
	
    3. 向Ice run time 告知这个servant 的存在。
	
    4. 把这个对象的代理传给客户,以让客户访问它。	
		
实例化servant
    
    	NodePtr servant = new NodeI("Fred");

        或者:
        
        typedef IceUtil::Handle<NodeI> NodeIPtr;
        NodeIPtr servant = new NodeI("Fred");	
		
创建标识:

        每一个ICE对象都需要一个标识,在使用同一个对象的所有
	    servant中,该标识是唯一的。
	    
		Module Ice
		{
		    struct Identity
			{
			    string name;
				string category;
			}
		}
		
		示例:
		
		Ice::Identity id;
		id.name = "Fred";
		
激活Servant

    只要显式的把servant告知对象适配器之后,Ice run time 才会知道这个servant的存在
	
	要激活servant,要调用对象适配器的add操作,
	
	_adapter->add(servant,id);
	
	
举例:

    void activeServant(const string & name)
	{
	    NodePtr servant = new NodeI(name);   //Recount = 1;
		Ice::Identity id;
		id.name = name;
		_adapter->add(servant,id);
	}

用UUID做标识符

    用uuid做标识符可以保证唯一性

    _adapter->addWithUUID(servant);

创建代理:

    	
    一旦激活Ice的servant,服务器就可以处理针对这个对象的请求了。
	但是,只有拥有了对象的代理,客户才能访问该对象。
	
	对象适配器含有创建代理所需的全部详细信息,寻址信息和协议信息,
	还有对象标识。Ice run  time 提供几种创建代理的途径,一经创建,
	可以将代理当做返回值或者操作调用的out参数传给客户。
	
	代理与Servant激活
	
	有两种方法获取代理 直连和通过icegrid
	
	    对象适配器的add和addwithuuid servant激活操作会返回对应的
		Ice对象的一个代理,示例:
		
		typedef IceUtil::Handle<NodeI> NodeIPtr;
		
		NodeIPtr servant = new NodeI(name);
		
		NodeIPtr proxy = NodeIPtr::uncheckedCast(_adapter->addWithUUID(servant));
		
	直接代理创建:
	
	Ice::Identity  id;
	id.name = IceUtil::generateUUID();
	
	objectPrx o = _adapter->createProxy(id);
	
	
	
Ice属性与配置

    
	需要设置 ICE_CONFIG环境变量
	
	
c++线程与并发

    Ice线程库提供了一下与线程有关的抽象:
	
	1)互斥体
	2)递归互斥体
	3)读写递归互斥体
	4)监控器
	5)一个线程抽象,容许你创建、控制、销毁线程
	
互斥体:

    IceUtil::Mutex类和IceUtil::staticMutex提供了简单的非递归互斥机制
	
递归体:

    RecMutex;

读写互斥体		
    
	readlock和writeLock
	
定时锁:

   为读写锁提供一个超时操作
   
监控器:

    Monitor是临界保护区的同步机制,相当于condition机制
	
Ice Run Time详解

    Ice::Communicator监控的资源:
	
	    1)客户端线程池
		2)服务端线程池
		3)配置属性
		4)对象工厂
		5)日志记录器对象
		6)统计对象
		7)缺省路由器
		8)缺省定位器
		9)插件管理器
		10)对象适配器
		
通信器的操作:
	
	    1)proxyToString
		2)stringToProxy
		
	    这两个操作允许你把dialing转换成串化表示,或者进行反向转换
	
	    1)createObjectAdapter
		2) createObjectAdapterWithEndpoints
		
		这两个操作创建新的对象适配器,没个对象适配器都与一个或多个
		传输端点关联在一起。
	    createObjectAdapter 从配置文件读如主机名端口号信息
		而createObjectAdapterWithEndpoints需要用户自己指定
		
适配器状态:
	
	    适配器具有如下几个状态:
		
		1)扣留状态:
		    
			适配器任何到来的请求都会被扣留
		
		2)活动状态:
		
		    这种状态的适配器会接受新到来的请求
			
		3)不活动状态:
		
		    已经处理的请求继续,但不接受新的请求
			

对象标识
    
	module Ice{
	    struct Identity{
		     string name;
			 string category;
		}
	}
	
	这个标识可以唯一的确定servants
	
Ice::current对象

    通过访问Current对象,可以访问"正在执行的请求"和"服务器中操作的实现"等操作,
	包括:
	
	当前请求的对象适配器
	
	当前请求的对象标识
	
	请求的facet
	
	正在被调用的操作的名字
	
	成员含有的操作的调用模式(Normal,Idempotent、Nonmutating)
	
Servant定位器

    略

Ice::Context

    module Ice{
	    local dictionary<string,string> Context;
	}		
    
	上下文就是把一个串映射带串的词典。

调用超时:

    客户发出的远程调用是同步和阻塞的,也就是说客户端调用完成的
	条件是服务器处理完该调用,如果想要迫使它终止,可以调用
	ice_timeout操作
	举例来说
	
	Filesystem::FilePrx myFile = ...;
    FileSystem::FilePrx timeoutFile
    = FileSystem::FilePrx::uncheckedCast(
    myFile->ice_timeout(5000));
    try {
            Lines text = timeoutFile->read(); // Read with timeout
        } catch(const Ice::TimeoutException &) {
    cerr << "invocation timed out" << endl;
                                                }
        Lines text = myFile->read(); // Read without timeout
		
	如果通过timeoutFile调用read函数,5秒后没有反馈就是收到异常
	
单向调用:


ICEPack

    IcePack提供了若干基本的服务,可以简化复杂的分布式应用和部署
	
	    1)定位服务器,用于定位对象和保证位置的透明性
	    2)服务器激活和监控服务,用于管理服务器进程
	    3)服务器部署机制
	
	    4)IcePack注册表,用于管理部署在特定域中的应用的所有相关信息
		
	    5)IcePack节点,用于激活和监控服务器的进程
	
	绑定:
	    
		绑定是把代理和它的servant连接起来的过程
		
		有两种绑定方法,直接绑定和间接绑定
		
		直接绑定:
		
		    调用createObjectAdapterWithEndpoints
			
			或createObjectAdapter
			
		间接绑定:
		
		    客户不需要为代理指定端点信息,代理端点可以由
			Ice run  time 动态确定
			
	部署:

        应用部署包含配置文件的创建和安装,icebox的初始化,
        编写脚本处理启动和关闭流程。

Ice定位器设施

IceStorm

    IceStorm,用于实现应用的 发布/订阅

    		
	收集器-----> IceStorm   ------>各个监视器

	消息:
        
        IceStrom的消息是强类型,IceStorm的消息递送使用的是推模式,轮询模式不支持

    主题:
    
        应用要通过订阅某个主题(topic)来表明自己有兴趣接收某些消息
        IceStorm服务器能够订阅任意数量的主题,这些主题是动态创建的,通过
        唯一的名字来区分。

    单向语义:
    
        IceStorm具有单向语义,因此发布者无法接收起订阅者的答复

    成本:

        成本是与消息和链接相关联在一起的,当你在某个主题上发布消息的时候,
        主题会拿与它每个链接相关联的成本与消息成本进行比较,并且只在那些成本
        等于或超过消息成本的链接上传播该消息。

    服务质量:
	
	    Qos IceStrom订阅者可以在订阅时指定Qos参数,IceStorm目前只支持reliablity
		
		设定oneway,一收到消息就发出去,减少了消息因为IceStrom故障而丢失的可能性
		
	    设定batch会把消息放进队列里面,其存放时间可以配置,这增加了消息因为故障而
		丢失的可能性,但是使开销更小
		
    持久:
	
	   IceStorm用于一个数据,里面维护的是关于其 主题和链接信息
	   
	订阅者出错:
	
	    因为IceStorm 消息是采用单向语义递送的, IceStorm 只能检测到连接或
        超时错误。如果在把消息递送给订阅者的过程中, IceStorm 遇到这样的错
        误,该订阅者就会立刻被解除与该消息对应的主题的订阅。
        慢速的订阅者也可能会造成问题。一旦消息发布, IceStorm 会立刻尝试
        递送它们:IceStorm 发布者对象可能会一收到消息就嵌套地调用主题的订
        阅者。因此,如果订阅者消费消息的速度没有发布的速度快,它就可能造
        成IceStorm 中的线程数不断增加。如果线程数到达了线程池的最大尺寸,
        那么就不再能发布新消息了。
	   
	IceStorm接口综述:

        TopicManager:
        
            TopicManager是一个单体对象,充当的是Topic对象的工厂和仓库,接口类型
        如下:
         
        module IceStorm
        {
		    dictonary<string,topic*> TopicDict;
		}			
	    exception TopicExists{
		    string name;
			
		}
        
        exception NoSuchTopic {
            string name;
        };
        interface TopicManager {
        Topic* create(string name) throws TopicExists;
        nonmutating Topic* retrieve(string name) throws NoSuchTopic;
        nonmutating TopicDict retrieveAll();
        };
    
    Topic:
        
        Topic接口表示一个主题,用于配置链接/管理订阅者
        
        module IceStorm{
		    struct LinkInfo
			{
			    Topic* theTopic;
				string name;
				int cost;
			}
		};
        
        sequence<LinInfo> LinkInfoSeq;
		
		dictionary<string,string> Qos;
		
		exception LinkExists{
		    string name;
		}
		
		interface Topic
		{
		    nonmutating string getName();
			nonmutating Object* getPublisher();
			void subscribe(QoS theQos,Object* subscriber);
			
			idempotent void unsubscribe(Object* subscriber);
			
			idempotent void link(Topic* linkTo,int cost)throws LinkExists;
			
			idempotent void unlink(Topic* linkTo) throws NoSuchLink;
			
            nonmutating LinkInfoSeq getLinkInfoSeq();
			
            void destroy();
		}
		
		};
		};
		
实现发布订阅需要的语句:

        struct Measurement{
		    string tower;    //tower id;
			float windSpeed;  //knots;
			short windDirection; //degrees
			float temperature;    //degrees Celsius
		}
		
    interface Monitor
	{
	    void report(Measurement m);
	};
	
收集器的实现:

    1.获取TopicManager的一个代理,这是IceStorm的主要对象
	2.获取Weather主题的一个代理--如果主题不存在,就创建它,否则就获取已有
	  主题的代理。
	3.获取Weather主题的'发布者'的代理,用于发布消息,因此会被窄化成主题接口(Monitor)
	
	4.收集帮报告观测数据
	
	Ice::objectPrx obj = communicator->stringToProxy("IceStorm/TopicManager:tcp -p 9999");
	IceStorm::TopicManagerPrx topicManager = IceStorm::TopicManagerPrx::checkedCast(obj);//获取TopicManager的一个代理,这是IceStorm的主要对象
	IceStorm::TopicPrx topic;    //
	try{
	    
		topic = topicManager->retrieve("Weather");
	}
	catch(const IceStorm::NoSuchTopic&){
	    topic = topicManager->creat("Weather");  //获取主题代理
	}
	
	Ice::ObjectPrx pub = topic->getPublisher();  //获取一个发布者
	
    if (!pub->ice_isDatagram())
        pub = pub->ice_oneway();
    MonitorPrx monitor = MonitorPrx::uncheckedCast(pub); //获取发布者代理并设置QOs参数
	while(true)
	{
	    Measurement m = getMeasurement();   //收集到发布的数据并report
        monitor->report(m);
	}
}

监视器:

    class MonitorI : virtual public Monitor
	{
	public:
	    virtual void report(const Measurement& m,const Ice::Current&)
		{
		    cout<<"Measurement report"<<endl;
			...
		}
	}   //这个可以理解为被调用的函数
	
Ice::objectPrx obj = communicator->stringToProxy("IceStorm/TopicManager:tcp -p 9999");

IceStorm::TopicManagerPrx topicManager = IceStorm::TopicManagerPrx::checkedCast(obj); //
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值