Dubbo源碼解析(三十六)集羣——configurator

集羣——configurator

目標:介紹dubbo中集羣的配置規則,介紹dubbo-cluster下configurator包的源碼。

前言

向註冊中心寫入動態配置覆蓋規則 。該功能一般由監控中心或治理中心的頁面完成。在最新的2.7.0版本中有新的配置規則,我會在後續講解2.7.0新特性的時候提到。這裏仍是根據舊版本中配置規則來說解,能夠參考官方文檔:html

http://dubbo.apache.org/zh-cn...

源碼分析

(一)AbstractConfigurator

該類實現了Configurator接口,是配置規則 抽象類,配置有兩種方式,一種是沒有時添加配置,這種暫時沒有用到,另外一種是覆蓋配置。java

1.configure

@Override
public URL configure(URL url) {
    if (configuratorUrl == null || configuratorUrl.getHost() == null
            || url == null || url.getHost() == null) {
        return url;
    }
    // If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
    // 若是覆蓋url具備端口,則表示它是提供者地址。咱們但願使用此覆蓋URL控制特定提供程序,它能夠在提供端生效 也能夠在消費端生效。
    if (configuratorUrl.getPort() != 0) {
        if (url.getPort() == configuratorUrl.getPort()) {
            return configureIfMatch(url.getHost(), url);
        }
    } else {// override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0
        // 1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore;
        // 2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider
        // 配置規則,URL 沒有端口,意味着override 輸入消費端地址 或者 0.0.0.0
        if (url.getParameter(Constants.SIDE_KEY, Constants.PROVIDER).equals(Constants.CONSUMER)) {
            // 若是它是一個消費者ip地址,目的是控制一個特定的消費者實例,它必須在消費者一方生效,任何提供者收到這個覆蓋url應該忽略;
            return configureIfMatch(NetUtils.getLocalHost(), url);// NetUtils.getLocalHost is the ip address consumer registered to registry.
        } else if (url.getParameter(Constants.SIDE_KEY, Constants.CONSUMER).equals(Constants.PROVIDER)) {
            // 若是ip爲0.0.0.0,則此覆蓋url能夠在使用者上使用,也能夠在提供者上使用
            return configureIfMatch(Constants.ANYHOST_VALUE, url);// take effect on all providers, so address must be 0.0.0.0, otherwise it won't flow to this if branch
        }
    }
    return url;
}

該方法是規則配置到URL中,可是關鍵邏輯在configureIfMatch方法中。git

2.configureIfMatch

private URL configureIfMatch(String host, URL url) {
    // 匹配 Host
    if (Constants.ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) {
        String configApplication = configuratorUrl.getParameter(Constants.APPLICATION_KEY,
                configuratorUrl.getUsername());
        String currentApplication = url.getParameter(Constants.APPLICATION_KEY, url.getUsername());
        // 匹配 "application"
        if (configApplication == null || Constants.ANY_VALUE.equals(configApplication)
                || configApplication.equals(currentApplication)) {
            Set<String> conditionKeys = new HashSet<String>();
            // 配置 URL 中的條件 KEYS 集合。其中下面四個 KEY ,不算是條件,而是內置屬性。考慮到下面要移除,因此添加到該集合中。
            conditionKeys.add(Constants.CATEGORY_KEY);
            conditionKeys.add(Constants.CHECK_KEY);
            conditionKeys.add(Constants.DYNAMIC_KEY);
            conditionKeys.add(Constants.ENABLED_KEY);
            // 判斷傳入的 url 是否匹配配置規則 URL 的條件。
            for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                // 除了 "application" 和 "side" 以外,帶有 `"~"` 開頭的 KEY ,也是條件。
                if (key.startsWith("~") || Constants.APPLICATION_KEY.equals(key) || Constants.SIDE_KEY.equals(key)) {
                    // 添加搭配條件集合
                    conditionKeys.add(key);
                    if (value != null && !Constants.ANY_VALUE.equals(value)
                            && !value.equals(url.getParameter(key.startsWith("~") ? key.substring(1) : key))) {
                        return url;
                    }
                }
            }
            // 移除條件 KEYS 集合,並配置到 URL 中
            return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
        }
    }
    return url;
}

該方法是當條件匹配時,纔對url進行配置。github

3.compareTo

@Override
public int compareTo(Configurator o) {
    if (o == null) {
        return -1;
    }

    // // host 升序
    int ipCompare = getUrl().getHost().compareTo(o.getUrl().getHost());
    // 若是host相同,則根據priority降序來對比
    if (ipCompare == 0) {//host is the same, sort by priority
        int i = getUrl().getParameter(Constants.PRIORITY_KEY, 0),
                j = o.getUrl().getParameter(Constants.PRIORITY_KEY, 0);
        return i < j ? -1 : (i == j ? 0 : 1);
    } else {
        return ipCompare;
    }


}

這是配置的排序策略。先根據host升序,若是相同,再經過priority降序。apache

(二)AbsentConfigurator

public class AbsentConfigurator extends AbstractConfigurator {

    public AbsentConfigurator(URL url) {
        super(url);
    }

    @Override
    public URL doConfigure(URL currentUrl, URL configUrl) {
        // 當不存在時添加
        return currentUrl.addParametersIfAbsent(configUrl.getParameters());
    }

}

該配置方式就是當配置不存在的時候添加。app

(三)AbsentConfiguratorFactory

public class AbsentConfiguratorFactory implements ConfiguratorFactory {

    @Override
    public Configurator getConfigurator(URL url) {
        // 建立一個AbsentConfigurator。
        return new AbsentConfigurator(url);
    }

}

該類是不存在時添加配置的工廠類,用來建立AbsentConfigurator。ide

(四)OverrideConfigurator

public class OverrideConfigurator extends AbstractConfigurator {

    public OverrideConfigurator(URL url) {
        super(url);
    }

    @Override
    public URL doConfigure(URL currentUrl, URL configUrl) {
        // 覆蓋添加
        return currentUrl.addParameters(configUrl.getParameters());
    }

}

這種是覆蓋添加。是目前在用的配置方式。源碼分析

(五)OverrideConfiguratorFactory

public class OverrideConfiguratorFactory implements ConfiguratorFactory {

    @Override
    public Configurator getConfigurator(URL url) {
        // 建立OverrideConfigurator
        return new OverrideConfigurator(url);
    }

}

該類是OverrideConfigurator的工廠類,用來提供OverrideConfigurator實例。this

後記

該部分相關的源碼解析地址: https://github.com/CrazyHZM/i...

該文章講解了集羣中關於configurator實現的部分,講了兩種配置方式,分別是不存在再添加和覆蓋添加。接下來我將開始對集羣模塊關於Directory部分進行講解。url

相關文章
相關標籤/搜索