对于分布式的应用,人们一般都希望把工作集中的应用本身的逻辑上,而不必关心像连接、数据传输格式这样的细节,最好的效果就是可以把它当成一个非分布式的应用来设计编码,由框架或其他技术来处理应用的分布式问题,这样不仅使分布式应用的开发变得简单,同时也提高了应用的灵活性,正符合Martin Flower所说的:“记住分布式计算机的第一法则:不要分布你的对象”。ICE就是解决这种问题的中间件之一,相比同类技术如CORBA和DCOM,其主要优势在于:
- 简单。易学易用。
- 高效。看其测试数据比CORBA要高不少,更不用说Web Service之流了。
- 开源。代码水平高,值得借鉴。
然而既然牵涉到网络通讯,对网络连接的管理必然是个重要的部分,ICE是怎样管理连接的?下面以问答的方式 作了一些总结,例子当然是ICE版的Hello world,这里暂且只考虑客户端:
Slice: module Demo { interface Hello { nonmutating void sayHello(); idempotent void shutdown(); }; }; Client: Ice::CommunicatorPtr communicator = Ice::initialize(argc, argv); Ice::ObjectPrx base = communicator->stringToProxy(proxy); HelloPrx hello = HelloPrx::checkedCast(base); hello->sayHello();
Q:连接在何时建立?
A:在HelloPrx::checkedCast时。这个函数除了建立连接之外,还会向服务器发送一条消息,消息包含目标接口的ID,这里是字符串::Demo::Hello,若对方是正确的服务器,该转换就成功,否则转换失败。
Q:连接可以重用吗?
A:只要有可能,ICE总会重用存在的连接。事实上,ICE没有对外提供创建新连接的接口,其内部通过一个Connection Factory实现了连接的重用,当然重用是有条件的,当为某个proxy建立连接时,如果某个已存在连接满足下列条件,ICE就会重用连接它:
- 该连接的远程端点匹配proxy的端点之一
- 该连接被创建这个proxy的Communicator创建
- 该连接匹配该proxy的配置。timeout值是个重要的匹配项
Q:当连接意外断开后能自动重连吗?
A:能。事实上这是ICE中operation retry机制的side effect。配置属性Ice.RetryIntervals用来配置当一个操作失败时自动重试的次数和重试的间隔时间,对slice中定义的每个非local方法,生成的proxy代码中都会有一个循环,比如这里的sayHello方法,生成的C++实现是:
void IceProxy::Demo::Hello::sayHello(const ::Ice::Context& __ctx) { int __cnt = 0; while(true) { try { ::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase = __getDelegate(); ::IceDelegate::Demo::Hello* __del = dynamic_cast< ::IceDelegate::Demo::Hello*>(__delBase.get()); __del->sayHello(__ctx); return; } catch(const ::IceInternal::NonRepeatable& __ex) { __handleException(*__ex.get(), __cnt); } catch(const ::Ice::LocalException& __ex) { __handleException(__ex, __cnt); } } }
当连接意外断掉后,__del->sayHello抛出的异常会被第二个catch语句抓住,对该异常的处理会把该Proxy对象内部保存的delegate(类型是::IceDelegate::Ice::Object)指针置0, 这样当循环再次到__getDelegate时,就会重新创建一个delegate,而在创建delegate的过程中就会重新建立连接。对连接次数和连接间隔时间的控制都是在__handleException函数中完成的。
Q:怎么处理长时间不用的连接?
A:如果你希望自动关闭长时间不用的连接来节省资源,可以利用ICE的ACM(Active Connection Management)机制。配置属性Ice.ACM.Client用来设置当一个outgoing连接多长时候没有活动时就关闭它;Ice.ACM.Server用来设置当一个Incoming 连接多长时间没有活动时就关闭它。当然,关闭这样的连接对应用是不会产生影响的,在需要的时候连接会重新建立。ACM对应用是可选的,将那两个属性设置为 0,ACM就不会起作用了。