ICE connection问答
hanlray@hotmail.com
Revision: 1.0 Date: 2005/07/31
对于分布式的应用,人们一般都希望把工作集中的应用本身的逻辑上,而不必关心像连接、数据传输格式这样的细节,最好的效果就是可以把它当成一个非分布式的应用来设计编码,由框架或其他技术来处理应用的分布式问题,这样不仅使分布式应用的开发变得简单,同时也提高了应用的灵活性,正符合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就不会起作用了。