绝想首页

Ice3.3.1 First Connection来自哪里

张洁gp9yaa [苦涩] 2013-03-15 18:19:51 星期五 晴天 查看:152 回复:0 发消息给作者

所有连接的创建工作都由OutgoingConnectionFactory完成
OutgoingConnectionFactory的factory方法为create(EndpointI[] endps,boolean hasMore,EndpointSelectionType selType,CreateConnectionCallback callback)
这是一个异步方法,CreateConnectionCallback为异步的回调对象,连接创建成功后回调该对象。
整个创建过程如下:
    1。调用findConnectionByEndpoint方法,看看对应的Endpoint是否创建好的connection可用,如果可用则马上callback
    2。没有可用connection,创建ConnectCallback对象,ConnectCallback对象负责后继的connection的创建过程
    3。ConnectCallback调用getConnectors()方法,这个方法首先调用_factory.incPendingConnectCount()来计算以免connection还没有创建完成OutgoingConnectionFactory对象就被destory掉。
    接下调用ConnectCallback的nextEndpoint()方法,这个方法迭代出一个Endpoint,然后调用Endpoint的connectors_async()方法
    connectors_async()方法调用EndpointHostResolver.resolve()方法

EndpointHostResolver是一个单独的线程,线程循环如下:
    从resolver队列里面取一个需要resolver的对象出来
    调用Endpoint.connectors()方法
    调用ConnectCallback.connectors()方法
    while(true){
        ResolverEntry resolve = (ResolverEntry)_queue.removeFirst();
        Endpoint endpoint = resolve.endpoint;
        List list = endpoint.connectors(Listaddresses);
        ConnectCallback cb = resolve.callback;
        cb.connectors(list);
    }

这里重点是ConnectCallback的connectors(List cons)方法,这个方法由Resolve线程回调,函数本身迭代cons列表集合,迭代时如果有Endpoint怎继续调用nextEndpoint()方法,如果没有Endpoint则表示迭代完成,这个时候调用getConnection()方法开始尝试获取一个connection
getConnection()方法首先还是委托OutgoingConnectionFactory的getConnection()方法来获取连接,

OutgoingConnectionFactory中的重要数据结构
OutgoingConnectionFactory有下面两个字段:
Map _connections 维护一个ConnectorInfo建立的所有ConnectionI,用于根据ConnectorInfo查找连接
Map _connectionsByEndpoint 维护一个Endpoint建立的所有ConnectionI,用户根据Endpoint查找连接
Map _pending 用户根据ConnectorInfo查找连接,一旦ConnectorInfo的连接建立完成,则回调Set里面的所有对象

