Dubbo源码解析——connections vs share connection
前言
先说明一下connections
和share connections
的区别,这里先看下connections
的使用方式和官方文档:
1 | <dubbo:reference interface="com.foo.BarService" connections="10" /> |
这种方式可以限制客户端服务使用连接不能超过10个。而默认不配置的情况,就是共享一个连接,但是共享连接存在一个问题,比如两个Invoker
贡献了一个连接,只有Invoker1
关闭的时候是不能直接关闭连接的,只有在两个Invoker
都关闭的时候才可以关闭连接。
connections
这里connections
意味限制连接个数,而share connection
意味共享连接(也可以认为单个连接),后面不再说明。
先看下connections
的实现。入口在DubboProtocol#refer
:
1 | optimizeSerialization(url); |
继续追一下getClients
:
1 | boolean service_share_connect = false; |
先看initClient
:
1 | // sth... |
这里主要是根据是否懒加载创建连接,具体的创建连接的操作这里不细说了。我们可以看到,如果配置了connections
(大于0),则会直接创建connections
个client
,以此来控制客户端的连接数量。
share connection
继续看戏分享链接的地方getSharedClient
,这里说明一下,如果是分享链接,那么clients.length = 1
,只会进行一次循环:
1 | String key = url.getAddress(); |
这里并非是一个Service
使用一个共享连接(因为key
是Provider
的address
),而是一个Consumer
和一个Provider
之间,默认情况下,所有的服务都共享一个连接。举个例子,比如Provider
暴露了DemoService1
、DemoService2
和DemoService3
,Consumer
端引用了这三个服务,这时候三个服务的会共用同一条TCP通道。
这里我最早的理解也是错误的,我最早的理解是,如果Consumer
引用了DemoService1
两次,则两个DemoService1
共用一个连接,DemoService2
和DemoService3
并不能使用DemoService1
的连接。
继续往下看这个ReferenceCountExchangeClient
:
1 | final class ReferenceCountExchangeClient implements ExchangeClient { |
可以看到,这个ReferenceCountExchangeClient
只是包装了一下真正的client
,里面维护了一个refenceCount
是计数,我们之前说过,如果共享连接,那么只有当这个连接的所有使用者都关闭后,才可以关闭这个连接,我们看下其close
方法:
1 | if (refenceCount.decrementAndGet() <= 0) { |
这里就实现了所有使用方都关闭的情况下才关闭连接的功能。继续看下replaceWithLazyClient
,这个方法的功能是将关闭之后的连接变成一个懒加载的client
:
1 | URL lazyUrl = url.addParameter(Constants.LAZY_CONNECT_INITIAL_STATE_KEY, Boolean.FALSE) |
这里就是把ReferenceCountExchangeClient
维护的client
包装成LazyConnectExchangeClient
,这样我们的这个ReferenceCountExchangeClient
其实仍然可以使用,只不过是在发送请求的时候才进行连接。
总结
这么看过来,我们基本可以看到connections
和share connection
的区别:
connections = 5
则5个都是普通连接,关闭的时候全部关闭。而share connection
的情况下,创建一个ReferenceCountExchangeClient
,用以维护使用计数,只有在使用方都关闭的情况下才关闭,且关闭后可以继续使用(懒加载,使用这个client
发送数据的时候才进行connect
操作)。