From 00b15a44c61f88da69670b6f2f1357736eb8776e Mon Sep 17 00:00:00 2001 From: "ken.lj" Date: Mon, 3 Dec 2018 15:59:52 +0800 Subject: [PATCH] refactor config-center implementation --- .../config/ConfigConditionRouter.java | 37 +++++-------- .../rpc/cluster/router/tag/TagRouter.java | 22 ++++---- .../router/file/FileRouterEngineTest.java | 5 +- .../support/AbstractClusterInvokerTest.java | 5 +- .../wrapper/MockClusterInvokerTest.java | 5 +- .../common/config}/ConfigurationUtils.java | 28 ++++------ .../dubbo/config/ConfigCenterConfig.java | 10 ++-- .../AbstractDynamicConfiguration.java | 32 ++++------- .../AbstractDynamicConfigurationFactory.java | 41 ++++++++++++++ .../configcenter/ConfigurationListener.java | 1 - .../configcenter/ConfigurationWrapper.java | 54 ------------------- .../configcenter/DynamicConfiguration.java | 38 ++----------- ....java => DynamicConfigurationFactory.java} | 22 ++++---- .../support/nop/NopDynamicConfiguration.java | 13 +++++ .../nop/NopDynamicConfigurationFactory.java | 32 +++++++++++ ....configcenter.DynamicConfigurationFactory} | 2 +- .../AbstractDynamicConfigurationTest.java | 47 ++++++++++++++++ .../mock/MockDynamicConfiguration.java | 43 ++++++++++++++- .../mock/MockDynamicConfigurationFactory.java | 32 +++++++++++ ...he.dubbo.configcenter.DynamicConfiguration | 1 - ...o.configcenter.DynamicConfigurationFactory | 1 + .../apollo/ApolloDynamicConfiguration.java | 11 ++-- .../ApolloDynamicConfigurationFactory.java | 31 +++++++++++ ....configcenter.DynamicConfigurationFactory} | 2 +- .../support/zookeeper/CacheListener.java | 10 ++-- .../ZookeeperDynamicConfiguration.java | 38 +++++++------ .../ZookeeperDynamicConfigurationFactory.java | 31 +++++++++++ ....configcenter.DynamicConfigurationFactory} | 2 +- .../ZookeeperDynamicConfigurationTest.java | 13 ++--- .../dubbo/container/log4j/Log4jContainer.java | 10 ++-- .../integration/RegistryDirectory.java | 47 ++++++++-------- .../integration/RegistryProtocol.java | 46 ++++++++++++---- .../rpc/protocol/dubbo/DubboInvoker.java | 2 +- .../rpc/protocol/dubbo/DubboProtocol.java | 2 +- .../dubbo/DubboInvokerAvilableTest.java | 3 +- .../rpc/protocol/thrift/ThriftProtocol.java | 2 +- 36 files changed, 458 insertions(+), 263 deletions(-) rename {dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter => dubbo-common/src/main/java/org/apache/dubbo/common/config}/ConfigurationUtils.java (67%) create mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java delete mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java rename dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/{ConfigType.java => DynamicConfigurationFactory.java} (80%) create mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java rename dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/{org.apache.dubbo.configcenter.DynamicConfiguration => org.apache.dubbo.configcenter.DynamicConfigurationFactory} (84%) create mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.java create mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java delete mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration create mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory create mode 100644 dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationFactory.java rename dubbo-configcenter/dubbo-configcenter-apollo/src/main/resources/META-INF/dubbo/internal/{org.apache.dubbo.configcenter.DynamicConfiguration => org.apache.dubbo.configcenter.DynamicConfigurationFactory} (75%) create mode 100644 dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java rename dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/{org.apache.dubbo.configcenter.DynamicConfiguration => org.apache.dubbo.configcenter.DynamicConfigurationFactory} (68%) diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java index f18254a883..ac4cb97922 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java @@ -21,7 +21,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.configcenter.ConfigChangeEvent; import org.apache.dubbo.configcenter.ConfigChangeType; import org.apache.dubbo.configcenter.ConfigurationListener; @@ -58,33 +57,25 @@ public class ConfigConditionRouter extends AbstractRouter implements Configurati this.configuration = configuration; this.force = false; this.url = url; - try { - String rawRule = this.configuration.getConfig(url.getEncodedServiceKey() + Constants.ROUTERS_SUFFIX, this); - String appRawRule = this.configuration.getConfig(url.getParameter(Constants.APPLICATION_KEY) + Constants.ROUTERS_SUFFIX, this); - if (!StringUtils.isEmpty(rawRule)) { - try { - routerRule = ConditionRuleParser.parse(rawRule); - generateConditions(); - } catch (Exception e) { - logger.error("Failed to parse the raw condition rule and it will not take effect, please check if the condition rule matches with the template, the raw rule is: \n" + rawRule, e); - } - } - if (!StringUtils.isEmpty(appRawRule)) { - try { - appRouterRule = ConditionRuleParser.parse(appRawRule); - generateAppConditions(); - } catch (Exception e) { - logger.error("Failed to parse the raw condition rule and it will not take effect, please check if the condition rule matches with the template, the raw rule is: \n" + appRawRule, e); - } - } - } catch (Exception e) { - throw new IllegalStateException("Failed to init the condition router for service " + url.getServiceKey() + ", application " + url.getParameter(Constants.APPLICATION_KEY), e); + synchronized (this) { + String appKey = url.getParameter(Constants.APPLICATION_KEY) + Constants.ROUTERS_SUFFIX; + configuration.addListener(appKey, this); + String appRawRule = configuration.getConfig(appKey); + if (appRawRule != null) { + this.process(new ConfigChangeEvent(appKey, appRawRule)); + } + String key = url.getEncodedServiceKey() + Constants.ROUTERS_SUFFIX; + configuration.addListener(key, this); + String rawRule = configuration.getConfig(key); + if (rawRule != null) { + this.process(new ConfigChangeEvent(key, rawRule)); + } } } @Override - public void process(ConfigChangeEvent event) { + public synchronized void process(ConfigChangeEvent event) { if (event.getChangeType().equals(ConfigChangeType.DELETED)) { // Now, we can only recognize if it's a app level or service level change by try to match event key. if (event.getKey().endsWith(this.url.getParameter(Constants.APPLICATION_KEY) + Constants.ROUTERS_SUFFIX)) { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java index 8ffd0fbf1c..0370d458a3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java @@ -27,6 +27,7 @@ import org.apache.dubbo.configcenter.ConfigChangeEvent; import org.apache.dubbo.configcenter.ConfigChangeType; import org.apache.dubbo.configcenter.ConfigurationListener; import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcException; @@ -56,7 +57,7 @@ public class TagRouter extends AbstractRouter implements Comparable, Con private TagRouterRule tagRouterRule; private String application; - private AtomicBoolean isInited = new AtomicBoolean(false); + private AtomicBoolean inited = new AtomicBoolean(false); /** * compatible constructor, it should never be called to create TagRouter. @@ -64,7 +65,7 @@ public class TagRouter extends AbstractRouter implements Comparable, Con * @param url */ public TagRouter(URL url) { - this(ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension(), url); + this(ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension().getDynamicConfiguration(url), url); } public TagRouter(DynamicConfiguration configuration, URL url) { @@ -80,24 +81,25 @@ public class TagRouter extends AbstractRouter implements Comparable, Con } private void init() { - if (!isInited.compareAndSet(false, true)) { + if (!inited.compareAndSet(false, true)) { return; } if (StringUtils.isEmpty(application)) { logger.error("TagRouter must getConfig from or subscribe to a specific application, but the application in this TagRouter is not specified."); } - try { - String rawRule = this.configuration.getConfig(application + TAGROUTERRULES_DATAID, this); - if (StringUtils.isNotEmpty(rawRule)) { - this.tagRouterRule = TagRuleParser.parse(rawRule); + + synchronized (this) { + String key = application + TAGROUTERRULES_DATAID; + configuration.addListener(key, this); + String rawRule = configuration.getConfig(key); + if (rawRule != null) { + this.process(new ConfigChangeEvent(key, rawRule)); } - } catch (Exception e) { - logger.error("Failed to parse the raw tag router rule and it will not take effect, please check if the rule matches with the template, the raw rule is:\n ", e); } } @Override - public void process(ConfigChangeEvent event) { + public synchronized void process(ConfigChangeEvent event) { try { if (event.getChangeType().equals(ConfigChangeType.DELETED)) { this.tagRouterRule = null; diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java index 71f28bfd04..5d8db163cd 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java @@ -19,7 +19,7 @@ package org.apache.dubbo.rpc.cluster.router.file; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; @@ -31,6 +31,7 @@ import org.apache.dubbo.rpc.cluster.LoadBalance; import org.apache.dubbo.rpc.cluster.RouterFactory; import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker; + import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -165,7 +166,7 @@ public class FileRouterEngineTest { Map>> methodInvokers = new HashMap<>(); methodInvokers.put("method1", invokers); methodInvokers.put("method2", invokers); - dic.buildRouterChain(methodInvokers, ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension()); + dic.buildRouterChain(methodInvokers, ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension().getDynamicConfiguration(null)); dic.getRouterChain().setResidentRouters(Arrays.asList(routerFactory.getRouter(url))); } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java index b16062a275..af81795099 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java @@ -20,7 +20,7 @@ import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; @@ -34,6 +34,7 @@ import org.apache.dubbo.rpc.cluster.filter.DemoService; import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance; import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance; import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance; + import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -458,7 +459,7 @@ public class AbstractClusterInvokerTest { private void initDic() { Map>> map = new HashMap<>(); map.put("sayHello", invokers); - dic.buildRouterChain(map, ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension()); + dic.buildRouterChain(map, ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension().getDynamicConfiguration(null)); } @Test() diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java index 6a2eaaedcf..1546f7aa64 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java @@ -19,7 +19,7 @@ package org.apache.dubbo.rpc.cluster.support.wrapper; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; @@ -31,6 +31,7 @@ import org.apache.dubbo.rpc.cluster.LoadBalance; import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker; import org.apache.dubbo.rpc.support.MockProtocol; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -660,7 +661,7 @@ public class MockClusterInvokerTest { Arrays.stream(methods).forEach(m -> { methodInvokers.put(m.getName(), invokers); }); - dic.buildRouterChain(methodInvokers, ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension()); + dic.buildRouterChain(methodInvokers, ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension().getDynamicConfiguration(null)); AbstractClusterInvoker cluster = new AbstractClusterInvoker(dic) { @Override protected Result doInvoke(Invocation invocation, List invokers, LoadBalance loadbalance) diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java similarity index 67% rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java index cc3a3dcb58..28ef93bcf9 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java @@ -14,31 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.configcenter; +package org.apache.dubbo.common.config; import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.config.Configuration; -import org.apache.dubbo.common.config.Environment; - -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; /** * Utilities for manipulating configurations from different sources */ 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 specifies. If no DynamicConfig presents, - * NopDynamicConfiguration will be used. - */ - public static DynamicConfiguration getDynamicConfiguration() { - DynamicConfiguration dynamicConfiguration = (DynamicConfiguration) Environment.getInstance().getDynamicConfiguration(); - if (dynamicConfiguration == null) { - dynamicConfiguration = getExtensionLoader(DynamicConfiguration.class).getDefaultExtension(); - } - return dynamicConfiguration; - } - + // FIXME @SuppressWarnings("deprecation") public static int getServerShutdownTimeout() { int timeout = Constants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT; @@ -63,4 +47,12 @@ public class ConfigurationUtils { } return timeout; } + + public static String getProperty(String property) { + return getProperty(property, null); + } + + public static String getProperty(String property, String defaultValue) { + return Environment.getInstance().getConfiguration().getString(property, defaultValue); + } } 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 4c699f991f..dbe3821fdc 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 @@ -24,6 +24,7 @@ import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; import java.io.IOException; import java.io.StringReader; @@ -94,11 +95,10 @@ public class ConfigCenterConfig extends AbstractConfig { } private DynamicConfiguration startDynamicConfiguration(URL url) { - DynamicConfiguration dynamicConfiguration = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getExtension(url.getProtocol()); - // TODO, maybe we need a factory to do this? - dynamicConfiguration.initWith(url); - Environment.getInstance().setDynamicConfiguration(dynamicConfiguration); - return dynamicConfiguration; + DynamicConfigurationFactory dynamicConfigurationFactory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getExtension(url.getProtocol()); + DynamicConfiguration configuration = dynamicConfigurationFactory.getDynamicConfiguration(url); + Environment.getInstance().setDynamicConfiguration(configuration); + return configuration; } private URL toConfigUrl() { 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 4190e1d69d..6d711bac02 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 @@ -21,13 +21,12 @@ import org.apache.dubbo.common.config.AbstractConfiguration; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; /** * Dynamic configuration template class. The concrete implementation needs to provide implementation for three methods. * * @see AbstractDynamicConfiguration#getTargetConfig(String, String, long) - * @see AbstractDynamicConfiguration#addConfigurationListener(TargetListener, ConfigurationListener) + * @see AbstractDynamicConfiguration#addConfigurationListener(String key, TargetListener, ConfigurationListener) * @see AbstractDynamicConfiguration#createTargetListener(String) */ public abstract class AbstractDynamicConfiguration extends AbstractConfiguration @@ -35,7 +34,6 @@ public abstract class AbstractDynamicConfiguration extends Abstr protected static final String DEFAULT_GROUP = "dubbo"; protected URL url; - private AtomicBoolean inited = new AtomicBoolean(false); // One key can register multiple target listeners, but one target listener only maps to one configuration listener protected ConcurrentMap targetListeners = @@ -44,12 +42,9 @@ public abstract class AbstractDynamicConfiguration extends Abstr public AbstractDynamicConfiguration() { } - @Override - public void initWith(URL url) { - if (!inited.compareAndSet(false, true)) { - return; - } + public AbstractDynamicConfiguration(URL url) { this.url = url; + initWith(url); } @Override @@ -60,30 +55,18 @@ public abstract class AbstractDynamicConfiguration extends Abstr @Override public String getConfig(String key) { - return getConfig(key, null, null); + return getConfig(key, null, 0L); } @Override public String getConfig(String key, String group) { - return getConfig(key, group, null); + return getConfig(key, group, 0L); } - @Override - public String getConfig(String key, ConfigurationListener listener) { - return getConfig(key, null, listener); - } @Override - public String getConfig(String key, String group, ConfigurationListener listener) { - return getConfig(key, group, listener, 0L); - } - - @Override - public String getConfig(String key, String group, ConfigurationListener listener, long timeout) { + public String getConfig(String key, String group, long timeout) { try { - if (listener != null) { - this.addListener(key, listener); - } return getTargetConfig(key, group, timeout); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); @@ -95,6 +78,9 @@ public abstract class AbstractDynamicConfiguration extends Abstr } + protected abstract void initWith(URL url); + + // FIXME do wo need this? protected abstract void recover(); /** diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java new file mode 100644 index 0000000000..324f2cbef7 --- /dev/null +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.configcenter; + +import org.apache.dubbo.common.URL; + +/** + * + */ +public abstract class AbstractDynamicConfigurationFactory implements DynamicConfigurationFactory { + + private volatile DynamicConfiguration dynamicConfiguration; + + @Override + public DynamicConfiguration getDynamicConfiguration(URL url) { + if (dynamicConfiguration == null) { + synchronized (this) { + if (dynamicConfiguration == null) { + dynamicConfiguration = createDynamicConfiguration(url); + } + } + } + return dynamicConfiguration; + } + + protected abstract DynamicConfiguration createDynamicConfiguration(URL url); +} 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 7031a07489..7c7a1310d4 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 @@ -22,7 +22,6 @@ package org.apache.dubbo.configcenter; public interface ConfigurationListener { /** - * FIXME should it be synchronized? * Listener call back method. Listener gets notified by this method once there's any change happens on the config * the listener listens on. * 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 deleted file mode 100644 index f60d560b6c..0000000000 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.configcenter; - -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; - private String service; - private String method; - - private Configuration delegate; - - public ConfigurationWrapper(String application, String service, String method, Configuration configuration) { - this.application = application; - this.service = service; - this.method = method; - 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); - if (value == null) { - value = delegate.getProperty(service + "." + key); - } - if (value == null) { - value = delegate.getProperty(service + "." + method + "." + key); - } - if (value == null) { - value = delegate.getProperty(key); - } - return value; - } -} 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 7e37918f7c..6b4b476460 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 @@ -16,32 +16,24 @@ */ package org.apache.dubbo.configcenter; -import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.Configuration; -import org.apache.dubbo.common.extension.SPI; /** * Dynamic configuration */ -@SPI("nop") public interface DynamicConfiguration extends Configuration { - /** - * 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 - * The listener only works for service governance purpose, so the group would always be 'dubbo' + * The listener only works for service governance purpose, so the target group would always be the value user specifies at startup or 'dubbo' by default. + * This method will only register listener, which means it will not trigger a notification that contains the current value. * * @param key the key to represent a configuration * @param listener configuration listener */ void addListener(String key, ConfigurationListener listener); + void removeListener(String key, ConfigurationListener listener); /** @@ -62,34 +54,14 @@ public interface DynamicConfiguration extends Configuration { 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); - - /** - * 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 + * Get the configuration mapped to the given key and the given group. 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); + String getConfig(String key, String group, long timeout) throws IllegalStateException; } 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/DynamicConfigurationFactory.java similarity index 80% rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigType.java rename to dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfigurationFactory.java index d38e39d1e1..4e0b9b521c 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/DynamicConfigurationFactory.java @@ -16,17 +16,15 @@ */ package org.apache.dubbo.configcenter; -/** - * Config type - */ -public enum ConfigType { - /** - * For Dubbo dynamic config other than routing rules. - */ - CONFIGURATORS, +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.SPI; + +/** + * + */ +@SPI("nop") +public interface DynamicConfigurationFactory { + + DynamicConfiguration getDynamicConfiguration(URL url); - /** - * For Dubbo routing rules - */ - ROUTERS } 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 125023333c..1c061a46c4 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 @@ -16,6 +16,7 @@ */ package org.apache.dubbo.configcenter.support.nop; +import org.apache.dubbo.common.URL; import org.apache.dubbo.configcenter.AbstractDynamicConfiguration; import org.apache.dubbo.configcenter.ConfigurationListener; import org.apache.dubbo.configcenter.DynamicConfiguration; @@ -26,6 +27,18 @@ import org.apache.dubbo.configcenter.DynamicConfiguration; */ public class NopDynamicConfiguration extends AbstractDynamicConfiguration { + NopDynamicConfiguration() { + } + + public NopDynamicConfiguration(URL url) { + super(url); + } + + @Override + protected void initWith(URL url) { + + } + @Override protected String getTargetConfig(String key, String group, long timeout) { return null; diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java new file mode 100644 index 0000000000..0b6aee6a35 --- /dev/null +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.configcenter.support.nop; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory; +import org.apache.dubbo.configcenter.DynamicConfiguration; + +/** + * + */ +public class NopDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory { + + @Override + protected DynamicConfiguration createDynamicConfiguration(URL url) { + return new NopDynamicConfiguration(url); + } +} diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/org.apache.dubbo.configcenter.DynamicConfiguration b/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/org.apache.dubbo.configcenter.DynamicConfigurationFactory similarity index 84% rename from dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/org.apache.dubbo.configcenter.DynamicConfiguration rename to dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/org.apache.dubbo.configcenter.DynamicConfigurationFactory index 6d8fab4a71..51c4004176 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/org.apache.dubbo.configcenter.DynamicConfiguration +++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/org.apache.dubbo.configcenter.DynamicConfigurationFactory @@ -1 +1 @@ -nop=org.apache.dubbo.configcenter.support.nop.NopDynamicConfiguration \ No newline at end of file +nop=org.apache.dubbo.configcenter.support.nop.NopDynamicConfigurationFactory \ No newline at end of file diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.java new file mode 100644 index 0000000000..7d187e82a4 --- /dev/null +++ b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.configcenter.mock; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; +import org.apache.dubbo.configcenter.support.nop.NopDynamicConfigurationFactory; + +import org.junit.Assert; +import org.junit.Test; + +/** + * + */ +public class AbstractDynamicConfigurationTest { + public DynamicConfigurationFactory configurationFactory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getExtension("mock"); + public URL url = URL.valueOf("nop://127.0.0.1:10880/DynamicConfiguration"); + + @Test + public void testInit() { + DynamicConfiguration configuration1 = configurationFactory.getDynamicConfiguration(url); + DynamicConfiguration configuration2 = configurationFactory.getDynamicConfiguration(url); + Assert.assertEquals(configuration1, configuration2); + } + + @Test + public void testDefaultExtension() { + DynamicConfigurationFactory factory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension(); + Assert.assertTrue(factory instanceof NopDynamicConfigurationFactory); + } +} diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java index 012322d7a6..f2ad4c855c 100644 --- a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java @@ -16,8 +16,49 @@ */ package org.apache.dubbo.configcenter.mock; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.configcenter.AbstractDynamicConfiguration; +import org.apache.dubbo.configcenter.ConfigurationListener; + /** * */ -public class MockDynamicConfiguration { +public class MockDynamicConfiguration extends AbstractDynamicConfiguration { + + MockDynamicConfiguration() { + } + + MockDynamicConfiguration(URL url) { + super(url); + } + + @Override + protected void initWith(URL url) { + + } + + @Override + protected void recover() { + + } + + @Override + protected String getTargetConfig(String key, String group, long timeout) { + return null; + } + + @Override + protected void addConfigurationListener(String key, Object o, ConfigurationListener configurationListener) { + + } + + @Override + protected Object createTargetListener(String key) { + return null; + } + + @Override + protected Object getInternalProperty(String key) { + return null; + } } diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java new file mode 100644 index 0000000000..13482b7729 --- /dev/null +++ b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.configcenter.mock; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory; +import org.apache.dubbo.configcenter.DynamicConfiguration; + +/** + * + */ +public class MockDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory { + + @Override + protected DynamicConfiguration createDynamicConfiguration(URL url) { + return new MockDynamicConfiguration(url); + } +} diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration b/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration deleted file mode 100644 index 944a089c92..0000000000 --- a/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration +++ /dev/null @@ -1 +0,0 @@ -mock=org.apache.dubbo.configcenter.support.mock.MockDynamicConfiguration \ No newline at end of file diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory new file mode 100644 index 0000000000..211d45e8a7 --- /dev/null +++ b/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory @@ -0,0 +1 @@ +mock=org.apache.dubbo.configcenter.mock.MockDynamicConfigurationFactory \ No newline at end of file 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 6e3b77eef8..8b34d552f9 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 @@ -47,14 +47,15 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration { private static final Logger logger = LoggerFactory.getLogger(ZookeeperDynamicConfiguration.class); - private Executor executor = Executors.newFixedThreadPool(1); + private Executor executor; private CuratorFramework client; // The final root path would be: /configRootPath/"config" private String rootPath; private TreeCache treeCache; - private CountDownLatch initializedLatch = new CountDownLatch(1); + private CountDownLatch initializedLatch; private CacheListener cacheListener; - @Override - public void initWith(URL url) { - super.initWith(url); + ZookeeperDynamicConfiguration() { + } + ZookeeperDynamicConfiguration(URL url) { + super(url); + } + + protected void initWith(URL url) { rootPath = "/" + url.getParameter(CONFIG_NAMESPACE_KEY, Constants.DUBBO) + "/config"; RetryPolicy policy = new ExponentialBackoffRetry(1000, 3); - int sessionTimeout = 60 * 1000; - int connectTimeout = 10 * 1000; + int sessionTimeout = url.getParameter("config.session.timeout", 60 * 1000); + int connectTimeout = url.getParameter("config.connect.timeout", 10 * 1000); String connectString = url.getBackupAddress(); client = newClient(connectString, sessionTimeout, connectTimeout, policy); client.start(); @@ -69,7 +74,7 @@ public class ZookeeperDynamicConfiguration extends AbstractDynamicConfiguration< try { boolean connected = client.blockUntilConnected(3 * connectTimeout, TimeUnit.MILLISECONDS); if (!connected) { - if (url.getParameter(Constants.CONFIG_CHECK_KEY, false)) { + if (url.getParameter(Constants.CONFIG_CHECK_KEY, true)) { throw new IllegalStateException("Failed to connect to config center (zookeeper): " + connectString + " in " + 3 * connectTimeout + "ms."); } else { @@ -81,8 +86,9 @@ public class ZookeeperDynamicConfiguration extends AbstractDynamicConfiguration< + connectString + " config center, ", e); } + initializedLatch = new CountDownLatch(1); this.cacheListener = new CacheListener(rootPath, initializedLatch); - + this.executor = Executors.newFixedThreadPool(1); // build local cache try { this.buildCache(); @@ -97,7 +103,7 @@ public class ZookeeperDynamicConfiguration extends AbstractDynamicConfiguration< key = group + "." + key; } - return (String) getInternalProperty(key); + return (String) getInternalProperty(rootPath + "/" + key.replaceFirst("\\.", "/")); } @Override @@ -116,7 +122,7 @@ public class ZookeeperDynamicConfiguration extends AbstractDynamicConfiguration< */ @Override protected Object getInternalProperty(String key) { - ChildData childData = treeCache.getCurrentData(rootPath + "/" + key.replaceFirst("\\.", "/")); + ChildData childData = treeCache.getCurrentData(key); if (childData != null) { return new String(childData.getData(), StandardCharsets.UTF_8); } diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java new file mode 100644 index 0000000000..7994e0461f --- /dev/null +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.configcenter.support.zookeeper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory; +import org.apache.dubbo.configcenter.DynamicConfiguration; + +/** + * + */ +public class ZookeeperDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory { + @Override + protected DynamicConfiguration createDynamicConfiguration(URL url) { + return new ZookeeperDynamicConfiguration(url); + } +} diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory similarity index 68% rename from dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration rename to dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory index 0379c0e662..34ad0f42c5 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfiguration +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory @@ -1 +1 @@ -zookeeper=org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration \ No newline at end of file +zookeeper=org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfigurationFactory \ No newline at end of file diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java index af9571c640..e3b137bb4d 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java @@ -16,16 +16,18 @@ */ package org.apache.dubbo.configcenter.support.zookeeper; -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.CuratorFrameworkFactory; -import org.apache.curator.retry.ExponentialBackoffRetry; -import org.apache.curator.test.TestingServer; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.configcenter.ConfigChangeEvent; import org.apache.dubbo.configcenter.ConfigurationListener; import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.curator.test.TestingServer; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -66,8 +68,7 @@ public class ZookeeperDynamicConfigurationTest { configUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); - configuration = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getExtension(configUrl.getProtocol()); - configuration.initWith(configUrl); + configuration = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getExtension(configUrl.getProtocol()).getDynamicConfiguration(configUrl); } @AfterClass diff --git a/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java b/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java index d7827e90e2..4b90cc2b2e 100644 --- a/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java +++ b/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java @@ -16,8 +16,7 @@ */ package org.apache.dubbo.container.log4j; -import org.apache.dubbo.common.config.Configuration; -import org.apache.dubbo.common.config.Environment; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.container.Container; import org.apache.log4j.Appender; @@ -44,10 +43,9 @@ public class Log4jContainer implements Container { @Override @SuppressWarnings("unchecked") public void start() { - Configuration configuration = Environment.getInstance().getConfiguration(); - String file = configuration.getString(LOG4J_FILE); + String file = ConfigurationUtils.getProperty(LOG4J_FILE); if (file != null && file.length() > 0) { - String level = configuration.getString(LOG4J_LEVEL); + String level = ConfigurationUtils.getProperty(LOG4J_LEVEL); if (level == null || level.length() == 0) { level = DEFAULT_LOG4J_LEVEL; } @@ -61,7 +59,7 @@ public class Log4jContainer implements Container { properties.setProperty("log4j.appender.application.layout.ConversionPattern", "%d [%t] %-5p %C{6} (%F:%L) - %m%n"); PropertyConfigurator.configure(properties); } - String subdirectory = configuration.getString(LOG4J_SUBDIRECTORY); + String subdirectory = ConfigurationUtils.getProperty(LOG4J_SUBDIRECTORY); if (subdirectory != null && subdirectory.length() > 0) { Enumeration ls = LogManager.getCurrentLoggers(); while (ls.hasMoreElements()) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java index 785e41e857..df19377b10 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java @@ -192,27 +192,22 @@ public class RegistryDirectory extends AbstractDirectory implements Notify public void subscribe(URL url) { setConsumerUrl(url); - String rawConfig = null; - try { - rawConfig = dynamicConfiguration.getConfig(url.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX, this); - if (StringUtils.isNotEmpty(rawConfig)) { - this.dynamicConfigurators = configToConfiguratiors(rawConfig); - } - } catch (Exception e) { - logger.error("Failed to load or parse dynamic config (service level), the raw config is: " + rawConfig, e); - } - - String rawConfigApp = null; - try { - rawConfigApp = dynamicConfiguration.getConfig(url.getParameter(Constants.APPLICATION_KEY) + Constants.CONFIGURATORS_SUFFIX, this); - if (StringUtils.isNotEmpty(rawConfigApp)) { - this.appDynamicConfigurators = configToConfiguratiors(rawConfigApp); - } - } catch (Exception e) { - logger.error("Failed to load or parse dynamic config (application level), the raw config is: " + rawConfigApp, e); - } - registry.subscribe(url, this); + + synchronized (this) { + String key = url.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX; + dynamicConfiguration.addListener(key, this); + String rawConfig = dynamicConfiguration.getConfig(key); + if (rawConfig != null) { + this.process(new ConfigChangeEvent(key, rawConfig)); + } + + String appKey = url.getParameter(Constants.APPLICATION_KEY) + Constants.CONFIGURATORS_SUFFIX; + String appRawConfig = dynamicConfiguration.getConfig(appKey); + if (appRawConfig != null) { + this.process(new ConfigChangeEvent(appKey, appRawConfig)); + } + } } @Override @@ -279,6 +274,14 @@ public class RegistryDirectory extends AbstractDirectory implements Notify List routers = toRouters(routerUrls); addRouters(routers); } + + overrideDirectoryUrl(); + + // providers + refreshInvoker(invokerUrls); + } + + private void overrideDirectoryUrl() { // merge override parameters this.overrideDirectoryUrl = directoryUrl; List localConfigurators = this.configurators; // local reference @@ -299,8 +302,6 @@ public class RegistryDirectory extends AbstractDirectory implements Notify this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl); }); } - // providers - refreshInvoker(invokerUrls); } /* private List compositeDynamicConfiguration(List urls) { @@ -708,7 +709,7 @@ public class RegistryDirectory extends AbstractDirectory implements Notify } @Override - public void process(ConfigChangeEvent event) { + public synchronized void process(ConfigChangeEvent event) { List urls = new ArrayList<>(); if (event.getChangeType().equals(ConfigChangeType.DELETED)) { URL url = getConsumerUrl().clearParameters().setProtocol(Constants.EMPTY_PROTOCOL); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java index d07d8a4ab5..1b3aba5874 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java @@ -18,6 +18,8 @@ package org.apache.dubbo.registry.integration; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; +import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -28,7 +30,6 @@ import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.configcenter.ConfigChangeEvent; import org.apache.dubbo.configcenter.ConfigChangeType; import org.apache.dubbo.configcenter.ConfigurationListener; -import org.apache.dubbo.configcenter.ConfigurationUtils; import org.apache.dubbo.configcenter.DynamicConfiguration; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.Registry; @@ -86,7 +87,7 @@ public class RegistryProtocol implements Protocol { public RegistryProtocol() { INSTANCE = this; - dynamicConfiguration = ConfigurationUtils.getDynamicConfiguration(); + dynamicConfiguration = (DynamicConfiguration) Environment.getInstance().getDynamicConfiguration(); } public static RegistryProtocol getRegistryProtocol() { @@ -159,7 +160,7 @@ public class RegistryProtocol implements Protocol { final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker); overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener); - providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener); + providerUrl = overrideUrlWithConfig(providerUrl); //export invoker final ExporterChangeableWrapper exporter = doLocalExport(originInvoker, providerUrl); @@ -174,7 +175,9 @@ public class RegistryProtocol implements Protocol { ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true); } + // Deprecated! Subscribe to override rules in 2.6.x or before. registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener); + subscribeDynamicConfiguration(overrideSubscribeUrl); exporter.setRegisterUrl(registeredProviderUrl); exporter.setSubscribeUrl(overrideSubscribeUrl); @@ -182,24 +185,49 @@ public class RegistryProtocol implements Protocol { return new DestroyableExporter<>(exporter); } - private URL overrideUrlWithConfig(URL providerUrl, OverrideListener listener) { + /** + * Get existing configuration rule and override provider url before exporting. + * + * @param providerUrl + * @param + * @return + */ + private URL overrideUrlWithConfig(URL providerUrl) { List configurators = new LinkedList<>(); - String appRawConfig = dynamicConfiguration.getConfig(providerUrl.getParameter(Constants.APPLICATION_KEY) + Constants.CONFIGURATORS_SUFFIX, listener); + String appRawConfig = dynamicConfiguration.getConfig(providerUrl.getParameter(Constants.APPLICATION_KEY) + Constants.CONFIGURATORS_SUFFIX); if (!StringUtils.isEmpty(appRawConfig)) { List appDynamicConfigurators = RegistryDirectory.configToConfiguratiors(appRawConfig); - listener.setAppDynamicConfigurators(appDynamicConfigurators); configurators.addAll(appDynamicConfigurators); } - String rawConfig = dynamicConfiguration.getConfig(providerUrl.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX, listener); + String rawConfig = dynamicConfiguration.getConfig(providerUrl.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX); if (!StringUtils.isEmpty(rawConfig)) { List dynamicConfigurators = RegistryDirectory.configToConfiguratiors(rawConfig); - listener.setDynamicConfigurators(dynamicConfigurators); configurators.addAll(dynamicConfigurators); } providerUrl = getConfigedInvokerUrl(configurators, providerUrl); return providerUrl; } + private void subscribeDynamicConfiguration(URL url) { + synchronized (overrideListeners.get(url)) { + OverrideListener listener = (OverrideListener) overrideListeners.get(url); + + String appKey = url.getParameter(Constants.APPLICATION_KEY) + Constants.CONFIGURATORS_SUFFIX; + dynamicConfiguration.addListener(appKey, listener); + String appRawConfig = dynamicConfiguration.getConfig(appKey); + if (appRawConfig != null) { + listener.process(new ConfigChangeEvent(appKey, appRawConfig)); + } + + String serviceKey = url.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX; + dynamicConfiguration.addListener(serviceKey, listener); + String rawConfig = dynamicConfiguration.getConfig(serviceKey); + if (rawConfig != null) { + listener.process(new ConfigChangeEvent(serviceKey, rawConfig)); + } + } + } + @SuppressWarnings("unchecked") private ExporterChangeableWrapper doLocalExport(final Invoker originInvoker, URL providerUrl) { String key = getCacheKey(originInvoker); @@ -556,7 +584,7 @@ public class RegistryProtocol implements Protocol { } @Override - public void process(ConfigChangeEvent event) { + public synchronized void process(ConfigChangeEvent event) { List urls; if (event.getChangeType().equals(ConfigChangeType.DELETED)) { URL originUrl = RegistryProtocol.this.getProviderUrl(originInvoker); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java index 60c56f0453..d590f9ec90 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java @@ -18,8 +18,8 @@ package org.apache.dubbo.rpc.protocol.dubbo; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.utils.AtomicPositiveInteger; -import org.apache.dubbo.configcenter.ConfigurationUtils; import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.TimeoutException; import org.apache.dubbo.remoting.exchange.ExchangeClient; diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java index 2b7c156790..d3ac220101 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java @@ -18,13 +18,13 @@ package org.apache.dubbo.rpc.protocol.dubbo; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.serialize.support.SerializableClassRegistry; import org.apache.dubbo.common.serialize.support.SerializationOptimizer; import org.apache.dubbo.common.utils.ConcurrentHashSet; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.configcenter.ConfigurationUtils; import org.apache.dubbo.remoting.Channel; import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.Transporter; diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java index 984ab71fd1..4addbf37ad 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java @@ -19,13 +19,14 @@ package org.apache.dubbo.rpc.protocol.dubbo; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.configcenter.ConfigurationUtils; import org.apache.dubbo.remoting.exchange.ExchangeClient; import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.ProxyFactory; import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; + import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java index 731e94787c..958d8e6323 100644 --- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java +++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java @@ -18,8 +18,8 @@ package org.apache.dubbo.rpc.protocol.thrift; import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.configcenter.ConfigurationUtils; import org.apache.dubbo.remoting.Channel; import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.Transporter;