OutgoingConnectionFactory的findConnection(List)方法描述
循环迭代List集合{
    如果ConnectorInfo在pending列表中,continue;
    如果_connections map集合中没有,continue;
    迭代_connections map中对应key的value List{
        如果ConnectionI是激活的,则返回ConnectionI

返回null

OutgoingConnectionFactory的getConnection(List connectors,ConnectCallback cb,BooleanHolder compress)方法描述
这个方法根据传进来的connectors参数找到一条对应连接即可。
while(true){
    调用findConnection(List)看看是否有创建好的ConnectionI,找到就返回该ConnectionI
    如果在_pending列表里面有,则说明已经有其他线程在创建连接了,返回null,等连接成功了回调ConnectCallback对象
    如果_pending列表里面没有,则开始调用ConnectorCallback的nextConnector()创建一条连接。
}

ConnectCallback方法的nextConnector()方法委托OutgoingConnectionFactory的createConnection方法开始真正的连接创建工作。
createConnection方法很简单:
实例化一个ConnectionI对象,然后把ConnectionI对象放到_connections和_connectionsByEndpoint集合
然后调用ConnectionI的start方法

现在来讲讲创建连接都有那些回调吧
首先是ConnectRequestHandler,实现了Reference.GetConnectionCallback接口
GetConnectionCallback
setConnection(ConnectionI connection)
setException(LocalException ex)
这个接口的回调是在连接创建好后被callback setConnection

ConnectRequestHandler的connect方法调用_reference.getConnection(GetConnectionCallback callback)去获取连接,如果没有RouterInfo,reference.getConnection方法则继续调用getConnectionNoRouterInfo(GetConnectionCallback callback)方法,这个方法则继续调用createConnection(Endpoint[],GetConnectionCallback callback)方法,这个方法继续把调用委托给OutgoingConnectionFactory的create(Endpoint[],boolean,int,CreateConnectionCallback)方法,现在又看到了一个新的回调接口
CreateConnectionCallback
setConnection(Ice.ConnectionI)
setException(LocalException ex)
这个接口和GetConnectionCallback一模一样,对ConnectRequestHandler他不负责创建接口,所以叫GetConnectionCallback,而OutgoingConnectionCallback负责创建接口,所以叫CreateConnectionCallback。
这里的CreateConnectionCallback接口实现很简单就是调用GetConnectionCallback的对应接口方法,继续OutgoingConnectionFactory的create方法create(EndpointI[] endpts, boolean hasMore,Ice.EndpointSelectionType selType,CreateConnectionCallback callback),这个方法首先findConnectionByEndpoint去找一个连接,找到就马上回调callback,如果没有找到则实例化一个ConnectCallback对象,这个对象又引用了CreateConnectionCallback,就是说ConnectCallback创建完连接后,再回调CreateConnectionCallback.

整个调用栈如下:
ConnectRequestHandler.connect()
    Reference.getConnection(GetConnectionCallback callback)
    Reference.getConnectionNoRouterInfo()
    Reference.createConnection()
        OutgoingConnectionFactory.create()
            ConnectCallback.getConnectors()


一个ObjectPrx对应一个Reference但不对应一条连接,一个Endpoint对应一条连接。
多个ObjectPrx可以对应同一个Reference.

一个ObjectPrxy都有一个Delegate,Delegate也需要一个Setup过程,Delegate都有一个RequestHandler对象,RequestHandler则启动链接的创建,具体从Reference.getConnection()函数开始。
Reference.getConnection函数被重载为下面两个函数:
getConnection(boolean comp);
getConnection(GetConnectionCallback callback);
从这两个函数开始,产生了2个分支来创建一条链接
分支一:getConnection(boolean comp);==>createConnection(EndpointI[] allEndpoints,boolean comp);==>(Connection|返回值)OutgoingConnectionFactory.create(EndpointI[] endpts, boolean hasMore,Ice.EndpointSelectionType selType, Ice.BooleanHolder compress)
这条分支创建连接是阻塞的。
分支二:getConnection(GetConnectionCallback callback);==>createConnection(EndpointI[] allEndpoints,GetConnectionCallback callback);==>(void)OutgoingConnectionFactory.create(EndpointI[] endpts, boolean hasMore,Ice.EndpointSelectionType selType, CreateConnectionCallback callback);
这条分支创建连接是非阻塞的,所以需要Callback

但2个分支在创建连接时都会先看看本地有没有对特定的Endpoint已经建立好的连接,如果有的话,则不管你是否设置了CacheConnection都会然会已经建立好的连接,不会去重新创建。
建立好的连接是存放在以Endpoint为key的HashMap里面,所以如果想每次都去创建新的连接的一个技巧就是改变Endpoint,Endpoint的hashcode函数被override,修改Endpoint的connectionId属性就会影响
hashcode值。

顶一下(33 写日记 1219987 234757
分享排行

 

 

留住已经逝去的峥嵘岁月 记住曾经绽现的万种风情 在记忆即将淡漠的时候 来把这些重新回味

Copyright (C) 2008-2014 www.juexiang.com, All Rights Reserved.

京ICP备2023001011号-3   京公网安备11010802011908号

客服QQ 1017160561 违法和不良信息举报电话 13148464312 邮箱 1017160561@qq.com