Skip to content

dubbo2.7.5中多注册中心集群选址策略,只有preferred有效 #5654

@brucelwl

Description

@brucelwl

dubbo2.7.5中新增了4种多注册中心选址策略,分别为preferred,zone,weight,任意可用,

但是目前zone,weight是无效的,

原因在于在通过registryUrl创建RegistryDirectory时,会将registryUrl中的参数清楚, 但是仅仅保留了preferred这个参数. 代码见org.apache.dubbo.registry.integration.RegistryDirectory#RegistryDirectory,
该方法调用 turnRegistryUrlToConsumerUrl(url);将registryUrl做了转换,导致丢失了zone,weight两个参数

public RegistryDirectory(Class<T> serviceType, URL url) {
        super(url);
        if (serviceType == null) {
            throw new IllegalArgumentException("service type is null.");
        }
        if (url.getServiceKey() == null || url.getServiceKey().length() == 0) {
            throw new IllegalArgumentException("registry serviceKey is null.");
        }
        this.serviceType = serviceType;
        this.serviceKey = url.getServiceKey();
        this.queryMap = StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY));
        //注意: 这里将registryUrl做了转换
        this.overrideDirectoryUrl = this.directoryUrl = turnRegistryUrlToConsumerUrl(url);
        String group = directoryUrl.getParameter(GROUP_KEY, "");
        this.multiGroup = group != null && (ANY_VALUE.equals(group) || group.contains(","));
    }

org.apache.dubbo.registry.integration.RegistryDirectory#turnRegistryUrlToConsumerUrl
该方法中只保留了PREFERRED_KEY即preferred这个参数,并设置前缀registry,但是丢失了zone,weight,导致这两个选址策略无效

private URL turnRegistryUrlToConsumerUrl(URL url) {
        // save any parameter in registry that will be useful to the new url.
        String isDefault = url.getParameter(PREFERRED_KEY);
        if (StringUtils.isNotEmpty(isDefault)) {
            queryMap.put(REGISTRY_KEY + "." + PREFERRED_KEY, isDefault);
        }
        return URLBuilder.from(url)
                .setPath(url.getServiceInterface())
                .clearParameters()
                .addParameters(queryMap)
                .removeParameter(MONITOR_KEY)
                .build();
    }

解决方案
方案1: 在turnRegistryUrlToConsumerUrl方法中,按照和preferred同样的方式,将zone,weight,添加上,
**方案缺点: ** 如果后期有更多关于注册中心的参数都可能需要这么做,容易忘记编码

方案2:(建议方式) 在turnRegistryUrlToConsumerUrl方法中,保留所有的RegistryConfig参数,并设置registry参数
**方案缺点: ** parameter参数多几个字段而已,无伤大雅

方案3: 在org.apache.dubbo.registry.integration.RegistryDirectory#RegistryDirectory类中,保存取原始的registryUrl, 即可获取RegistryConfig中的所有参数,
**方案缺点: **需要修改的类和方法比较多.
大致需要修改如下:
RegistryDirectory 添加成员变量,保存原始registryUrl
org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker 添加返回directory的方法
ZoneAwareClusterInvoker 中判断去除前缀

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions