refactor config-center implementation
This commit is contained in:
parent
38a8fad488
commit
00b15a44c6
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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<Router>, 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<Router>, 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<Router>, 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;
|
||||
|
|
|
|||
|
|
@ -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<String, List<Invoker<FileRouterEngineTest>>> 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)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String, List<Invoker<IHelloService>>> 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()
|
||||
|
|
|
|||
|
|
@ -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<IHelloService> cluster = new AbstractClusterInvoker(dic) {
|
||||
@Override
|
||||
protected Result doInvoke(Invocation invocation, List invokers, LoadBalance loadbalance)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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<TargetListener> extends AbstractConfiguration
|
||||
|
|
@ -35,7 +34,6 @@ public abstract class AbstractDynamicConfiguration<TargetListener> 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<String, TargetListener> targetListeners =
|
||||
|
|
@ -44,12 +42,9 @@ public abstract class AbstractDynamicConfiguration<TargetListener> 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<TargetListener> 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<TargetListener> extends Abstr
|
|||
|
||||
}
|
||||
|
||||
protected abstract void initWith(URL url);
|
||||
|
||||
// FIXME do wo need this?
|
||||
protected abstract void recover();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
nop=org.apache.dubbo.configcenter.support.nop.NopDynamicConfiguration
|
||||
nop=org.apache.dubbo.configcenter.support.nop.NopDynamicConfigurationFactory
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
mock=org.apache.dubbo.configcenter.support.mock.MockDynamicConfiguration
|
||||
|
|
@ -0,0 +1 @@
|
|||
mock=org.apache.dubbo.configcenter.mock.MockDynamicConfigurationFactory
|
||||
|
|
@ -47,14 +47,15 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration<Apo
|
|||
|
||||
private Config dubboConfig;
|
||||
|
||||
public ApolloDynamicConfiguration() {
|
||||
ApolloDynamicConfiguration() {
|
||||
}
|
||||
|
||||
ApolloDynamicConfiguration(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initWith(URL url) {
|
||||
super.initWith(url);
|
||||
|
||||
// Instead of using Dubbo's configuration, I would suggest use the original configuration method Apollo provides.
|
||||
String configEnv = url.getParameter(Constants.CONFIG_ENV_KEY);
|
||||
String configAddr = url.getBackupAddress();
|
||||
|
|
@ -71,7 +72,7 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration<Apo
|
|||
|
||||
dubboConfig = ConfigService.getConfig(url.getParameter(Constants.CONFIG_GROUP_KEY, DEFAULT_GROUP));
|
||||
// Decide to fail or to continue when failed to connect to remote server.
|
||||
boolean check = url.getParameter(Constants.CONFIG_CHECK_KEY, false);
|
||||
boolean check = url.getParameter(Constants.CONFIG_CHECK_KEY, true);
|
||||
if (dubboConfig.getSourceType() != ConfigSourceType.REMOTE) {
|
||||
if (check) {
|
||||
throw new IllegalStateException("Failed to connect to config center, the config center is Apollo, " +
|
||||
|
|
@ -142,7 +143,7 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration<Apo
|
|||
public void onChange(com.ctrip.framework.apollo.model.ConfigChangeEvent changeEvent) {
|
||||
for (String key : changeEvent.changedKeys()) {
|
||||
ConfigChange change = changeEvent.getChange(key);
|
||||
if (StringUtils.isEmpty(change.getNewValue())) {
|
||||
if ("".equals(change.getNewValue())) {
|
||||
logger.warn("an empty rule is received for " + key + ", the current working rule is " +
|
||||
change.getOldValue() + ", the empty rule will not take effect.");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -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.apollo;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
|
||||
import org.apache.dubbo.configcenter.DynamicConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ApolloDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {
|
||||
@Override
|
||||
protected DynamicConfiguration createDynamicConfiguration(URL url) {
|
||||
return new ApolloDynamicConfiguration(url);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
apollo=org.apache.dubbo.configcenter.support.apollo.ApolloDynamicConfiguration
|
||||
apollo=org.apache.dubbo.configcenter.support.apollo.ApolloDynamicConfigurationFactory
|
||||
|
|
@ -16,16 +16,17 @@
|
|||
*/
|
||||
package org.apache.dubbo.configcenter.support.zookeeper;
|
||||
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
|
||||
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
|
||||
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;
|
||||
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
|
||||
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -97,6 +98,7 @@ public class CacheListener implements TreeCacheListener {
|
|||
|
||||
/**
|
||||
* This is used to convert a configuration nodePath into a key
|
||||
* TODO doc
|
||||
*
|
||||
* @param path
|
||||
* @return key (nodePath less the config root path)
|
||||
|
|
|
|||
|
|
@ -16,16 +16,17 @@
|
|||
*/
|
||||
package org.apache.dubbo.configcenter.support.zookeeper;
|
||||
|
||||
import org.apache.curator.RetryPolicy;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.apache.curator.framework.recipes.cache.TreeCache;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.dubbo.common.Constants;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.configcenter.AbstractDynamicConfiguration;
|
||||
import org.apache.dubbo.configcenter.ConfigurationListener;
|
||||
|
||||
import org.apache.curator.RetryPolicy;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.apache.curator.framework.recipes.cache.TreeCache;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -43,25 +44,29 @@ import static org.apache.dubbo.common.Constants.CONFIG_NAMESPACE_KEY;
|
|||
*/
|
||||
public class ZookeeperDynamicConfiguration extends AbstractDynamicConfiguration<CacheListener> {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
zookeeper=org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration
|
||||
zookeeper=org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfigurationFactory
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<org.apache.log4j.Logger> ls = LogManager.getCurrentLoggers();
|
||||
while (ls.hasMoreElements()) {
|
||||
|
|
|
|||
|
|
@ -192,27 +192,22 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> 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<T> extends AbstractDirectory<T> implements Notify
|
|||
List<Router> routers = toRouters(routerUrls);
|
||||
addRouters(routers);
|
||||
}
|
||||
|
||||
overrideDirectoryUrl();
|
||||
|
||||
// providers
|
||||
refreshInvoker(invokerUrls);
|
||||
}
|
||||
|
||||
private void overrideDirectoryUrl() {
|
||||
// merge override parameters
|
||||
this.overrideDirectoryUrl = directoryUrl;
|
||||
List<Configurator> localConfigurators = this.configurators; // local reference
|
||||
|
|
@ -299,8 +302,6 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
|
|||
this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl);
|
||||
});
|
||||
}
|
||||
// providers
|
||||
refreshInvoker(invokerUrls);
|
||||
}
|
||||
|
||||
/* private List<URL> compositeDynamicConfiguration(List<URL> urls) {
|
||||
|
|
@ -708,7 +709,7 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
|
|||
}
|
||||
|
||||
@Override
|
||||
public void process(ConfigChangeEvent event) {
|
||||
public synchronized void process(ConfigChangeEvent event) {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
if (event.getChangeType().equals(ConfigChangeType.DELETED)) {
|
||||
URL url = getConsumerUrl().clearParameters().setProtocol(Constants.EMPTY_PROTOCOL);
|
||||
|
|
|
|||
|
|
@ -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<T> 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 <T> URL overrideUrlWithConfig(URL providerUrl, OverrideListener listener) {
|
||||
/**
|
||||
* Get existing configuration rule and override provider url before exporting.
|
||||
*
|
||||
* @param providerUrl
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
private <T> URL overrideUrlWithConfig(URL providerUrl) {
|
||||
List<Configurator> 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<Configurator> 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<Configurator> 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 <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> 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<URL> urls;
|
||||
if (event.getChangeType().equals(ConfigChangeType.DELETED)) {
|
||||
URL originUrl = RegistryProtocol.this.getProviderUrl(originInvoker);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue