dubbo原始碼解析(三十六)叢集——configurator
叢集——configurator
目標:介紹dubbo中叢集的配置規則,介紹dubbo-cluster下configurator包的原始碼。
前言
向註冊中心寫入動態配置覆蓋規則 。該功能通常由監控中心或治理中心的頁面完成。在最新的2.7.0版本中有新的配置規則,我會在後續講解2.7.0新特性的時候提到。這裡還是根據舊版本中配置規則來講解,可以參考官方文件:
http://dubbo.apache.org/zh-cn...
原始碼分析
(一)AbstractConfigurator
該類實現了Configurator介面,是配置規則 抽象類,配置有兩種方式,一種是沒有時新增配置,這種暫時沒有用到,另一種是覆蓋配置。
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方法中。
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進行配置。
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降序。
(二)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()); } }
該配置方式就是當配置不存在的時候新增。
(三)AbsentConfiguratorFactory
public class AbsentConfiguratorFactory implements ConfiguratorFactory { @Override public Configurator getConfigurator(URL url) { // 建立一個AbsentConfigurator。 return new AbsentConfigurator(url); } }
該類是不存在時新增配置的工廠類,用來建立AbsentConfigurator。
(四)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例項。
後記
該部分相關的原始碼解析地址:https://github.com/CrazyHZM/i...
該文章講解了叢集中關於configurator實現的部分,講了兩種配置方式,分別是不存在再新增和覆蓋新增。接下來我將開始對叢集模組關於Directory部分進行講解。