Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
brucelwl opened this issue Jan 15, 2020 · 4 comments
Closed

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

brucelwl opened this issue Jan 15, 2020 · 4 comments
Milestone

Comments

@brucelwl
Copy link
Contributor

brucelwl commented Jan 15, 2020

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 中判断去除前缀

@startjava
Copy link

为什么不PR??自己改,然后COMMIT

@brucelwl
Copy link
Contributor Author

为什么不PR??自己改,然后COMMIT

我提出了多种方案, 希望大家选用一个好的,再提交PR, 如果不好提了PR等,很久,结果不被合并,谁有那么多时间

@brucelwl
Copy link
Contributor Author

@chickenlj

@chickenlj
Copy link
Contributor

感谢反馈,我来尝试具体理解一下问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants