diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java index 32457e9e00..7b13b9e633 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java @@ -51,7 +51,7 @@ public class RouterChain { public static RouterChain buildChain(DynamicConfiguration dynamicConfiguration, URL url) { RouterChain routerChain = new RouterChain<>(url); - List extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class).getActivateExtension(dynamicConfiguration.getUrl(), (String[]) null); + List extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class).getActivateExtension(url, (String[]) null); List routers = extensionFactories.stream() .map(factory -> { Router router = factory.getRouter(dynamicConfiguration, url); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/Configuration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Configuration.java index 2d76882f06..8380b59e19 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/Configuration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Configuration.java @@ -17,7 +17,7 @@ package org.apache.dubbo.common.config; /** - * + * Configuration interface, to fetch the value for the specified key. */ public interface Configuration { /** @@ -58,6 +58,15 @@ public interface Configuration { */ Object getProperty(String key); + /** + * Gets a property from the configuration. The default value will return if the configuration doesn't contain + * the mapping for the specified key. + * + * @param key property to retrieve + * @param defaultValue default value + * @return the value to which this configuration maps the specified key, or default value if the configuration + * contains no mapping for this key. + */ Object getProperty(String key, Object defaultValue); /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java index 1e9c538596..83a6c7fae1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java @@ -302,10 +302,6 @@ public class ExtensionLoader { return Collections.unmodifiableSet(new TreeSet(cachedInstances.keySet())); } - public Set getLoadedExtensionInstances() { - return Collections.unmodifiableSet(cachedInstances.values().stream().map(Holder::get).collect(Collectors.toSet())); - } - public Object getLoadedAdaptiveExtensionInstances() { return cachedAdaptiveInstance.get(); } @@ -340,6 +336,14 @@ public class ExtensionLoader { return (T) instance; } + /** + * Return all available extension instances. + */ + public Set getExtensions() { + return Collections.unmodifiableSet(getSupportedExtensions().stream().map(this::getExtension) + .collect(Collectors.toSet())); + } + /** * Return default extension, return null if it's not configured. */ diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index e8649f0c4a..b1f72234d2 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -157,7 +157,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { // For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and there's no config center specified explicitly. RegistryConfig registry = registries.get(0); if (registry.isZookeeperProtocol()) { - Set loadedConfigurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances(); + Set loadedConfigurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getExtensions(); // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. if (CollectionUtils.isEmpty(loadedConfigurations)) { ConfigCenterConfig configCenterConfig = new ConfigCenterConfig(); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java index c957f1a31a..0b884ccabe 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java @@ -20,7 +20,6 @@ import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.config.support.Parameter; @@ -31,7 +30,6 @@ import java.io.StringReader; import java.util.HashMap; import java.util.Map; import java.util.Properties; -import java.util.Set; /** * @@ -102,16 +100,11 @@ public class ConfigCenterConfig extends AbstractConfig { // checkConfigCenter(); URL url = toConfigUrl(); - Set loadedConfigurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances(); - if (CollectionUtils.isEmpty(loadedConfigurations)) { - DynamicConfiguration dynamicConfiguration = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getExtension(url.getProtocol()); - // TODO, maybe we need a factory to do this? - dynamicConfiguration.setUrl(url); - dynamicConfiguration.init(); - return dynamicConfiguration; - } - return (DynamicConfiguration) loadedConfigurations.iterator().next(); + DynamicConfiguration dynamicConfiguration = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getExtension(url.getProtocol()); + // TODO, maybe we need a factory to do this? + dynamicConfiguration.initWith(url); + return dynamicConfiguration; } private URL toConfigUrl() { diff --git a/dubbo-configcenter/dubbo-configcenter-api/pom.xml b/dubbo-configcenter/dubbo-configcenter-api/pom.xml index e75fb9e339..68b51ff7dd 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/pom.xml +++ b/dubbo-configcenter/dubbo-configcenter-api/pom.xml @@ -25,7 +25,7 @@ dubbo-configcenter-api jar ${project.artifactId} - The api definition of the service configcenter module + The api definition of the service config-center module false @@ -37,4 +37,4 @@ ${project.parent.version} - \ No newline at end of file + diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfiguration.java index 3411032f30..258ce526ad 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfiguration.java @@ -23,23 +23,36 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** + * Dynamic configuration template class. The concrete implementation needs to provide implementation for three methods. * + * @see AbstractDynamicConfiguration#getTargetConfig(String, String, long) + * @see AbstractDynamicConfiguration#addListener(String, ConfigurationListener) + * @see AbstractDynamicConfiguration#createTargetListener(String, ConfigurationListener) */ -public abstract class AbstractDynamicConfiguration extends AbstractConfiguration implements DynamicConfiguration { - public static final String DEFAULT_GROUP = "dubbo"; +public abstract class AbstractDynamicConfiguration extends AbstractConfiguration + implements DynamicConfiguration { + protected static final String DEFAULT_GROUP = "dubbo"; + protected URL url; - /** - * One key can register multiple target listeners, but one target listener only maps to one configuration listener - */ - private ConcurrentMap> listenerToTargetListenerMap = new ConcurrentHashMap<>(); + + // One key can register multiple target listeners, but one target listener only maps to one configuration listener + private ConcurrentMap> targetListeners = + new ConcurrentHashMap<>(); public AbstractDynamicConfiguration() { } + @Override + public void initWith(URL url) { + this.url = url; + } + @Override public void addListener(String key, ConfigurationListener listener) { - ConcurrentMap listeners = listenerToTargetListenerMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>()); - TargetConfigListener targetListener = listeners.computeIfAbsent(listener, k -> createTargetConfigListener(key, listener)); + ConcurrentMap listeners = targetListeners.computeIfAbsent(key, + k -> new ConcurrentHashMap<>()); + TargetListener targetListener = listeners.computeIfAbsent(listener, + k -> createTargetListener(key, listener)); addTargetListener(key, targetListener); } @@ -60,33 +73,48 @@ public abstract class AbstractDynamicConfiguration extends @Override public String getConfig(String key, String group, ConfigurationListener listener) { - return getConfig(key, group, 0l, listener); + return getConfig(key, group, listener, 0L); } @Override - public String getConfig(String key, String group, long timeout, ConfigurationListener listener) { + public String getConfig(String key, String group, ConfigurationListener listener, long timeout) { try { if (listener != null) { this.addListener(key, listener); } - return getInternalProperty(key, group, timeout); + return getTargetConfig(key, group, timeout); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } - public URL getUrl() { - return url; - } + /** + * Fetch dynamic configuration from backend config storage. If timeout exceeds, exception should be thrown. + * + * @param key property key + * @param group group + * @param timeout timeout + * @return target config value + */ + protected abstract String getTargetConfig(String key, String group, long timeout); - public void setUrl(URL url) { - this.url = url; - } + /** + * Register a native listener to the backend config storage so that Dubbo has chance to get notified when the + * value changes. + * + * @param key property key listener is interested. + * @param listener native listener for the backend config storage + */ + protected abstract void addTargetListener(String key, TargetListener listener); - protected abstract String getInternalProperty(String key, String group, long timeout); - - protected abstract void addTargetListener(String key, TargetConfigListener listener); - - protected abstract TargetConfigListener createTargetConfigListener(String key, ConfigurationListener listener); + /** + * Create a native listener for the backend config storage, eventually ConfigurationListener will get notified once + * the value changes. + * + * @param key property key the native listener will listen on + * @param listener ConfigurationListener instance + * @return native listener for the backend config storage + */ + protected abstract TargetListener createTargetListener(String key, ConfigurationListener listener); } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java index d99d4001dd..403ec755a1 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java @@ -17,7 +17,9 @@ package org.apache.dubbo.configcenter; /** + * Config change event. * + * @see ConfigChangeType */ public class ConfigChangeEvent { private String key; diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java index 00f56f31d9..e810ddce60 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java @@ -17,10 +17,21 @@ package org.apache.dubbo.configcenter; /** - * + * Config change event type */ public enum ConfigChangeType { + /** + * A config is created. + */ ADDED, + + /** + * A config is updated. + */ MODIFIED, + + /** + * A config is deleted. + */ DELETED } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigType.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigType.java index e5ec836b07..d38e39d1e1 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigType.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigType.java @@ -17,9 +17,16 @@ package org.apache.dubbo.configcenter; /** - * + * Config type */ public enum ConfigType { + /** + * For Dubbo dynamic config other than routing rules. + */ CONFIGURATORS, + + /** + * For Dubbo routing rules + */ ROUTERS } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java index 50b2f423ed..bacaa14f85 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java @@ -19,11 +19,18 @@ package org.apache.dubbo.configcenter; import org.apache.dubbo.common.URL; /** - * + * Config listener, will get notified when the config it listens on changes. */ public interface ConfigurationListener { + /** + * Listener call back method. Listener gets notified by this method once there's any change happens on the config + * the listener listens on. + * + * @param event config change event + */ void process(ConfigChangeEvent event); + // FIXME: why we need this? URL getUrl(); } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java index cf57b6729f..ef3e6d6f3e 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java @@ -28,7 +28,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** - * + * Utilities for manipulating configurations from different sources */ public class ConfigurationUtils { private static final CompositeConfiguration compositeConfiguration; @@ -64,17 +64,16 @@ public class ConfigurationUtils { } /** - * If user opens DynamicConfig, the extension instance must has been created during the initialization of ConfigCenterConfig with the right extension type user specified. - * If no DynamicConfig presents, NopDynamicConfiguration will be used. - * - * @return + * If user opens DynamicConfig, the extension instance must has been created during the initialization of + * ConfigCenterConfig with the right extension type user specified. If no DynamicConfig presents, + * NopDynamicConfiguration will be used. */ public static DynamicConfiguration getDynamicConfiguration() { - Set configurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances(); + Set configurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getExtensions(); if (CollectionUtils.isEmpty(configurations)) { return ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension(); } else { - return (DynamicConfiguration) configurations.iterator().next(); + return configurations.iterator().next(); } } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java index 9a22dddcd4..f60d560b6c 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java @@ -20,7 +20,7 @@ import org.apache.dubbo.common.config.AbstractConfiguration; import org.apache.dubbo.common.config.Configuration; /** - * + * A wrapper to fetch a config for the specific key with the different prefix in the specified order. */ public class ConfigurationWrapper extends AbstractConfiguration { private String application; @@ -36,6 +36,7 @@ public class ConfigurationWrapper extends AbstractConfiguration { this.delegate = configuration; } + // FIXME: I think the order is wrong, service.method.key go first, then service.key, and then application.key @Override protected Object getInternalProperty(String key) { Object value = delegate.getProperty(application + "." + key); diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java index 7adcc47cc5..83faee634b 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java @@ -21,27 +21,72 @@ import org.apache.dubbo.common.config.Configuration; import org.apache.dubbo.common.extension.SPI; /** - * + * Dynamic configuration */ @SPI("nop") public interface DynamicConfiguration extends Configuration { - void init(); - - URL getUrl(); - - void setUrl(URL url); + /** + * Init dynamic configuration from URL + * + * @param url the url in which info for initializing dynamic configuration is contained. + */ + void initWith(URL url); + /** + * Register a configuration listener for a specified key + * + * @param key the key to represent a configuration + * @param listener configuration listener + */ void addListener(String key, ConfigurationListener listener); + /** + * Get the configuration mapped to the given key + * + * @param key property key + * @return target configuration mapped to the given key + */ String getConfig(String key); + /** + * Get the configuration mapped to the given key and the given group + * + * @param key property key + * @param group group + * @return target configuration mapped to the given key and the given group + */ String getConfig(String key, String group); + /** + * Get the configuration mapped to the given key, and notify the passed-in listener + * + * @param key property key + * @param listener configuration listener + * @return + */ String getConfig(String key, ConfigurationListener listener); - String getConfig(String key, String group, long timeout, ConfigurationListener listener); - + /** + * Get the configuration mapped to the given key and the given group, and notify the passed-in listener + * + * @param key property key + * @param group group + * @param listener configuration listener + * @return target configuration mapped to the given key and the given group + */ String getConfig(String key, String group, ConfigurationListener listener); + /** + * Get the configuration mapped to the given key and the given group, and notify the passed-in listener. If the + * configuration fails to fetch after timeout exceeds, IllegalStateException will be thrown. + * + * @param key property key + * @param group group + * @param listener configuration listener + * @param timeout timeout value for fetching the target config + * @return target configuration mapped to the given key and the given group, IllegalStateException will be thrown + * if timeout exceeds. + */ + String getConfig(String key, String group, ConfigurationListener listener, long timeout); } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java index f506935ce9..1dc0794f72 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java @@ -21,28 +21,23 @@ import org.apache.dubbo.configcenter.ConfigurationListener; import org.apache.dubbo.configcenter.DynamicConfiguration; /** - * The default extension of {@link DynamicConfiguration}. - * If user does not specify a config centre, or specifies one that is not a valid extension, it will default to this one. + * The default extension of {@link DynamicConfiguration}. If user does not specify a config centre, or specifies one + * that is not a valid extension, it will default to this one. */ public class NopDynamicConfiguration extends AbstractDynamicConfiguration { @Override - public void init() { - - } - - @Override - protected String getInternalProperty(String key, String group, long timeout) { + protected String getTargetConfig(String key, String group, long timeout) { return null; } @Override protected void addTargetListener(String key, Object o) { - + // no-op } @Override - protected Object createTargetConfigListener(String key, ConfigurationListener listener) { + protected Object createTargetListener(String key, ConfigurationListener listener) { return null; } diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java index f3f392d394..efec2fbf4c 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java @@ -52,7 +52,8 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration configurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances(); - if (CollectionUtils.isEmpty(configurations)) { - dynamicConfiguration = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension(); - } else { - dynamicConfiguration = (DynamicConfiguration) configurations.iterator().next(); - } + dynamicConfiguration = ConfigurationUtils.getDynamicConfiguration(); } public static RegistryProtocol getRegistryProtocol() {