21.服务分组实现

分析服务分组的test case

我们假设的场景是,多idc机房,一个zk注册中心,我们通过分组设置达到,本机房的consumer调用本机房的provider。为了分析,我们假设了两个idc机房idc001和idc002

provider端的节点1服务配置上加上group:

<dubbo:service interface="com.code260.ss.dubbo.demov.facade.service.HelloService" ref="m00001.app001.xx.helloService"
        group="idc001"/>

节点2的group设置为idc002。

consumer端节点1的ref配置上加上group:

<dubbo:reference id="helloService" interface="com.code260.ss.dubbo.demov.facade.service.HelloService" group="idc001"/>

与provider一样,节点2的group设置为idc002。

我们把case跑起来就能发现group为idc001的消费者调用group为idc001的provider,002的调用002的。

分析分组调用

从上面的case我们可以看出,我们要解决的问题,分组的消费组如何调用到对应分组的provider。

我直接贴下调用栈,这是启动consumer时构造proxy的场景,对于那种后起来的加进来的provider与之类似。

UrlUtils.isMatch(URL, URL) line: 375	
ZookeeperRegistry.toUrlsWithoutEmpty(URL, List<String>) line: 258	
ZookeeperRegistry.toUrlsWithEmpty(URL, String, List<String>) line: 268	
ZookeeperRegistry.doSubscribe(URL, NotifyListener) line: 167	
ZookeeperRegistry(FailbackRegistry).subscribe(URL, NotifyListener) line: 189	
RegistryDirectory<T>.subscribe(URL) line: 133	
RegistryProtocol.doRefer(Cluster, Registry, Class<T>, URL) line: 271	
RegistryProtocol.refer(Class<T>, URL) line: 254	
ProtocolFilterWrapper.refer(Class<T>, URL) line: 60	
ProtocolListenerWrapper.refer(Class<T>, URL) line: 63	
Protocol$Adpative.refer(Class, URL) line: not available	
ReferenceBean<T>(ReferenceConfig<T>).createProxy(Map<String,String>) line: 392

我们在前面 09.消费者如何发现服务 一文中写过,在发现服务时,是靠添加监听器时并拿到children时,获得了provider列表。此处,是接着发现服务后的逻辑继续处理,在ZookeeperRegistry.doSubscribe发现了provider列表后,会通过UrlUtils.isMatch来匹配这个provider是要留下,匹配的字段里就有group,即比较consumer的group和provider是否一致,不一致的就丢弃了。version的机制也是在这里处理。

贴一下 比对的代码:

public static boolean isMatch(URL consumerUrl, URL providerUrl) {
    String consumerInterface = consumerUrl.getServiceInterface();
    String providerInterface = providerUrl.getServiceInterface();
    if( ! (Constants.ANY_VALUE.equals(consumerInterface) || StringUtils.isEquals(consumerInterface, providerInterface)) ) return false;
    
    if (! isMatchCategory(providerUrl.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY), 
            consumerUrl.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY))) {
        return false;
    }
    if (! providerUrl.getParameter(Constants.ENABLED_KEY, true) 
            && ! Constants.ANY_VALUE.equals(consumerUrl.getParameter(Constants.ENABLED_KEY))) {
        return false;
    }
   
    String consumerGroup = consumerUrl.getParameter(Constants.GROUP_KEY);
    String consumerVersion = consumerUrl.getParameter(Constants.VERSION_KEY);
    String consumerClassifier = consumerUrl.getParameter(Constants.CLASSIFIER_KEY, Constants.ANY_VALUE);
    
    String providerGroup = providerUrl.getParameter(Constants.GROUP_KEY);
    String providerVersion = providerUrl.getParameter(Constants.VERSION_KEY);
    String providerClassifier = providerUrl.getParameter(Constants.CLASSIFIER_KEY, Constants.ANY_VALUE);
    return (Constants.ANY_VALUE.equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup))
           && (Constants.ANY_VALUE.equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion))
           && (consumerClassifier == null || Constants.ANY_VALUE.equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier));
}

当然这是分析的单分组的,如果是多分组的即group=”idc001,idc003”这种还有一些其他逻辑处理。