From f51b3944c36679500ce0da3eee79843e6dd467d9 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 11 Jul 2019 15:13:08 +0800 Subject: [PATCH 01/30] Polish apache/dubbo#4542 : [Enhancement] Adapt the Java standard Event/Listener mechanism --- .../dubbo/common/config/configcenter/ConfigChangeEvent.java | 6 +++++- .../common/config/configcenter/ConfigurationListener.java | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java index 751746f199d..177551be929 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java @@ -16,15 +16,18 @@ */ package org.apache.dubbo.common.config.configcenter; +import java.util.EventObject; + /** * Config change event, immutable. * * @see ConfigChangeType */ -public class ConfigChangeEvent { +public class ConfigChangeEvent extends EventObject { private final String key; private final String value; + private final ConfigChangeType changeType; public ConfigChangeEvent(String key, String value) { @@ -32,6 +35,7 @@ public ConfigChangeEvent(String key, String value) { } public ConfigChangeEvent(String key, String value, ConfigChangeType changeType) { + super(key + "=" + value); this.key = key; this.value = value; this.changeType = changeType; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java index 09746c5bcee..2a1779a383d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java @@ -16,10 +16,12 @@ */ package org.apache.dubbo.common.config.configcenter; +import java.util.EventListener; + /** * Config listener, will get notified when the config it listens on changes. */ -public interface ConfigurationListener { +public interface ConfigurationListener extends EventListener { /** * Listener call back method. Listener gets notified by this method once there's any change happens on the config From 9e58caaae2efa96f9ab50642c2cccc4d77a9438e Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 15 Jul 2019 21:07:15 +0800 Subject: [PATCH 02/30] =?UTF-8?q?Polish=20apache/dubbo#4541=20:=20[Feature?= =?UTF-8?q?]=20Add=20local=20File=20System=20DynamicConfigurationFactory?= =?UTF-8?q?=E2=80=98s=20extension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dubbo-common/pom.xml | 4 + .../configcenter/DynamicConfiguration.java | 39 ++- .../DynamicConfigurationFactory.java | 4 +- .../file/FileSystemDynamicConfiguration.java | 324 ++++++++++++++++++ ...FileSystemDynamicConfigurationFactory.java | 35 ++ ...g.configcenter.DynamicConfigurationFactory | 3 +- .../FileSystemDynamicConfigurationTest.java | 95 +++++ dubbo-dependencies-bom/pom.xml | 11 +- 8 files changed, 497 insertions(+), 18 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java create mode 100644 dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java diff --git a/dubbo-common/pom.xml b/dubbo-common/pom.xml index 98ecc9b87b2..dabf4bb47ea 100644 --- a/dubbo-common/pom.xml +++ b/dubbo-common/pom.xml @@ -77,5 +77,9 @@ de.ruedigermoeller fst + + commons-io + commons-io + \ No newline at end of file diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java index f5bf9a426a0..8115669aa49 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java @@ -20,11 +20,10 @@ import org.apache.dubbo.common.config.Environment; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeMap; import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; @@ -133,6 +132,20 @@ default String getConfigs(String key, String group) throws IllegalStateException */ String getConfigs(String key, String group, long timeout) throws IllegalStateException; + + /** + * Publish Config mapped to the given key and the given group. + * + * @param key the key to represent a configuration + * @param content the content of configuration + * @return true if success, or false + * @throws UnsupportedOperationException If the under layer does not support + * @since 2.7.4 + */ + default boolean publishConfig(String key, String content) throws UnsupportedOperationException { + return publishConfig(key, DEFAULT_GROUP, content); + } + /** * Publish Config mapped to the given key and the given group. * @@ -155,38 +168,38 @@ default boolean publishConfig(String key, String group, String content) throws U * @throws UnsupportedOperationException If the under layer does not support * @since 2.7.4 */ - default SortedSet getConfigKeys(String group) throws UnsupportedOperationException { + default Set getConfigKeys(String group) throws UnsupportedOperationException { throw new UnsupportedOperationException("No support"); } /** - * Get the {@link SortedMap} with with config keys and contents value by the specified group + * Get the {@link Map} with with config keys and contents value by the specified group * * @param group the specified group - * @return the read-only non-null sorted {@link SortedMap map} + * @return the read-only non-null sorted {@link Map map} * @throws UnsupportedOperationException If the under layer does not support * @since 2.7.4 */ - default SortedMap getConfigs(String group) throws UnsupportedOperationException { + default Map getConfigs(String group) throws UnsupportedOperationException { return getConfigs(group, -1); } /** - * Get the {@link SortedMap} with with config keys and content value by the specified group + * Get the {@link Map} with with config keys and content value by the specified group * * @param group the specified group * @param timeout the millisecond for timeout - * @return the read-only non-null sorted {@link SortedMap map} + * @return the read-only non-null sorted {@link Map map} * @throws UnsupportedOperationException If the under layer does not support * @throws IllegalStateException If timeout exceeds * @since 2.7.4 */ - default SortedMap getConfigs(String group, long timeout) throws UnsupportedOperationException, + default Map getConfigs(String group, long timeout) throws UnsupportedOperationException, IllegalStateException { - SortedMap configs = new TreeMap<>(); - SortedSet configKeys = getConfigKeys(group); + Map configs = new LinkedHashMap<>(); + Set configKeys = getConfigKeys(group); configKeys.forEach(key -> configs.put(key, getConfig(key, group, timeout))); - return Collections.unmodifiableSortedMap(configs); + return Collections.unmodifiableMap(configs); } /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java index 59c27ce0cb4..42e090f0cd8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java @@ -20,9 +20,9 @@ import org.apache.dubbo.common.extension.SPI; /** - * + * The factory interface to create the instance of {@link DynamicConfiguration} */ -@SPI("nop") +@SPI("filesystem") // 2.7.4 change the public interface DynamicConfigurationFactory { DynamicConfiguration getDynamicConfiguration(URL url); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java new file mode 100644 index 00000000000..d0e47fa438e --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -0,0 +1,324 @@ +/* + * 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.common.config.configcenter.file; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; +import org.apache.dubbo.common.config.configcenter.ConfigChangeType; +import org.apache.dubbo.common.config.configcenter.ConfigurationListener; +import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; +import org.apache.dubbo.common.function.ThrowableConsumer; +import org.apache.dubbo.common.utils.NamedThreadFactory; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +import static java.lang.Integer.max; +import static java.lang.String.format; +import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; +import static java.util.Collections.unmodifiableMap; +import static java.util.concurrent.Executors.newFixedThreadPool; +import static java.util.stream.Stream.of; +import static org.apache.commons.io.FileUtils.readFileToString; +import static org.apache.dubbo.common.utils.StringUtils.isBlank; + +/** + * File-System based {@link DynamicConfiguration} implementation + * + * @since 2.7.4 + */ +public class FileSystemDynamicConfiguration implements DynamicConfiguration { + + public static final String CONFIG_CENTER_DIR_PARAM_NAME = "dubbo.config-center.dir"; + + public static final String CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME = "dubbo.config-center.thread-pool.name"; + + public static final String CONFIG_CENTER_THREAD_POOL_SIZE_PARAM_NAME = "dubbo.config-center.thread-pool.size"; + + public static final String CONFIG_CENTER_ENCODING_PARAM_NAME = "dubbo.config-center.encoding"; + + public static final String DEFAULT_CONFIG_CENTER_DIR_PATH = System.getProperty("user.home") + File.separator + + ".dubbo" + File.separator + "config-center"; + + public static final String DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME = "dubbo-config-center"; + + public static final int DEFAULT_CONFIG_CENTER_THREAD_POOL_SIZE = 2; + + public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8"; + + private static final WatchEvent.Kind[] INTEREST_PATH_KINDS = + new WatchEvent.Kind[]{ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY}; + + /** + * The unmodifiable map for {@link ConfigChangeType} whose key is the {@link WatchEvent.Kind#name() name} of + * {@link WatchEvent.Kind WatchEvent's Kind} + */ + private static final Map CONFIG_CHANGE_TYPES_MAP = + unmodifiableMap(new HashMap() { + // Initializes the elements that is mapping ConfigChangeType + { + put(ENTRY_CREATE.name(), ConfigChangeType.ADDED); + put(ENTRY_DELETE.name(), ConfigChangeType.DELETED); + put(ENTRY_MODIFY.name(), ConfigChangeType.MODIFIED); + } + }); + + /** + * Logger + */ + private final Log logger = LogFactory.getLog(getClass()); + + /** + * The Root Directory for config center + */ + private final File directory; + + /** + * The thread pool used to execute I/O tasks + */ + private final ExecutorService executorService; + + private final String encoding; + + private final Optional watchService; + + private final Map> listenersRepository; + + public FileSystemDynamicConfiguration(URL url) { + this.directory = initDirectory(url); + this.executorService = initExecutorService(url); + this.encoding = url.getParameter(CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); + this.watchService = newWatchService(); + this.listenersRepository = new LinkedHashMap<>(); + } + + private Optional newWatchService() { + Optional watchService = null; + FileSystem fileSystem = FileSystems.getDefault(); + try { + watchService = Optional.of(fileSystem.newWatchService()); + } catch (IOException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + watchService = Optional.empty(); + } + return watchService; + } + + private File initDirectory(URL url) { + String directoryPath = url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH); + File rootDirectory = new File(url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH)); + if (!rootDirectory.exists() && !rootDirectory.mkdirs()) { + throw new IllegalStateException(format("Dubbo config center directory[%s] can't be created!", + directoryPath)); + } + return rootDirectory; + } + + private ExecutorService initExecutorService(URL url) { + String threadPoolName = url.getParameter(CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME, DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME); + int threadPoolSize = url.getParameter(CONFIG_CENTER_THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_CONFIG_CENTER_THREAD_POOL_SIZE); + threadPoolSize = max(threadPoolSize, 2); + return newFixedThreadPool(threadPoolSize, new NamedThreadFactory(threadPoolName)); + } + + private File groupDirectory(String group) { + String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; + return new File(directory, actualGroup); + } + + private File keyFile(String key, String group) { + return new File(groupDirectory(group), key); + } + + @Override + public void addListener(String key, String group, ConfigurationListener listener) { + doInListener(key, group, (watchedFilePath, listeners) -> { + + if (listeners.isEmpty()) { // If no element, register watchService + ThrowableConsumer.execute(watchedFilePath, path -> { + File file = path.toFile(); + // A directory to be watched + File watchedDirectory = file.isFile() ? file.getParentFile() : file.isDirectory() ? file : null; + if (watchedDirectory != null) { + watchedDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS); + } + }); + } + + // Add into cache + listeners.add(listener); + }); + } + + @Override + public void removeListener(String key, String group, ConfigurationListener listener) { + doInListener(key, group, (file, listeners) -> { + // Remove into cache + listeners.remove(listener); + }); + } + + private void doInListener(String key, String group, BiConsumer> consumer) { + watchService.ifPresent(watchService -> { + // Initializes watchService if there is not any listener + if (listenersRepository.isEmpty()) { + initWatchService(watchService); + } + + File keyFile = keyFile(key, group); + if (keyFile.exists()) { // keyFile must exist + Path watchedFilePath = keyFile.toPath(); + List listeners = getListeners(watchedFilePath); + consumer.accept(watchedFilePath, listeners); + } + }); + } + + private void initWatchService(WatchService watchService) { + executorService.submit(() -> { // Async execution + while (true) { + WatchKey watchKey = watchService.poll(); + if (watchKey != null && watchKey.isValid()) { + List> events = watchKey.pollEvents(); + for (WatchEvent event : events) { + WatchEvent.Kind kind = event.kind(); + // configChangeType's key to match WatchEvent's Kind + ConfigChangeType configChangeType = CONFIG_CHANGE_TYPES_MAP.get(kind.name()); + if (configChangeType != null) { + Path parentPath = (Path) watchKey.watchable(); + Path currentPath = (Path) event.context(); + fireConfigChangeEvent(parentPath.resolve(currentPath), configChangeType); + } + } + } + } + }); + } + + private List getListeners(Path watchedFilePath) { + return listenersRepository.computeIfAbsent(watchedFilePath, p -> new LinkedList<>()); + } + + private void fireConfigChangeEvent(Path watchedFilePath, ConfigChangeType configChangeType) { + File watchedFile = watchedFilePath.toFile(); + String key = watchedFile.getName(); + String group = watchedFile.getParentFile().getName(); + String value = getConfig(key, group); + // fire ConfigChangeEvent one by one + getListeners(watchedFilePath).forEach(listener -> { + listener.process(new ConfigChangeEvent(key, value, configChangeType)); + }); + } + + @Override + public String getConfig(String key, String group, long timeout) throws IllegalStateException { + File keyFile = keyFile(key, group); + return keyFile.exists() ? execute(() -> readFileToString(keyFile, encoding), timeout) : null; + } + + @Override + public String getConfigs(String key, String group, long timeout) throws IllegalStateException { + return getConfig(key, group, timeout); + } + + @Override + public Object getInternalProperty(String key) { + return null; + } + + @Override + public boolean publishConfig(String key, String group, String content) { + File keyFile = keyFile(key, group); + boolean published = false; + try { + FileUtils.write(keyFile, content, encoding); + published = true; + } catch (IOException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage()); + } + } + return published; + } + + @Override + public Set getConfigKeys(String group) throws UnsupportedOperationException { + return of(groupDirectory(group).listFiles(File::isFile)) + .map(File::getName) + .collect(Collectors.toSet()); + } + + @Override + public Map getConfigs(String group) throws UnsupportedOperationException { + return getConfigs(group, -1); + } + + private V execute(Callable task, long timeout) { + V value = null; + try { + + if (timeout < 1) { // less or equal 0 + value = task.call(); + } else { + Future future = executorService.submit(task); + value = future.get(timeout, TimeUnit.MILLISECONDS); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + return value; + } + + protected File getDirectory() { + return directory; + } + + protected ExecutorService getExecutorService() { + return executorService; + } + + protected String getEncoding() { + return encoding; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java new file mode 100644 index 00000000000..4c23e36594b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java @@ -0,0 +1,35 @@ +/* + * 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.common.config.configcenter.file; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory; +import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; +import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; + +/** + * File-System based {@link DynamicConfigurationFactory} implementation + * + * @since 2.7.4 + */ +public class FileSystemDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory { + + @Override + protected DynamicConfiguration createDynamicConfiguration(URL url) { + return null; + } +} diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory index 42d6a251120..7cb20dc81fd 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory @@ -1 +1,2 @@ -nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory \ No newline at end of file +nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory +filesystem=org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory \ No newline at end of file diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java new file mode 100644 index 00000000000..39fc5bab6ff --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -0,0 +1,95 @@ +/* + * 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.common.config.configcenter.file; + +import org.apache.dubbo.common.URL; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.commons.io.FileUtils.deleteQuietly; +import static org.apache.dubbo.common.URL.valueOf; +import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * {@link FileSystemDynamicConfiguration} Test + */ +public class FileSystemDynamicConfigurationTest { + + private FileSystemDynamicConfiguration configuration; + + private static final String KEY = "abc-def-ghi"; + + private static final String CONTENT = "Hello,World"; + + @BeforeEach + public void init() { + String classPath = getClassPath(); + URL url = valueOf("dubbo://127.0.0.1:20880").addParameter(CONFIG_CENTER_DIR_PARAM_NAME, classPath + File.separator + "config-center"); + configuration = new FileSystemDynamicConfiguration(url); + deleteQuietly(configuration.getDirectory()); + } + + private String getClassPath() { + return getClass().getProtectionDomain().getCodeSource().getLocation().getPath(); + } + + @Test + public void testInit() { + assertEquals(new File(getClassPath(),"config-center"), configuration.getDirectory()); + assertEquals("UTF-8", configuration.getEncoding()); + assertEquals(ThreadPoolExecutor.class, configuration.getExecutorService().getClass()); + assertEquals(2, ((ThreadPoolExecutor) configuration.getExecutorService()).getMaximumPoolSize()); + assertEquals(2, ((ThreadPoolExecutor) configuration.getExecutorService()).getCorePoolSize()); + } + + @Test + public void testPublishAndGetConfig() { + assertTrue(configuration.publishConfig(KEY, CONTENT)); + assertEquals(CONTENT, configuration.getConfig(KEY)); + assertTrue(configuration.getConfigs(null).size() > 0); + } + + @Test + public void testAddAndRemoveListener() throws InterruptedException { + + configuration.publishConfig(KEY, "A"); + + AtomicBoolean processedEvent = new AtomicBoolean(); + + configuration.addListener(KEY, event -> { + + processedEvent.set(true); + +// assertEquals(KEY, event.getKey()); +// assertEquals("B", event.getValue()); + }); + + configuration.publishConfig(KEY, "B"); + + while (!processedEvent.get()) { + Thread.sleep(1 * 1000L); + } + + } +} diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index d6cf69e4bfc..27e284f8f57 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -15,14 +15,15 @@ limitations under the License. --> - + 4.0.0 org.apache apache 21 - + org.apache.dubbo @@ -135,6 +136,7 @@ 1.2.16 1.2.2 2.11.1 + 2.6 0.6 @@ -442,6 +444,11 @@ commons-logging ${jcl_version} + + commons-io + commons-io + ${commons_io_version} + log4j log4j From 9252be1e5f2a894709a06d1b0042a3012217e8ba Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Tue, 16 Jul 2019 01:15:46 +0800 Subject: [PATCH 03/30] Polish apache#4541 : Bugfix --- .../file/FileSystemDynamicConfiguration.java | 122 ++++++++----- .../FileSystemDynamicConfigurationTest.java | 38 +++- .../META-INF/spring/dubbo-provider.xml | 16 +- .../java/org/apache/dubbo/event/WatchDir.java | 164 ++++++++++++++++++ 4 files changed, 290 insertions(+), 50 deletions(-) create mode 100644 dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index d0e47fa438e..b1e0d674881 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -47,14 +47,14 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.stream.Collectors; import static java.lang.Integer.max; import static java.lang.String.format; -import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; -import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; -import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; +import static java.nio.file.StandardWatchEventKinds.*; import static java.util.Collections.unmodifiableMap; import static java.util.concurrent.Executors.newFixedThreadPool; import static java.util.stream.Stream.of; @@ -123,6 +123,8 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { private final Map> listenersRepository; + private final Lock lock = new ReentrantLock(); + public FileSystemDynamicConfiguration(URL url) { this.directory = initDirectory(url); this.executorService = initExecutorService(url); @@ -162,24 +164,25 @@ private ExecutorService initExecutorService(URL url) { return newFixedThreadPool(threadPoolSize, new NamedThreadFactory(threadPoolName)); } - private File groupDirectory(String group) { + protected File groupDirectory(String group) { String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; return new File(directory, actualGroup); } - private File keyFile(String key, String group) { + protected File configFile(String key, String group) { return new File(groupDirectory(group), key); } @Override public void addListener(String key, String group, ConfigurationListener listener) { - doInListener(key, group, (watchedFilePath, listeners) -> { + doInListener(key, group, (configFilePath, listeners) -> { - if (listeners.isEmpty()) { // If no element, register watchService - ThrowableConsumer.execute(watchedFilePath, path -> { - File file = path.toFile(); + if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before + ThrowableConsumer.execute(configFilePath, path -> { + File configFile = path.toFile(); + FileUtils.forceMkdirParent(configFile); // A directory to be watched - File watchedDirectory = file.isFile() ? file.getParentFile() : file.isDirectory() ? file : null; + File watchedDirectory = configFile.getParentFile(); if (watchedDirectory != null) { watchedDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS); } @@ -201,16 +204,19 @@ public void removeListener(String key, String group, ConfigurationListener liste private void doInListener(String key, String group, BiConsumer> consumer) { watchService.ifPresent(watchService -> { - // Initializes watchService if there is not any listener - if (listenersRepository.isEmpty()) { - initWatchService(watchService); - } + lock.lock(); + try { + // Initializes watchService if there is not any listener + if (listenersRepository.isEmpty()) { + initWatchService(watchService); + } - File keyFile = keyFile(key, group); - if (keyFile.exists()) { // keyFile must exist - Path watchedFilePath = keyFile.toPath(); - List listeners = getListeners(watchedFilePath); - consumer.accept(watchedFilePath, listeners); + File configFile = configFile(key, group); + Path configFilePath = configFile.toPath(); + List listeners = getListeners(configFilePath); + consumer.accept(configFilePath, listeners); + } finally { + lock.unlock(); } }); } @@ -218,43 +224,67 @@ private void doInListener(String key, String group, BiConsumer { // Async execution while (true) { - WatchKey watchKey = watchService.poll(); - if (watchKey != null && watchKey.isValid()) { - List> events = watchKey.pollEvents(); - for (WatchEvent event : events) { - WatchEvent.Kind kind = event.kind(); - // configChangeType's key to match WatchEvent's Kind - ConfigChangeType configChangeType = CONFIG_CHANGE_TYPES_MAP.get(kind.name()); - if (configChangeType != null) { - Path parentPath = (Path) watchKey.watchable(); - Path currentPath = (Path) event.context(); - fireConfigChangeEvent(parentPath.resolve(currentPath), configChangeType); + WatchKey watchKey = null; + try { + watchKey = watchService.take(); + if (watchKey.isValid()) { + for (WatchEvent event : watchKey.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + // configChangeType's key to match WatchEvent's Kind + ConfigChangeType configChangeType = CONFIG_CHANGE_TYPES_MAP.get(kind.name()); + if (configChangeType != null) { + Path parentPath = (Path) watchKey.watchable(); + Path currentPath = (Path) event.context(); + Path actualPath = parentPath.resolve(currentPath); + fireConfigChangeEvent(actualPath, configChangeType); + } } } + } catch (Exception e) { + e.printStackTrace(); + return; + } finally { + if (watchKey != null) { + // reset + watchKey.reset(); + } } } }); } - private List getListeners(Path watchedFilePath) { - return listenersRepository.computeIfAbsent(watchedFilePath, p -> new LinkedList<>()); + private List getListeners(Path configFilePath) { + return listenersRepository.computeIfAbsent(configFilePath, p -> new LinkedList<>()); } - private void fireConfigChangeEvent(Path watchedFilePath, ConfigChangeType configChangeType) { - File watchedFile = watchedFilePath.toFile(); + private void fireConfigChangeEvent(Path configFilePath, ConfigChangeType configChangeType) { + File watchedFile = configFilePath.toFile(); String key = watchedFile.getName(); - String group = watchedFile.getParentFile().getName(); - String value = getConfig(key, group); - // fire ConfigChangeEvent one by one - getListeners(watchedFilePath).forEach(listener -> { - listener.process(new ConfigChangeEvent(key, value, configChangeType)); - }); + String value = getConfig(watchedFile, -1L); + lock.lock(); + try { + // fire ConfigChangeEvent one by one + getListeners(configFilePath).forEach(listener -> { + listener.process(new ConfigChangeEvent(key, value, configChangeType)); + }); + } finally { + lock.unlock(); + } + } @Override public String getConfig(String key, String group, long timeout) throws IllegalStateException { - File keyFile = keyFile(key, group); - return keyFile.exists() ? execute(() -> readFileToString(keyFile, encoding), timeout) : null; + File configFile = configFile(key, group); + return getConfig(configFile, timeout); + } + + protected String getConfig(File configFile, long timeout) { + return canRead(configFile) ? execute(() -> readFileToString(configFile, encoding), timeout) : null; + } + + private boolean canRead(File file) { + return file.exists() && file.canRead(); } @Override @@ -269,10 +299,10 @@ public Object getInternalProperty(String key) { @Override public boolean publishConfig(String key, String group, String content) { - File keyFile = keyFile(key, group); + File configFile = configFile(key, group); boolean published = false; try { - FileUtils.write(keyFile, content, encoding); + FileUtils.write(configFile, content, encoding); published = true; } catch (IOException e) { if (logger.isErrorEnabled()) { @@ -305,7 +335,9 @@ private V execute(Callable task, long timeout) { value = future.get(timeout, TimeUnit.MILLISECONDS); } } catch (Exception e) { - throw new IllegalStateException(e); + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } } return value; } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java index 39fc5bab6ff..510cadda9b3 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.config.configcenter.file; +import org.apache.commons.io.FileUtils; import org.apache.dubbo.common.URL; import org.junit.jupiter.api.BeforeEach; @@ -27,6 +28,7 @@ import static org.apache.commons.io.FileUtils.deleteQuietly; import static org.apache.dubbo.common.URL.valueOf; +import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP; import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -56,7 +58,7 @@ private String getClassPath() { @Test public void testInit() { - assertEquals(new File(getClassPath(),"config-center"), configuration.getDirectory()); + assertEquals(new File(getClassPath(), "config-center"), configuration.getDirectory()); assertEquals("UTF-8", configuration.getEncoding()); assertEquals(ThreadPoolExecutor.class, configuration.getExecutorService().getClass()); assertEquals(2, ((ThreadPoolExecutor) configuration.getExecutorService()).getMaximumPoolSize()); @@ -80,16 +82,44 @@ public void testAddAndRemoveListener() throws InterruptedException { configuration.addListener(KEY, event -> { processedEvent.set(true); - -// assertEquals(KEY, event.getKey()); -// assertEquals("B", event.getValue()); + assertEquals(KEY, event.getKey()); + System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName()); }); + configuration.publishConfig(KEY, "B"); + while (!processedEvent.get()) { + Thread.sleep(1 * 1000L); + } + + processedEvent.set(false); + configuration.publishConfig(KEY, "C"); + while (!processedEvent.get()) { + Thread.sleep(1 * 1000L); + } + processedEvent.set(false); + configuration.publishConfig(KEY, "D"); while (!processedEvent.get()) { Thread.sleep(1 * 1000L); } + configuration.addListener("test", "test", event -> { + processedEvent.set(true); + assertEquals("test", event.getKey()); + System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName()); + }); + processedEvent.set(false); + configuration.publishConfig("test", "test", "TEST"); + while (!processedEvent.get()) { + Thread.sleep(1 * 1000L); + } + + processedEvent.set(false); + File keyFile = configuration.configFile(KEY, DEFAULT_GROUP); + FileUtils.deleteQuietly(keyFile); + while (!processedEvent.get()) { + Thread.sleep(1 * 1000L); + } } } diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml index f7064cd1703..3e56228a919 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml @@ -21,8 +21,22 @@ http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd "> + + + + + + + + + + + + - + + + diff --git a/dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java b/dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java new file mode 100644 index 00000000000..a6f576639b7 --- /dev/null +++ b/dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java @@ -0,0 +1,164 @@ +package org.apache.dubbo.event; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.HashMap; +import java.util.Map; + +import static java.nio.file.LinkOption.NOFOLLOW_LINKS; +import static java.nio.file.StandardWatchEventKinds.*; + +public class WatchDir { + + private final WatchService watcher; + private final Map keys; + private final boolean recursive; + private boolean trace = false; + + @SuppressWarnings("unchecked") + static WatchEvent cast(WatchEvent event) { + return (WatchEvent)event; + } + + /** + * Register the given directory with the WatchService + */ + private void register(Path dir) throws IOException { + WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); + if (trace) { + Path prev = keys.get(key); + if (prev == null) { + System.out.format("register: %s\n", dir); + } else { + if (!dir.equals(prev)) { + System.out.format("update: %s -> %s\n", prev, dir); + } + } + } + keys.put(key, dir); + } + + /** + * Register the given directory, and all its sub-directories, with the + * WatchService. + */ + private void registerAll(final Path start) throws IOException { + // register directory and sub-directories + Files.walkFileTree(start, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException + { + register(dir); + return FileVisitResult.CONTINUE; + } + }); + } + + /** + * Creates a WatchService and registers the given directory + */ + WatchDir(Path dir, boolean recursive) throws IOException { + this.watcher = FileSystems.getDefault().newWatchService(); + this.keys = new HashMap(); + this.recursive = recursive; + + if (recursive) { + System.out.format("Scanning %s ...\n", dir); + registerAll(dir); + System.out.println("Done."); + } else { + register(dir); + } + + // enable trace after initial registration + this.trace = true; + } + + /** + * Process all events for keys queued to the watcher + */ + void processEvents() { + for (;;) { + + // wait for key to be signalled + WatchKey key; + try { + key = watcher.take(); + } catch (InterruptedException x) { + return; + } +// +// Path dir = keys.get(key); +// if (dir == null) { +// System.err.println("WatchKey not recognized!!"); +// continue; +// } + + for (WatchEvent event: key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + + // TBD - provide example of how OVERFLOW event is handled + if (kind == OVERFLOW) { + continue; + } + + // Context for directory entry event is the file name of entry + WatchEvent ev = cast(event); + Path name = ev.context(); + Path dir = (Path)key.watchable(); + Path child = dir.resolve(name); + + // print out event + System.out.format("%s: %s\n", event.kind().name(), child); + + // if directory is created, and watching recursively, then + // register it and its sub-directories + if (recursive && (kind == ENTRY_CREATE)) { + try { + if (Files.isDirectory(child, NOFOLLOW_LINKS)) { + registerAll(child); + } + } catch (IOException x) { + // ignore to keep sample readbale + } + } + } + + // reset key and remove from set if directory no longer accessible + boolean valid = key.reset(); + if (!valid) { + keys.remove(key); + + // all directories are inaccessible + if (keys.isEmpty()) { + break; + } + } + } + } + + static void usage() { + System.err.println("usage: java WatchDir [-r] dir"); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + // parse arguments + if (args.length == 0 || args.length > 2) + usage(); + boolean recursive = false; + int dirArg = 0; + if (args[0].equals("-r")) { + if (args.length < 2) + usage(); + recursive = true; + dirArg++; + } + + // register directory and process its events + Path dir = Paths.get(args[dirArg]); + new WatchDir(dir, recursive).processEvents(); + } +} \ No newline at end of file From 08089b6f7ec65f6b243bfa942d7e22c2da46ecca Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Tue, 16 Jul 2019 01:29:48 +0800 Subject: [PATCH 04/30] Polish apache/dubbo#4541 : Optimization --- .../file/FileSystemDynamicConfiguration.java | 22 ++- .../java/org/apache/dubbo/event/WatchDir.java | 164 ------------------ 2 files changed, 10 insertions(+), 176 deletions(-) delete mode 100644 dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index b1e0d674881..4c19bafec30 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -241,7 +241,6 @@ private void initWatchService(WatchService watchService) { } } } catch (Exception e) { - e.printStackTrace(); return; } finally { if (watchKey != null) { @@ -254,23 +253,22 @@ private void initWatchService(WatchService watchService) { } private List getListeners(Path configFilePath) { - return listenersRepository.computeIfAbsent(configFilePath, p -> new LinkedList<>()); - } - - private void fireConfigChangeEvent(Path configFilePath, ConfigChangeType configChangeType) { - File watchedFile = configFilePath.toFile(); - String key = watchedFile.getName(); - String value = getConfig(watchedFile, -1L); lock.lock(); try { - // fire ConfigChangeEvent one by one - getListeners(configFilePath).forEach(listener -> { - listener.process(new ConfigChangeEvent(key, value, configChangeType)); - }); + return listenersRepository.computeIfAbsent(configFilePath, p -> new LinkedList<>()); } finally { lock.unlock(); } + } + private void fireConfigChangeEvent(Path configFilePath, ConfigChangeType configChangeType) { + File watchedFile = configFilePath.toFile(); + String key = watchedFile.getName(); + String value = getConfig(watchedFile, -1L); + // fire ConfigChangeEvent one by one + getListeners(configFilePath).forEach(listener -> { + listener.process(new ConfigChangeEvent(key, value, configChangeType)); + }); } @Override diff --git a/dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java b/dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java deleted file mode 100644 index a6f576639b7..00000000000 --- a/dubbo-event/src/test/java/org/apache/dubbo/event/WatchDir.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.apache.dubbo.event; - -import java.io.IOException; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.HashMap; -import java.util.Map; - -import static java.nio.file.LinkOption.NOFOLLOW_LINKS; -import static java.nio.file.StandardWatchEventKinds.*; - -public class WatchDir { - - private final WatchService watcher; - private final Map keys; - private final boolean recursive; - private boolean trace = false; - - @SuppressWarnings("unchecked") - static WatchEvent cast(WatchEvent event) { - return (WatchEvent)event; - } - - /** - * Register the given directory with the WatchService - */ - private void register(Path dir) throws IOException { - WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); - if (trace) { - Path prev = keys.get(key); - if (prev == null) { - System.out.format("register: %s\n", dir); - } else { - if (!dir.equals(prev)) { - System.out.format("update: %s -> %s\n", prev, dir); - } - } - } - keys.put(key, dir); - } - - /** - * Register the given directory, and all its sub-directories, with the - * WatchService. - */ - private void registerAll(final Path start) throws IOException { - // register directory and sub-directories - Files.walkFileTree(start, new SimpleFileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) - throws IOException - { - register(dir); - return FileVisitResult.CONTINUE; - } - }); - } - - /** - * Creates a WatchService and registers the given directory - */ - WatchDir(Path dir, boolean recursive) throws IOException { - this.watcher = FileSystems.getDefault().newWatchService(); - this.keys = new HashMap(); - this.recursive = recursive; - - if (recursive) { - System.out.format("Scanning %s ...\n", dir); - registerAll(dir); - System.out.println("Done."); - } else { - register(dir); - } - - // enable trace after initial registration - this.trace = true; - } - - /** - * Process all events for keys queued to the watcher - */ - void processEvents() { - for (;;) { - - // wait for key to be signalled - WatchKey key; - try { - key = watcher.take(); - } catch (InterruptedException x) { - return; - } -// -// Path dir = keys.get(key); -// if (dir == null) { -// System.err.println("WatchKey not recognized!!"); -// continue; -// } - - for (WatchEvent event: key.pollEvents()) { - WatchEvent.Kind kind = event.kind(); - - // TBD - provide example of how OVERFLOW event is handled - if (kind == OVERFLOW) { - continue; - } - - // Context for directory entry event is the file name of entry - WatchEvent ev = cast(event); - Path name = ev.context(); - Path dir = (Path)key.watchable(); - Path child = dir.resolve(name); - - // print out event - System.out.format("%s: %s\n", event.kind().name(), child); - - // if directory is created, and watching recursively, then - // register it and its sub-directories - if (recursive && (kind == ENTRY_CREATE)) { - try { - if (Files.isDirectory(child, NOFOLLOW_LINKS)) { - registerAll(child); - } - } catch (IOException x) { - // ignore to keep sample readbale - } - } - } - - // reset key and remove from set if directory no longer accessible - boolean valid = key.reset(); - if (!valid) { - keys.remove(key); - - // all directories are inaccessible - if (keys.isEmpty()) { - break; - } - } - } - } - - static void usage() { - System.err.println("usage: java WatchDir [-r] dir"); - System.exit(-1); - } - - public static void main(String[] args) throws IOException { - // parse arguments - if (args.length == 0 || args.length > 2) - usage(); - boolean recursive = false; - int dirArg = 0; - if (args[0].equals("-r")) { - if (args.length < 2) - usage(); - recursive = true; - dirArg++; - } - - // register directory and process its events - Path dir = Paths.get(args[dirArg]); - new WatchDir(dir, recursive).processEvents(); - } -} \ No newline at end of file From cdd9338ef37cbae2f274debe7015a64fe3158463 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Tue, 16 Jul 2019 14:41:12 +0800 Subject: [PATCH 05/30] Polish apache/dubbo#4541 : Add the compatibility for PollingWatchService on the some platforms --- .../file/FileSystemDynamicConfiguration.java | 315 +++++++++++++----- .../FileSystemDynamicConfigurationTest.java | 9 +- 2 files changed, 237 insertions(+), 87 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index 4c19bafec30..c6d78aff42f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -24,6 +24,7 @@ import org.apache.dubbo.common.function.ThrowableConsumer; import org.apache.dubbo.common.utils.NamedThreadFactory; +import com.sun.nio.file.SensitivityWatchEventModifier; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -46,18 +47,22 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.stream.Collectors; +import java.util.stream.Stream; -import static java.lang.Integer.max; import static java.lang.String.format; -import static java.nio.file.StandardWatchEventKinds.*; +import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import static java.util.Collections.unmodifiableMap; -import static java.util.concurrent.Executors.newFixedThreadPool; -import static java.util.stream.Stream.of; +import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.commons.io.FileUtils.readFileToString; import static org.apache.dubbo.common.utils.StringUtils.isBlank; @@ -72,21 +77,29 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { public static final String CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME = "dubbo.config-center.thread-pool.name"; - public static final String CONFIG_CENTER_THREAD_POOL_SIZE_PARAM_NAME = "dubbo.config-center.thread-pool.size"; - public static final String CONFIG_CENTER_ENCODING_PARAM_NAME = "dubbo.config-center.encoding"; public static final String DEFAULT_CONFIG_CENTER_DIR_PATH = System.getProperty("user.home") + File.separator + ".dubbo" + File.separator + "config-center"; - public static final String DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME = "dubbo-config-center"; + public static final String DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME = "dubbo-config-center-workers"; - public static final int DEFAULT_CONFIG_CENTER_THREAD_POOL_SIZE = 2; public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8"; - private static final WatchEvent.Kind[] INTEREST_PATH_KINDS = - new WatchEvent.Kind[]{ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY}; + private static final WatchEvent.Kind[] INTEREST_PATH_KINDS = of(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); + + /** + * The class name of {@linkplain sun.nio.fs.PollingWatchService} + */ + private static final String POLLING_WATCH_SERVICE_CLASS_NAME = "sun.nio.fs.PollingWatchService"; + + private static final int WORKERS_THREAD_POOL_SIZE = 1; + + /** + * Logger + */ + private static final Log logger = LogFactory.getLog(FileSystemDynamicConfiguration.class); /** * The unmodifiable map for {@link ConfigChangeType} whose key is the {@link WatchEvent.Kind#name() name} of @@ -102,10 +115,6 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { } }); - /** - * Logger - */ - private final Log logger = LogFactory.getLog(getClass()); /** * The Root Directory for config center @@ -113,9 +122,19 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { private final File directory; /** - * The thread pool used to execute I/O tasks + * The thread pool for config's tasks + * + * @see ScheduledThreadPoolExecutor + */ + private final ScheduledThreadPoolExecutor workersThreadPool; + + /** + * The thread pool for {@link WatchEvent WatchEvents} loop + * It's optional if there is not any {@link ConfigurationListener} registration + * + * @see ExecutorService */ - private final ExecutorService executorService; + private ExecutorService watchEventsLoopThreadPool; private final String encoding; @@ -125,52 +144,30 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { private final Lock lock = new ReentrantLock(); + /** + * Is Pooling Based Watch Service + * + * @see #isPoolingBasedWatchService(Optional) + */ + private final boolean basedPoolingWatchService; + + private final WatchEvent.Modifier[] modifiers; + + /** + * the delay to {@link #publishConfig(String, String, String) publish} in seconds. + * If null, execute indirectly + */ + private final Integer delayToPublish; + public FileSystemDynamicConfiguration(URL url) { this.directory = initDirectory(url); - this.executorService = initExecutorService(url); - this.encoding = url.getParameter(CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); + this.workersThreadPool = newWorkersThreadPool(url); + this.encoding = getEncoding(url); this.watchService = newWatchService(); this.listenersRepository = new LinkedHashMap<>(); - } - - private Optional newWatchService() { - Optional watchService = null; - FileSystem fileSystem = FileSystems.getDefault(); - try { - watchService = Optional.of(fileSystem.newWatchService()); - } catch (IOException e) { - if (logger.isErrorEnabled()) { - logger.error(e.getMessage(), e); - } - watchService = Optional.empty(); - } - return watchService; - } - - private File initDirectory(URL url) { - String directoryPath = url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH); - File rootDirectory = new File(url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH)); - if (!rootDirectory.exists() && !rootDirectory.mkdirs()) { - throw new IllegalStateException(format("Dubbo config center directory[%s] can't be created!", - directoryPath)); - } - return rootDirectory; - } - - private ExecutorService initExecutorService(URL url) { - String threadPoolName = url.getParameter(CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME, DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME); - int threadPoolSize = url.getParameter(CONFIG_CENTER_THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_CONFIG_CENTER_THREAD_POOL_SIZE); - threadPoolSize = max(threadPoolSize, 2); - return newFixedThreadPool(threadPoolSize, new NamedThreadFactory(threadPoolName)); - } - - protected File groupDirectory(String group) { - String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; - return new File(directory, actualGroup); - } - - protected File configFile(String key, String group) { - return new File(groupDirectory(group), key); + this.basedPoolingWatchService = isPoolingBasedWatchService(watchService); + this.modifiers = initWatchEventModifiers(watchService); + this.delayToPublish = initDelayToPublish(modifiers); } @Override @@ -184,7 +181,7 @@ public void addListener(String key, String group, ConfigurationListener listener // A directory to be watched File watchedDirectory = configFile.getParentFile(); if (watchedDirectory != null) { - watchedDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS); + watchedDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, modifiers); } }); } @@ -202,27 +199,56 @@ public void removeListener(String key, String group, ConfigurationListener liste }); } + protected File groupDirectory(String group) { + String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; + return new File(directory, actualGroup); + } + + protected File configFile(String key, String group) { + return new File(groupDirectory(group), key); + } + + private void doInListener(String key, String group, BiConsumer> consumer) { watchService.ifPresent(watchService -> { - lock.lock(); - try { - // Initializes watchService if there is not any listener - if (listenersRepository.isEmpty()) { - initWatchService(watchService); + executeMutually(() -> { + // process the WatchEvents if there is not any listener + if (!initWatchEventsLoopThreadPool()) { + processWatchEventsLoop(watchService); } File configFile = configFile(key, group); Path configFilePath = configFile.toPath(); List listeners = getListeners(configFilePath); consumer.accept(configFilePath, listeners); - } finally { - lock.unlock(); - } + + // Nothing to return + return void.class; + }); }); } - private void initWatchService(WatchService watchService) { - executorService.submit(() -> { // Async execution + /** + * Initializes {@link #watchEventsLoopThreadPool} and return initialized or not + * + * @return if watchEventsLoopThreadPool is not null, return null + */ + private boolean initWatchEventsLoopThreadPool() { + boolean initialized = this.watchEventsLoopThreadPool != null; + if (!initialized) { + this.watchEventsLoopThreadPool = newWatchEventsLoopThreadPool(); + } + return initialized; + } + + /** + * Process the {@link WatchEvent WatchEvents} loop in async execution + * + * @param watchService {@link WatchService} + */ + private void processWatchEventsLoop(WatchService watchService) { + + getWatchEventsLoopThreadPool().execute(() -> { // WatchEvents Loop while (true) { WatchKey watchKey = null; try { @@ -253,12 +279,7 @@ private void initWatchService(WatchService watchService) { } private List getListeners(Path configFilePath) { - lock.lock(); - try { - return listenersRepository.computeIfAbsent(configFilePath, p -> new LinkedList<>()); - } finally { - lock.unlock(); - } + return executeMutually(() -> listenersRepository.computeIfAbsent(configFilePath, p -> new LinkedList<>())); } private void fireConfigChangeEvent(Path configFilePath, ConfigChangeType configChangeType) { @@ -278,7 +299,7 @@ public String getConfig(String key, String group, long timeout) throws IllegalSt } protected String getConfig(File configFile, long timeout) { - return canRead(configFile) ? execute(() -> readFileToString(configFile, encoding), timeout) : null; + return canRead(configFile) ? execute(() -> readFileToString(configFile, getEncoding()), timeout) : null; } private boolean canRead(File file) { @@ -297,22 +318,40 @@ public Object getInternalProperty(String key) { @Override public boolean publishConfig(String key, String group, String content) { + File configFile = configFile(key, group); + boolean published = false; + try { - FileUtils.write(configFile, content, encoding); - published = true; - } catch (IOException e) { + published = publish(() -> { + FileUtils.write(configFile, content, getEncoding()); + return true; + }); + } catch (Exception e) { if (logger.isErrorEnabled()) { logger.error(e.getMessage()); } } + return published; } + private boolean publish(Callable callable) throws Exception { + + Integer delay = getDelayToPublish(); + + if (delay != null) { + ScheduledFuture future = getWorkersThreadPool().schedule(callable, delay.longValue(), SECONDS); + return future.get(); + } else { + return callable.call(); + } + } + @Override public Set getConfigKeys(String group) throws UnsupportedOperationException { - return of(groupDirectory(group).listFiles(File::isFile)) + return Stream.of(groupDirectory(group).listFiles(File::isFile)) .map(File::getName) .collect(Collectors.toSet()); } @@ -329,7 +368,7 @@ private V execute(Callable task, long timeout) { if (timeout < 1) { // less or equal 0 value = task.call(); } else { - Future future = executorService.submit(task); + Future future = workersThreadPool.submit(task); value = future.get(timeout, TimeUnit.MILLISECONDS); } } catch (Exception e) { @@ -344,11 +383,121 @@ protected File getDirectory() { return directory; } - protected ExecutorService getExecutorService() { - return executorService; + protected ScheduledThreadPoolExecutor getWorkersThreadPool() { + return workersThreadPool; } protected String getEncoding() { return encoding; } + + protected Integer getDelayToPublish() { + return delayToPublish; + } + + protected boolean isBasedPoolingWatchService() { + return basedPoolingWatchService; + } + + public ExecutorService getWatchEventsLoopThreadPool() { + return watchEventsLoopThreadPool; + } + + private V executeMutually(Callable callable) { + V value = null; + lock.lock(); + try { + value = callable.call(); + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } finally { + lock.unlock(); + } + + return value; + } + + private static T[] of(T... values) { + return values; + } + + + private static Integer initDelayToPublish(WatchEvent.Modifier[] modifiers) { + return Stream.of(modifiers) + .filter(modifier -> modifier instanceof SensitivityWatchEventModifier) + .map(SensitivityWatchEventModifier.class::cast) + .map(SensitivityWatchEventModifier::sensitivityValueInSeconds) + .max(Integer::compareTo) + .orElse(null); + } + + /** + * Create a new {@link ScheduledThreadPoolExecutor} whose core and max pool size both are {@link #WORKERS_THREAD_POOL_SIZE 1} + * + * @param url + * @return + */ + private static ScheduledThreadPoolExecutor newWorkersThreadPool(URL url) { + String threadPoolName = url.getParameter(CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME, DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME); + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(WORKERS_THREAD_POOL_SIZE, new NamedThreadFactory(threadPoolName)); + executor.setMaximumPoolSize(WORKERS_THREAD_POOL_SIZE); + return executor; + } + + private static WatchEvent.Modifier[] initWatchEventModifiers(Optional watchService) { + if (isPoolingBasedWatchService(watchService)) { // If based on PollingWatchService, High sensitivity will be used + return of(SensitivityWatchEventModifier.HIGH); + } else { + return of(); + } + } + + /** + * It's whether the argument of {@link WatchService} is based on {@linkplain sun.nio.fs.PollingWatchService} + * or not. + *

+ * Some platforms do not provide the native implementation of {@link WatchService}, just use + * {@linkplain sun.nio.fs.PollingWatchService} in periodic poll file modifications. + * + * @param watchService the instance of {@link WatchService} + * @return if based, return true, or false + */ + private static boolean isPoolingBasedWatchService(Optional watchService) { + String className = watchService.map(Object::getClass).map(Class::getName).orElse(null); + return POLLING_WATCH_SERVICE_CLASS_NAME.equals(className); + } + + private static Optional newWatchService() { + Optional watchService = null; + FileSystem fileSystem = FileSystems.getDefault(); + try { + watchService = Optional.of(fileSystem.newWatchService()); + } catch (IOException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + watchService = Optional.empty(); + } + return watchService; + } + + private static File initDirectory(URL url) { + String directoryPath = url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH); + File rootDirectory = new File(url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH)); + if (!rootDirectory.exists() && !rootDirectory.mkdirs()) { + throw new IllegalStateException(format("Dubbo config center directory[%s] can't be created!", + directoryPath)); + } + return rootDirectory; + } + + private static String getEncoding(URL url) { + return url.getParameter(CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); + } + + private static ExecutorService newWatchEventsLoopThreadPool() { + return newSingleThreadExecutor(new NamedThreadFactory("dubbo-config-center-watch-events-loop")); + } } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java index 510cadda9b3..687aceac300 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -16,13 +16,14 @@ */ package org.apache.dubbo.common.config.configcenter.file; -import org.apache.commons.io.FileUtils; import org.apache.dubbo.common.URL; +import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.File; +import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicBoolean; @@ -60,9 +61,9 @@ private String getClassPath() { public void testInit() { assertEquals(new File(getClassPath(), "config-center"), configuration.getDirectory()); assertEquals("UTF-8", configuration.getEncoding()); - assertEquals(ThreadPoolExecutor.class, configuration.getExecutorService().getClass()); - assertEquals(2, ((ThreadPoolExecutor) configuration.getExecutorService()).getMaximumPoolSize()); - assertEquals(2, ((ThreadPoolExecutor) configuration.getExecutorService()).getCorePoolSize()); + assertEquals(ScheduledThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass()); + assertEquals(1, ((ThreadPoolExecutor) configuration.getWorkersThreadPool()).getMaximumPoolSize()); + assertEquals(1, ((ThreadPoolExecutor) configuration.getWorkersThreadPool()).getCorePoolSize()); } @Test From f0408f72888f3eb528b2f8e45dedc8c3d9a48cec Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 17 Jul 2019 00:27:38 +0800 Subject: [PATCH 06/30] Polish apache/dubbo#4541 : Add delay publish without ThreadPoolExecutor --- .../configcenter/DynamicConfiguration.java | 13 +- .../DynamicConfigurationFactory.java | 2 +- .../file/FileSystemDynamicConfiguration.java | 349 ++++++++++++------ .../nop/NopDynamicConfiguration.java | 1 + .../nop/NopDynamicConfigurationFactory.java | 1 + .../FileSystemDynamicConfigurationTest.java | 35 +- dubbo-common/src/test/resources/log4j.xml | 4 +- 7 files changed, 277 insertions(+), 128 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java index 8115669aa49..aad9ef08d31 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java @@ -37,7 +37,7 @@ *

  • 3. addListener/removeListener, add or remove listeners for governance rules or config items that need to watch.
  • * */ -public interface DynamicConfiguration extends Configuration { +public interface DynamicConfiguration extends Configuration, AutoCloseable { String DEFAULT_GROUP = "dubbo"; @@ -202,6 +202,17 @@ default Map getConfigs(String group, long timeout) throws Unsupp return Collections.unmodifiableMap(configs); } + /** + * Close the configuration + * + * @throws Exception + * @since 2.7.4 + */ + @Override + default void close() throws Exception { + throw new UnsupportedOperationException(); + } + /** * Find DynamicConfiguration instance * diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java index 42e090f0cd8..7a28ca2af2d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java @@ -22,7 +22,7 @@ /** * The factory interface to create the instance of {@link DynamicConfiguration} */ -@SPI("filesystem") // 2.7.4 change the +@SPI("filesystem") // 2.7.4 change the default SPI implementation public interface DynamicConfigurationFactory { DynamicConfiguration getDynamicConfiguration(URL url); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index c6d78aff42f..495bd8c828b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -37,21 +37,23 @@ import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -60,8 +62,10 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; +import static java.util.Collections.emptySet; import static java.util.Collections.unmodifiableMap; -import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static java.util.concurrent.Executors.newFixedThreadPool; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.commons.io.FileUtils.readFileToString; import static org.apache.dubbo.common.utils.StringUtils.isBlank; @@ -73,17 +77,22 @@ */ public class FileSystemDynamicConfiguration implements DynamicConfiguration { - public static final String CONFIG_CENTER_DIR_PARAM_NAME = "dubbo.config-center.dir"; + public static final String PARAM_NAME_PREFIX = "dubbo.config-center."; - public static final String CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME = "dubbo.config-center.thread-pool.name"; + public static final String CONFIG_CENTER_DIR_PARAM_NAME = PARAM_NAME_PREFIX + "dir"; - public static final String CONFIG_CENTER_ENCODING_PARAM_NAME = "dubbo.config-center.encoding"; + public static final String THREAD_POOL_PREFIX_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.prefix"; + + public static final String THREAD_POOL_SIZE_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.size"; + + public static final String CONFIG_CENTER_ENCODING_PARAM_NAME = PARAM_NAME_PREFIX + "encoding"; public static final String DEFAULT_CONFIG_CENTER_DIR_PATH = System.getProperty("user.home") + File.separator + ".dubbo" + File.separator + "config-center"; - public static final String DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME = "dubbo-config-center-workers"; + public static final String DEFAULT_THREAD_POOL_PREFIX = PARAM_NAME_PREFIX + "workers"; + public static final int DEFAULT_THREAD_POOL_SIZE = 1; public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8"; @@ -94,7 +103,7 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { */ private static final String POLLING_WATCH_SERVICE_CLASS_NAME = "sun.nio.fs.PollingWatchService"; - private static final int WORKERS_THREAD_POOL_SIZE = 1; + private static final int THREAD_POOL_SIZE = 1; /** * Logger @@ -115,59 +124,81 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { } }); + private static final Optional watchService; /** - * The Root Directory for config center + * Is Pooling Based Watch Service + * + * @see #detectPoolingBasedWatchService(Optional) */ - private final File directory; + private static final boolean basedPoolingWatchService; + + private static final WatchEvent.Modifier[] modifiers; /** - * The thread pool for config's tasks - * - * @see ScheduledThreadPoolExecutor + * the delay to {@link #publishConfig(String, String, String) publishConfig} in seconds. + * If null, execute indirectly */ - private final ScheduledThreadPoolExecutor workersThreadPool; + private static final Integer delayToPublish; /** * The thread pool for {@link WatchEvent WatchEvents} loop * It's optional if there is not any {@link ConfigurationListener} registration * - * @see ExecutorService + * @see ThreadPoolExecutor */ - private ExecutorService watchEventsLoopThreadPool; + private static final ThreadPoolExecutor watchEventsLoopThreadPool; - private final String encoding; + // static initialization + static { + watchService = newWatchService(); + basedPoolingWatchService = detectPoolingBasedWatchService(watchService); + modifiers = initWatchEventModifiers(); + delayToPublish = initDelayToPublish(modifiers); + watchEventsLoopThreadPool = newWatchEventsLoopThreadPool(); + } - private final Optional watchService; + /** + * The Root Directory for config center + */ + private final File directory; - private final Map> listenersRepository; + private final String threadPoolPrefixName; - private final Lock lock = new ReentrantLock(); + private final String encoding; /** - * Is Pooling Based Watch Service - * - * @see #isPoolingBasedWatchService(Optional) + * The thread pool for workers who executes the tasks */ - private final boolean basedPoolingWatchService; - - private final WatchEvent.Modifier[] modifiers; + private final ThreadPoolExecutor workersThreadPool; /** - * the delay to {@link #publishConfig(String, String, String) publish} in seconds. - * If null, execute indirectly + * The {@link Set} of {@link #configDirectory(String) directories} that may be processing, + *

    + * if {@link #isBasedPoolingWatchService()} is false, this properties will be + * {@link Collections#emptySet() empty} + * + * @see #initProcessingDirectories() */ - private final Integer delayToPublish; + private final Set processingDirectories; + + private final Map> listenersRepository; public FileSystemDynamicConfiguration(URL url) { this.directory = initDirectory(url); - this.workersThreadPool = newWorkersThreadPool(url); + this.threadPoolPrefixName = getThreadPoolPrefixName(url); this.encoding = getEncoding(url); - this.watchService = newWatchService(); + this.workersThreadPool = initWorkersThreadPool(url); + this.processingDirectories = initProcessingDirectories(); this.listenersRepository = new LinkedHashMap<>(); - this.basedPoolingWatchService = isPoolingBasedWatchService(watchService); - this.modifiers = initWatchEventModifiers(watchService); - this.delayToPublish = initDelayToPublish(modifiers); + } + + private Set initProcessingDirectories() { + return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet(); + } + + private static String getThreadPoolPrefixName(URL url) { + return url.getParameter(THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); } @Override @@ -175,13 +206,13 @@ public void addListener(String key, String group, ConfigurationListener listener doInListener(key, group, (configFilePath, listeners) -> { if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before - ThrowableConsumer.execute(configFilePath, path -> { - File configFile = path.toFile(); + ThrowableConsumer.execute(configFilePath, configFile -> { FileUtils.forceMkdirParent(configFile); // A directory to be watched - File watchedDirectory = configFile.getParentFile(); - if (watchedDirectory != null) { - watchedDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, modifiers); + File configDirectory = configFile.getParentFile(); + if (configDirectory != null) { + // Register the configDirectory + configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, modifiers); } }); } @@ -199,46 +230,35 @@ public void removeListener(String key, String group, ConfigurationListener liste }); } - protected File groupDirectory(String group) { + protected File configDirectory(String group) { String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; return new File(directory, actualGroup); } protected File configFile(String key, String group) { - return new File(groupDirectory(group), key); + return new File(configDirectory(group), key); } - - private void doInListener(String key, String group, BiConsumer> consumer) { + private void doInListener(String key, String group, BiConsumer> consumer) { watchService.ifPresent(watchService -> { - executeMutually(() -> { - // process the WatchEvents if there is not any listener - if (!initWatchEventsLoopThreadPool()) { - processWatchEventsLoop(watchService); + File configFile = configFile(key, group); + executeMutually(configFile.getParentFile(), () -> { + // process the WatchEvents if not start + if (!isProcessingWatchEvents()) { + processWatchEvents(watchService); } - File configFile = configFile(key, group); - Path configFilePath = configFile.toPath(); - List listeners = getListeners(configFilePath); - consumer.accept(configFilePath, listeners); + List listeners = getListeners(configFile); + consumer.accept(configFile, listeners); // Nothing to return - return void.class; + return null; }); }); } - /** - * Initializes {@link #watchEventsLoopThreadPool} and return initialized or not - * - * @return if watchEventsLoopThreadPool is not null, return null - */ - private boolean initWatchEventsLoopThreadPool() { - boolean initialized = this.watchEventsLoopThreadPool != null; - if (!initialized) { - this.watchEventsLoopThreadPool = newWatchEventsLoopThreadPool(); - } - return initialized; + private static boolean isProcessingWatchEvents() { + return getWatchEventsLoopThreadPool().getActiveCount() > 0; } /** @@ -246,8 +266,7 @@ private boolean initWatchEventsLoopThreadPool() { * * @param watchService {@link WatchService} */ - private void processWatchEventsLoop(WatchService watchService) { - + private void processWatchEvents(WatchService watchService) { getWatchEventsLoopThreadPool().execute(() -> { // WatchEvents Loop while (true) { WatchKey watchKey = null; @@ -259,10 +278,15 @@ private void processWatchEventsLoop(WatchService watchService) { // configChangeType's key to match WatchEvent's Kind ConfigChangeType configChangeType = CONFIG_CHANGE_TYPES_MAP.get(kind.name()); if (configChangeType != null) { - Path parentPath = (Path) watchKey.watchable(); + Path configDirectoryPath = (Path) watchKey.watchable(); Path currentPath = (Path) event.context(); - Path actualPath = parentPath.resolve(currentPath); - fireConfigChangeEvent(actualPath, configChangeType); + Path configFilePath = configDirectoryPath.resolve(currentPath); + File configDirectory = configDirectoryPath.toFile(); + executeMutually(configDirectory, () -> { + fireConfigChangeEvent(configFilePath.toFile(), configChangeType); + signalConfigDirectory(configDirectory); + return null; + }); } } } @@ -278,17 +302,42 @@ private void processWatchEventsLoop(WatchService watchService) { }); } - private List getListeners(Path configFilePath) { - return executeMutually(() -> listenersRepository.computeIfAbsent(configFilePath, p -> new LinkedList<>())); + private void signalConfigDirectory(File configDirectory) { + if (isBasedPoolingWatchService()) { + // remove configDirectory from processing set because it's done + removeProcessingDirectory(configDirectory); + // notify configDirectory + notifyProcessingDirectory(configDirectory); + if (logger.isDebugEnabled()) { + logger.debug(format("The config directory[%s] is signalled...", configDirectory.getName())); + } + } } - private void fireConfigChangeEvent(Path configFilePath, ConfigChangeType configChangeType) { - File watchedFile = configFilePath.toFile(); - String key = watchedFile.getName(); - String value = getConfig(watchedFile, -1L); + private void removeProcessingDirectory(File configDirectory) { + processingDirectories.remove(configDirectory); + } + + private void notifyProcessingDirectory(File configDirectory) { + configDirectory.notifyAll(); + } + + private List getListeners(File configFile) { + return listenersRepository.computeIfAbsent(configFile, p -> new LinkedList<>()); + } + + private void fireConfigChangeEvent(File configFile, ConfigChangeType configChangeType) { + String key = configFile.getName(); + String value = getConfig(configFile, -1L); // fire ConfigChangeEvent one by one - getListeners(configFilePath).forEach(listener -> { - listener.process(new ConfigChangeEvent(key, value, configChangeType)); + getListeners(configFile).forEach(listener -> { + try { + listener.process(new ConfigChangeEvent(key, value, configChangeType)); + } catch (Throwable e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } }); } @@ -324,7 +373,7 @@ public boolean publishConfig(String key, String group, String content) { boolean published = false; try { - published = publish(() -> { + published = publishConfig(key, group, configFile, () -> { FileUtils.write(configFile, content, getEncoding()); return true; }); @@ -337,21 +386,81 @@ public boolean publishConfig(String key, String group, String content) { return published; } - private boolean publish(Callable callable) throws Exception { + private ThreadPoolExecutor initWorkersThreadPool(URL url) { + int size = url.getParameter(THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE); + String prefix = url.getParameter(THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); + return (ThreadPoolExecutor) newFixedThreadPool(size, new NamedThreadFactory(prefix)); + } - Integer delay = getDelayToPublish(); + private ScheduledThreadPoolExecutor newWorkersThreadPool(File groupDirectory) { + String group = groupDirectory.getName(); + ThreadFactory threadFactory = newThreadFactory(group); + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(THREAD_POOL_SIZE, threadFactory); + executor.setMaximumPoolSize(THREAD_POOL_SIZE); + return executor; + } - if (delay != null) { - ScheduledFuture future = getWorkersThreadPool().schedule(callable, delay.longValue(), SECONDS); - return future.get(); - } else { - return callable.call(); + private ThreadFactory newThreadFactory(String group) { + return new NamedThreadFactory(String.format("%s[%s]", threadPoolPrefixName, group)); + } + + private boolean publishConfig(String key, String group, File configFile, Callable callable) throws Exception { + // Must be based on PoolingWatchService and has listeners under config file + if (isBasedPoolingWatchService()) { + File configDirectory = configFile.getParentFile(); + executeMutually(configDirectory, () -> { + if (hasListeners(configFile) && isProcessing(configDirectory)) { + Integer delayToPublish = getDelayToPublish(); + if (delayToPublish != null) { + // wait for delay in seconds + long timeout = SECONDS.toMillis(delayToPublish); + if (logger.isDebugEnabled()) { + logger.debug(format("The config[key : %s, group : %s] is about to delay publish in %d ms.", + key, group, timeout)); + } + configDirectory.wait(timeout); + } + } + addProcessing(configDirectory); + + return null; + }); } + + return callable.call(); + } + + private boolean hasListeners(File configFile) { + return getListeners(configFile).size() > 0; + } + + /** + * Is processing on {@link #configDirectory(String) config directory} + * + * @param configDirectory {@link #configDirectory(String) config directory} + * @return if processing , return true, or false + */ + private boolean isProcessing(File configDirectory) { + return processingDirectories.contains(configDirectory); + } + + private void addProcessing(File configDirectory) { + processingDirectories.add(configDirectory); + } + + private boolean asyncPublish(ScheduledThreadPoolExecutor executor, Callable callable) throws + Exception { + + Integer delay = getDelayToPublish(); + + ScheduledFuture future = executor.schedule(callable, delay.longValue(), SECONDS); + + return future.get(); } @Override public Set getConfigKeys(String group) throws UnsupportedOperationException { - return Stream.of(groupDirectory(group).listFiles(File::isFile)) + return Stream.of(configDirectory(group).listFiles(File::isFile)) .map(File::getName) .collect(Collectors.toSet()); } @@ -361,6 +470,11 @@ public Map getConfigs(String group) throws UnsupportedOperationE return getConfigs(group, -1); } + @Override + public void close() throws Exception { + // TODO + } + private V execute(Callable task, long timeout) { V value = null; try { @@ -383,7 +497,7 @@ protected File getDirectory() { return directory; } - protected ScheduledThreadPoolExecutor getWorkersThreadPool() { + protected ThreadPoolExecutor getWorkersThreadPool() { return workersThreadPool; } @@ -395,27 +509,33 @@ protected Integer getDelayToPublish() { return delayToPublish; } - protected boolean isBasedPoolingWatchService() { + /** + * It's whether the implementation of {@link WatchService} is based on {@linkplain sun.nio.fs.PollingWatchService} + * or not. + *

    + * + * @return if based, return true, or false + * @see #detectPoolingBasedWatchService(Optional) + */ + protected static boolean isBasedPoolingWatchService() { return basedPoolingWatchService; } - public ExecutorService getWatchEventsLoopThreadPool() { + protected static ThreadPoolExecutor getWatchEventsLoopThreadPool() { return watchEventsLoopThreadPool; } - private V executeMutually(Callable callable) { + private V executeMutually(Object mutex, Callable callable) { V value = null; - lock.lock(); - try { - value = callable.call(); - } catch (Exception e) { - if (logger.isErrorEnabled()) { - logger.error(e.getMessage(), e); + synchronized (mutex) { + try { + value = callable.call(); + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } } - } finally { - lock.unlock(); } - return value; } @@ -423,7 +543,6 @@ private static T[] of(T... values) { return values; } - private static Integer initDelayToPublish(WatchEvent.Modifier[] modifiers) { return Stream.of(modifiers) .filter(modifier -> modifier instanceof SensitivityWatchEventModifier) @@ -433,21 +552,8 @@ private static Integer initDelayToPublish(WatchEvent.Modifier[] modifiers) { .orElse(null); } - /** - * Create a new {@link ScheduledThreadPoolExecutor} whose core and max pool size both are {@link #WORKERS_THREAD_POOL_SIZE 1} - * - * @param url - * @return - */ - private static ScheduledThreadPoolExecutor newWorkersThreadPool(URL url) { - String threadPoolName = url.getParameter(CONFIG_CENTER_THREAD_POOL_NAME_PARAM_NAME, DEFAULT_CONFIG_CENTER_THREAD_POOL_NAME); - ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(WORKERS_THREAD_POOL_SIZE, new NamedThreadFactory(threadPoolName)); - executor.setMaximumPoolSize(WORKERS_THREAD_POOL_SIZE); - return executor; - } - - private static WatchEvent.Modifier[] initWatchEventModifiers(Optional watchService) { - if (isPoolingBasedWatchService(watchService)) { // If based on PollingWatchService, High sensitivity will be used + private static WatchEvent.Modifier[] initWatchEventModifiers() { + if (isBasedPoolingWatchService()) { // If based on PollingWatchService, High sensitivity will be used return of(SensitivityWatchEventModifier.HIGH); } else { return of(); @@ -455,7 +561,7 @@ private static WatchEvent.Modifier[] initWatchEventModifiers(Optional * Some platforms do not provide the native implementation of {@link WatchService}, just use @@ -464,7 +570,7 @@ private static WatchEvent.Modifier[] initWatchEventModifiers(Optionaltrue, or false */ - private static boolean isPoolingBasedWatchService(Optional watchService) { + private static boolean detectPoolingBasedWatchService(Optional watchService) { String className = watchService.map(Object::getClass).map(Class::getName).orElse(null); return POLLING_WATCH_SERVICE_CLASS_NAME.equals(className); } @@ -497,7 +603,10 @@ private static String getEncoding(URL url) { return url.getParameter(CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); } - private static ExecutorService newWatchEventsLoopThreadPool() { - return newSingleThreadExecutor(new NamedThreadFactory("dubbo-config-center-watch-events-loop")); + private static ThreadPoolExecutor newWatchEventsLoopThreadPool() { + return new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE, + 0L, MILLISECONDS, + new SynchronousQueue(), + new NamedThreadFactory("dubbo-config-center-watch-events-loop", true)); } -} +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java index 14accb28a23..a69f115ab71 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java @@ -28,6 +28,7 @@ * The default extension of {@link DynamicConfiguration}. If user does not specify a config centre, or specifies one * that is not a valid extension, it will default to this one. */ +@Deprecated public class NopDynamicConfiguration implements DynamicConfiguration { public NopDynamicConfiguration(URL url) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java index bd45e7f736e..487f70da6bb 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java @@ -23,6 +23,7 @@ /** * */ +@Deprecated public class NopDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory { @Override diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java index 687aceac300..9097b3ea4ee 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -23,15 +23,17 @@ import org.junit.jupiter.api.Test; import java.io.File; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicBoolean; +import static java.util.Collections.singleton; import static org.apache.commons.io.FileUtils.deleteQuietly; import static org.apache.dubbo.common.URL.valueOf; import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP; import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -59,20 +61,40 @@ private String getClassPath() { @Test public void testInit() { + assertEquals(new File(getClassPath(), "config-center"), configuration.getDirectory()); assertEquals("UTF-8", configuration.getEncoding()); - assertEquals(ScheduledThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass()); - assertEquals(1, ((ThreadPoolExecutor) configuration.getWorkersThreadPool()).getMaximumPoolSize()); - assertEquals(1, ((ThreadPoolExecutor) configuration.getWorkersThreadPool()).getCorePoolSize()); + assertEquals(ThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass()); + assertEquals(1, (configuration.getWorkersThreadPool()).getCorePoolSize()); + assertEquals(1, (configuration.getWorkersThreadPool()).getMaximumPoolSize()); + assertNotNull(configuration.getWatchEventsLoopThreadPool()); + assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getCorePoolSize()); + assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize()); + + if (configuration.isBasedPoolingWatchService()) { + assertEquals(2, configuration.getDelayToPublish()); + } else { + assertNull(configuration.getDelayToPublish()); + } } @Test public void testPublishAndGetConfig() { + assertTrue(configuration.publishConfig(KEY, CONTENT)); + assertTrue(configuration.publishConfig(KEY, CONTENT)); assertTrue(configuration.publishConfig(KEY, CONTENT)); assertEquals(CONTENT, configuration.getConfig(KEY)); assertTrue(configuration.getConfigs(null).size() > 0); } + @Test + public void testGetConfigs() { + assertTrue(configuration.publishConfig(KEY, CONTENT)); + + assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP)); + + } + @Test public void testAddAndRemoveListener() throws InterruptedException { @@ -116,6 +138,11 @@ public void testAddAndRemoveListener() throws InterruptedException { Thread.sleep(1 * 1000L); } + configuration.publishConfig("test", "test", "TEST"); + configuration.publishConfig("test", "test", "TEST"); + configuration.publishConfig("test", "test", "TEST"); + + processedEvent.set(false); File keyFile = configuration.configFile(KEY, DEFAULT_GROUP); FileUtils.deleteQuietly(keyFile); diff --git a/dubbo-common/src/test/resources/log4j.xml b/dubbo-common/src/test/resources/log4j.xml index bfb523c0cc3..21ea447138c 100644 --- a/dubbo-common/src/test/resources/log4j.xml +++ b/dubbo-common/src/test/resources/log4j.xml @@ -21,14 +21,14 @@ - + - + \ No newline at end of file From 5f354a0c6ccfbfc57d69694d61a824380d4ec4b4 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 17 Jul 2019 14:23:05 +0800 Subject: [PATCH 07/30] Polish apache/dubbo#4541 : Refactor the extension name --- .../DynamicConfigurationFactory.java | 2 +- ...FileSystemDynamicConfigurationFactory.java | 2 +- ...g.configcenter.DynamicConfigurationFactory | 2 +- .../DynamicConfigurationFactoryTest.java | 39 +++++++++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java index 7a28ca2af2d..4875a1b8d19 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java @@ -22,7 +22,7 @@ /** * The factory interface to create the instance of {@link DynamicConfiguration} */ -@SPI("filesystem") // 2.7.4 change the default SPI implementation +@SPI("file") // 2.7.4 change the default SPI implementation public interface DynamicConfigurationFactory { DynamicConfiguration getDynamicConfiguration(URL url); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java index 4c23e36594b..f2a13322c67 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java @@ -30,6 +30,6 @@ public class FileSystemDynamicConfigurationFactory extends AbstractDynamicConfig @Override protected DynamicConfiguration createDynamicConfiguration(URL url) { - return null; + return new FileSystemDynamicConfiguration(url); } } diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory index 7cb20dc81fd..f6fe6d68fcc 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory @@ -1,2 +1,2 @@ nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory -filesystem=org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory \ No newline at end of file +file=org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory \ No newline at end of file diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java new file mode 100644 index 00000000000..eacd3eed1e3 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java @@ -0,0 +1,39 @@ +/* + * 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.common.config.configcenter; + +import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory; + +import org.junit.jupiter.api.Test; + +import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link DynamicConfigurationFactory} Test + * + * @since 2.7.4 + */ +public class DynamicConfigurationFactoryTest { + + @Test + public void testDefaultExtension() { + DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension(); + assertEquals(FileSystemDynamicConfigurationFactory.class, factory.getClass()); + assertEquals(factory, getExtensionLoader(DynamicConfigurationFactory.class).getExtension("file")); + } +} From 8152a7579a1eacf92e23d4e5c8181b3cea499adb Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 17 Jul 2019 16:33:03 +0800 Subject: [PATCH 08/30] Polish apache/dubbo#4541 : Add remove ops --- .../configcenter/DynamicConfiguration.java | 27 ++++- .../file/FileSystemDynamicConfiguration.java | 98 +++++++++---------- .../FileSystemDynamicConfigurationTest.java | 16 ++- 3 files changed, 86 insertions(+), 55 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java index aad9ef08d31..df4f4526954 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java @@ -134,7 +134,7 @@ default String getConfigs(String key, String group) throws IllegalStateException /** - * Publish Config mapped to the given key and the given group. + * Publish Config mapped to the given key under the {@link #DEFAULT_GROUP default group} * * @param key the key to represent a configuration * @param content the content of configuration @@ -160,6 +160,31 @@ default boolean publishConfig(String key, String group, String content) throws U throw new UnsupportedOperationException("No support"); } + /** + * Remove Config mapped to the given key under the {@link #DEFAULT_GROUP default group} + * + * @param key the key to represent a configuration + * @return the content of configuration was removed + * @throws UnsupportedOperationException If the under layer does not support + * @since 2.7.4 + */ + default String removeConfig(String key) throws UnsupportedOperationException { + return removeConfig(key, DEFAULT_GROUP); + } + + /** + * Remove Config mapped to the given key and the given group. + * + * @param key the key to represent a configuration + * @param group the group where the key belongs to + * @return the content of configuration was removed + * @throws UnsupportedOperationException If the under layer does not support + * @since 2.7.4 + */ + default String removeConfig(String key, String group) throws UnsupportedOperationException { + throw new UnsupportedOperationException("No support"); + } + /** * Get the config keys by the specified group * diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index 495bd8c828b..3860353154a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.function.ThrowableConsumer; +import org.apache.dubbo.common.function.ThrowableFunction; import org.apache.dubbo.common.utils.NamedThreadFactory; import com.sun.nio.file.SensitivityWatchEventModifier; @@ -48,13 +49,11 @@ import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.Future; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -136,10 +135,9 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { private static final WatchEvent.Modifier[] modifiers; /** - * the delay to {@link #publishConfig(String, String, String) publishConfig} in seconds. - * If null, execute indirectly + * the delay to action in seconds. If null, execute indirectly */ - private static final Integer delayToPublish; + private static final Integer delayAction; /** * The thread pool for {@link WatchEvent WatchEvents} loop @@ -154,7 +152,7 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { watchService = newWatchService(); basedPoolingWatchService = detectPoolingBasedWatchService(watchService); modifiers = initWatchEventModifiers(); - delayToPublish = initDelayToPublish(modifiers); + delayAction = initDelayAction(modifiers); watchEventsLoopThreadPool = newWatchEventsLoopThreadPool(); } @@ -367,23 +365,22 @@ public Object getInternalProperty(String key) { @Override public boolean publishConfig(String key, String group, String content) { + return delay(key, group, configFile -> { + FileUtils.write(configFile, content, getEncoding()); + return true; + }); + } - File configFile = configFile(key, group); + @Override + public String removeConfig(String key, String group) { + return delay(key, group, configFile -> { - boolean published = false; + String content = getConfig(configFile, -1L); - try { - published = publishConfig(key, group, configFile, () -> { - FileUtils.write(configFile, content, getEncoding()); - return true; - }); - } catch (Exception e) { - if (logger.isErrorEnabled()) { - logger.error(e.getMessage()); - } - } + FileUtils.deleteQuietly(configFile); - return published; + return content; + }); } private ThreadPoolExecutor initWorkersThreadPool(URL url) { @@ -392,42 +389,49 @@ private ThreadPoolExecutor initWorkersThreadPool(URL url) { return (ThreadPoolExecutor) newFixedThreadPool(size, new NamedThreadFactory(prefix)); } - private ScheduledThreadPoolExecutor newWorkersThreadPool(File groupDirectory) { - String group = groupDirectory.getName(); - ThreadFactory threadFactory = newThreadFactory(group); - ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(THREAD_POOL_SIZE, threadFactory); - executor.setMaximumPoolSize(THREAD_POOL_SIZE); - return executor; - } - - private ThreadFactory newThreadFactory(String group) { - return new NamedThreadFactory(String.format("%s[%s]", threadPoolPrefixName, group)); - } - - private boolean publishConfig(String key, String group, File configFile, Callable callable) throws Exception { + /** + * Delay action for {@link #configFile(String, String) config file} + * + * @param key the key to represent a configuration + * @param group the group where the key belongs to + * @param function the customized {@link Function function} with {@link File} + * @param the computed value + * @return + */ + protected V delay(String key, String group, ThrowableFunction function) { + File configFile = configFile(key, group); // Must be based on PoolingWatchService and has listeners under config file if (isBasedPoolingWatchService()) { File configDirectory = configFile.getParentFile(); executeMutually(configDirectory, () -> { if (hasListeners(configFile) && isProcessing(configDirectory)) { - Integer delayToPublish = getDelayToPublish(); - if (delayToPublish != null) { + Integer delay = getDelayAction(); + if (delay != null) { // wait for delay in seconds - long timeout = SECONDS.toMillis(delayToPublish); + long timeout = SECONDS.toMillis(delay); if (logger.isDebugEnabled()) { - logger.debug(format("The config[key : %s, group : %s] is about to delay publish in %d ms.", + logger.debug(format("The config[key : %s, group : %s] is about to delay in %d ms.", key, group, timeout)); } configDirectory.wait(timeout); } } addProcessing(configDirectory); - return null; }); } - return callable.call(); + V value = null; + + try { + value = function.apply(configFile); + } catch (Throwable e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } + + return value; } private boolean hasListeners(File configFile) { @@ -448,16 +452,6 @@ private void addProcessing(File configDirectory) { processingDirectories.add(configDirectory); } - private boolean asyncPublish(ScheduledThreadPoolExecutor executor, Callable callable) throws - Exception { - - Integer delay = getDelayToPublish(); - - ScheduledFuture future = executor.schedule(callable, delay.longValue(), SECONDS); - - return future.get(); - } - @Override public Set getConfigKeys(String group) throws UnsupportedOperationException { return Stream.of(configDirectory(group).listFiles(File::isFile)) @@ -505,8 +499,8 @@ protected String getEncoding() { return encoding; } - protected Integer getDelayToPublish() { - return delayToPublish; + protected Integer getDelayAction() { + return delayAction; } /** @@ -543,7 +537,7 @@ private static T[] of(T... values) { return values; } - private static Integer initDelayToPublish(WatchEvent.Modifier[] modifiers) { + private static Integer initDelayAction(WatchEvent.Modifier[] modifiers) { return Stream.of(modifiers) .filter(modifier -> modifier instanceof SensitivityWatchEventModifier) .map(SensitivityWatchEventModifier.class::cast) diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java index 9097b3ea4ee..2b76e326d95 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -72,9 +72,9 @@ public void testInit() { assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize()); if (configuration.isBasedPoolingWatchService()) { - assertEquals(2, configuration.getDelayToPublish()); + assertEquals(2, configuration.getDelayAction()); } else { - assertNull(configuration.getDelayToPublish()); + assertNull(configuration.getDelayAction()); } } @@ -87,6 +87,18 @@ public void testPublishAndGetConfig() { assertTrue(configuration.getConfigs(null).size() > 0); } + @Test + public void testPublishAndRemoveConfig() throws InterruptedException { + assertTrue(configuration.publishConfig(KEY, CONTENT)); + configuration.addListener(KEY, event -> { + System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName()); + + }); + assertTrue(configuration.publishConfig(KEY, CONTENT)); + assertEquals(CONTENT, configuration.removeConfig(KEY)); + Thread.sleep(configuration.getDelayAction() * 1000); + } + @Test public void testGetConfigs() { assertTrue(configuration.publishConfig(KEY, CONTENT)); From df1a2587e18caf5c4c27c5f04ba988ac6981ac8a Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 17 Jul 2019 18:00:59 +0800 Subject: [PATCH 09/30] Polish apache/dubbo#4541 : Add testable constructor --- .../file/FileSystemDynamicConfiguration.java | 62 ++++++++++--------- .../FileSystemDynamicConfigurationTest.java | 10 +-- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index 3860353154a..e15474cfb0d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -137,7 +137,7 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { /** * the delay to action in seconds. If null, execute indirectly */ - private static final Integer delayAction; + private static final Integer delay; /** * The thread pool for {@link WatchEvent WatchEvents} loop @@ -152,16 +152,14 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { watchService = newWatchService(); basedPoolingWatchService = detectPoolingBasedWatchService(watchService); modifiers = initWatchEventModifiers(); - delayAction = initDelayAction(modifiers); + delay = initDelay(modifiers); watchEventsLoopThreadPool = newWatchEventsLoopThreadPool(); } /** * The Root Directory for config center */ - private final File directory; - - private final String threadPoolPrefixName; + private final File rootDirectory; private final String encoding; @@ -183,10 +181,16 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { private final Map> listenersRepository; public FileSystemDynamicConfiguration(URL url) { - this.directory = initDirectory(url); - this.threadPoolPrefixName = getThreadPoolPrefixName(url); - this.encoding = getEncoding(url); - this.workersThreadPool = initWorkersThreadPool(url); + this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url)); + } + + public FileSystemDynamicConfiguration(File rootDirectory, String encoding, + String threadPoolPrefixName, + int threadPoolSize + ) { + this.rootDirectory = rootDirectory; + this.encoding = encoding; + this.workersThreadPool = initWorkersThreadPool(threadPoolPrefixName, threadPoolSize); this.processingDirectories = initProcessingDirectories(); this.listenersRepository = new LinkedHashMap<>(); } @@ -195,10 +199,6 @@ private Set initProcessingDirectories() { return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet(); } - private static String getThreadPoolPrefixName(URL url) { - return url.getParameter(THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); - } - @Override public void addListener(String key, String group, ConfigurationListener listener) { doInListener(key, group, (configFilePath, listeners) -> { @@ -206,7 +206,7 @@ public void addListener(String key, String group, ConfigurationListener listener if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before ThrowableConsumer.execute(configFilePath, configFile -> { FileUtils.forceMkdirParent(configFile); - // A directory to be watched + // A rootDirectory to be watched File configDirectory = configFile.getParentFile(); if (configDirectory != null) { // Register the configDirectory @@ -230,7 +230,7 @@ public void removeListener(String key, String group, ConfigurationListener liste protected File configDirectory(String group) { String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; - return new File(directory, actualGroup); + return new File(rootDirectory, actualGroup); } protected File configFile(String key, String group) { @@ -307,7 +307,7 @@ private void signalConfigDirectory(File configDirectory) { // notify configDirectory notifyProcessingDirectory(configDirectory); if (logger.isDebugEnabled()) { - logger.debug(format("The config directory[%s] is signalled...", configDirectory.getName())); + logger.debug(format("The config rootDirectory[%s] is signalled...", configDirectory.getName())); } } } @@ -383,9 +383,7 @@ public String removeConfig(String key, String group) { }); } - private ThreadPoolExecutor initWorkersThreadPool(URL url) { - int size = url.getParameter(THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE); - String prefix = url.getParameter(THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); + private ThreadPoolExecutor initWorkersThreadPool(String prefix, int size) { return (ThreadPoolExecutor) newFixedThreadPool(size, new NamedThreadFactory(prefix)); } @@ -405,7 +403,7 @@ protected V delay(String key, String group, ThrowableFunction funct File configDirectory = configFile.getParentFile(); executeMutually(configDirectory, () -> { if (hasListeners(configFile) && isProcessing(configDirectory)) { - Integer delay = getDelayAction(); + Integer delay = getDelay(); if (delay != null) { // wait for delay in seconds long timeout = SECONDS.toMillis(delay); @@ -439,9 +437,9 @@ private boolean hasListeners(File configFile) { } /** - * Is processing on {@link #configDirectory(String) config directory} + * Is processing on {@link #configDirectory(String) config rootDirectory} * - * @param configDirectory {@link #configDirectory(String) config directory} + * @param configDirectory {@link #configDirectory(String) config rootDirectory} * @return if processing , return true, or false */ private boolean isProcessing(File configDirectory) { @@ -487,8 +485,8 @@ private V execute(Callable task, long timeout) { return value; } - protected File getDirectory() { - return directory; + protected File getRootDirectory() { + return rootDirectory; } protected ThreadPoolExecutor getWorkersThreadPool() { @@ -499,8 +497,8 @@ protected String getEncoding() { return encoding; } - protected Integer getDelayAction() { - return delayAction; + protected Integer getDelay() { + return delay; } /** @@ -515,6 +513,10 @@ protected static boolean isBasedPoolingWatchService() { return basedPoolingWatchService; } + private static String getThreadPoolPrefixName(URL url) { + return url.getParameter(THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); + } + protected static ThreadPoolExecutor getWatchEventsLoopThreadPool() { return watchEventsLoopThreadPool; } @@ -537,7 +539,7 @@ private static T[] of(T... values) { return values; } - private static Integer initDelayAction(WatchEvent.Modifier[] modifiers) { + private static Integer initDelay(WatchEvent.Modifier[] modifiers) { return Stream.of(modifiers) .filter(modifier -> modifier instanceof SensitivityWatchEventModifier) .map(SensitivityWatchEventModifier.class::cast) @@ -587,7 +589,7 @@ private static File initDirectory(URL url) { String directoryPath = url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH); File rootDirectory = new File(url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH)); if (!rootDirectory.exists() && !rootDirectory.mkdirs()) { - throw new IllegalStateException(format("Dubbo config center directory[%s] can't be created!", + throw new IllegalStateException(format("Dubbo config center rootDirectory[%s] can't be created!", directoryPath)); } return rootDirectory; @@ -597,6 +599,10 @@ private static String getEncoding(URL url) { return url.getParameter(CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); } + private static int getThreadPoolSize(URL url) { + return url.getParameter(THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE); + } + private static ThreadPoolExecutor newWatchEventsLoopThreadPool() { return new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE, 0L, MILLISECONDS, diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java index 2b76e326d95..852ff6a28f9 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -52,7 +52,7 @@ public void init() { String classPath = getClassPath(); URL url = valueOf("dubbo://127.0.0.1:20880").addParameter(CONFIG_CENTER_DIR_PARAM_NAME, classPath + File.separator + "config-center"); configuration = new FileSystemDynamicConfiguration(url); - deleteQuietly(configuration.getDirectory()); + deleteQuietly(configuration.getRootDirectory()); } private String getClassPath() { @@ -62,7 +62,7 @@ private String getClassPath() { @Test public void testInit() { - assertEquals(new File(getClassPath(), "config-center"), configuration.getDirectory()); + assertEquals(new File(getClassPath(), "config-center"), configuration.getRootDirectory()); assertEquals("UTF-8", configuration.getEncoding()); assertEquals(ThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass()); assertEquals(1, (configuration.getWorkersThreadPool()).getCorePoolSize()); @@ -72,9 +72,9 @@ public void testInit() { assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize()); if (configuration.isBasedPoolingWatchService()) { - assertEquals(2, configuration.getDelayAction()); + assertEquals(2, configuration.getDelay()); } else { - assertNull(configuration.getDelayAction()); + assertNull(configuration.getDelay()); } } @@ -96,7 +96,7 @@ public void testPublishAndRemoveConfig() throws InterruptedException { }); assertTrue(configuration.publishConfig(KEY, CONTENT)); assertEquals(CONTENT, configuration.removeConfig(KEY)); - Thread.sleep(configuration.getDelayAction() * 1000); + Thread.sleep(configuration.getDelay() * 1000); } @Test From 52c0205eb4e9df04577c832fd0278452c77e01c6 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 17 Jul 2019 22:30:40 +0800 Subject: [PATCH 10/30] Polish apache/dubbo#4541 : Add getConfigGroups method --- .../configcenter/DynamicConfiguration.java | 17 ++++++++++++++--- .../file/FileSystemDynamicConfiguration.java | 11 ++++++++++- .../FileSystemDynamicConfigurationTest.java | 8 ++++++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java index df4f4526954..1bb31156a07 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java @@ -185,11 +185,22 @@ default String removeConfig(String key, String group) throws UnsupportedOperatio throw new UnsupportedOperationException("No support"); } + /** + * Get all groups + * + * @return the read-only non-null {@link Set set} of config keys + * @throws UnsupportedOperationException If the under layer does not support + * @since 2.7.4 + */ + default Set getConfigGroups() throws UnsupportedOperationException { + throw new UnsupportedOperationException("No support"); + } + /** * Get the config keys by the specified group * * @param group the specified group - * @return the read-only non-null sorted {@link Set set} of config keys + * @return the read-only non-null {@link Set set} of config keys * @throws UnsupportedOperationException If the under layer does not support * @since 2.7.4 */ @@ -201,7 +212,7 @@ default Set getConfigKeys(String group) throws UnsupportedOperationExcep * Get the {@link Map} with with config keys and contents value by the specified group * * @param group the specified group - * @return the read-only non-null sorted {@link Map map} + * @return the read-only non-null {@link Map map} * @throws UnsupportedOperationException If the under layer does not support * @since 2.7.4 */ @@ -214,7 +225,7 @@ default Map getConfigs(String group) throws UnsupportedOperation * * @param group the specified group * @param timeout the millisecond for timeout - * @return the read-only non-null sorted {@link Map map} + * @return the read-only non-null {@link Map map} * @throws UnsupportedOperationException If the under layer does not support * @throws IllegalStateException If timeout exceeds * @since 2.7.4 diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index e15474cfb0d..867c581e2b9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -451,12 +451,21 @@ private void addProcessing(File configDirectory) { } @Override - public Set getConfigKeys(String group) throws UnsupportedOperationException { + public Set getConfigKeys(String group) { return Stream.of(configDirectory(group).listFiles(File::isFile)) .map(File::getName) .collect(Collectors.toSet()); } + + @Override + public Set getConfigGroups() { + return Stream.of(getRootDirectory().listFiles()) + .filter(File::isDirectory) + .map(File::getName) + .collect(Collectors.toSet()); + } + @Override public Map getConfigs(String group) throws UnsupportedOperationException { return getConfigs(group, -1); diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java index 852ff6a28f9..c68cd4c6d24 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java @@ -100,11 +100,15 @@ public void testPublishAndRemoveConfig() throws InterruptedException { } @Test - public void testGetConfigs() { + public void testGetConfigsAndGroups() { assertTrue(configuration.publishConfig(KEY, CONTENT)); - assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP)); + assertEquals(singleton(DEFAULT_GROUP), configuration.getConfigGroups()); + assertTrue(configuration.publishConfig(KEY, "test", CONTENT)); + assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP)); + assertTrue(configuration.getConfigGroups().contains(DEFAULT_GROUP)); + assertTrue(configuration.getConfigGroups().contains("test")); } @Test From 293a70dfbfbbc6fbaae5a7fc676bd2fda2f12daf Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Sat, 20 Jul 2019 14:44:09 +0800 Subject: [PATCH 11/30] Polish apache/dubbo#4610 : [Refactor] Refactor the bootstrap module --- .../dubbo/bootstrap/AbstractSettings.java | 36 -- .../dubbo/bootstrap/ApplicationSettings.java | 127 ------ .../dubbo/bootstrap/DubboBootstrap.java | 303 +++++++------- .../dubbo/bootstrap/ProtocolSettings.java | 215 ---------- .../dubbo/bootstrap/ReferenceSettings.java | 334 --------------- .../dubbo/bootstrap/RegistrySettings.java | 164 -------- .../dubbo/bootstrap/ServiceSettings.java | 384 ------------------ .../org/apache/dubbo/bootstrap/Settings.java | 32 -- .../DubboServiceConsumerBootstrap.java | 32 +- .../DubboServiceProviderBootstrap.java | 16 +- .../config/builders/AbstractBuilder.java | 2 +- .../dubbo/config/context/ConfigManager.java | 24 +- 12 files changed, 191 insertions(+), 1478 deletions(-) delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java delete mode 100644 dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java deleted file mode 100644 index 7ed1de54983..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java +++ /dev/null @@ -1,36 +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.bootstrap; - -/** - * Abstract {@link Settings} - * - * @since 2.7.4 - */ -public class AbstractSettings implements Settings { - - private final DubboBootstrap dubboBootstrap; - - public AbstractSettings(DubboBootstrap dubboBootstrap) { - this.dubboBootstrap = dubboBootstrap; - } - - @Override - public DubboBootstrap next() { - return dubboBootstrap; - } -} diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java deleted file mode 100644 index 23934f07404..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java +++ /dev/null @@ -1,127 +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.bootstrap; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.builders.ApplicationBuilder; - -import java.util.Map; - -/** - * {@link ApplicationConfig Application} settings - * - * @since 2.7.4 - */ -public class ApplicationSettings extends AbstractSettings { - - private final ApplicationBuilder builder; - - public ApplicationSettings(ApplicationBuilder builder, DubboBootstrap dubboBootstrap) { - super(dubboBootstrap); - this.builder = builder; - } - - public ApplicationSettings version(String version) { - builder.version(version); - return this; - } - - public ApplicationSettings owner(String owner) { - builder.owner(owner); - return this; - } - - public ApplicationSettings organization(String organization) { - builder.organization(organization); - return this; - } - - public ApplicationSettings architecture(String architecture) { - builder.architecture(architecture); - return this; - } - - public ApplicationSettings environment(String environment) { - builder.environment(environment); - return this; - } - - public ApplicationSettings compiler(String compiler) { - builder.compiler(compiler); - return this; - } - - public ApplicationSettings logger(String logger) { - builder.logger(logger); - return this; - } - - public ApplicationSettings monitor(MonitorConfig monitor) { - builder.monitor(monitor); - return this; - } - - public ApplicationSettings monitor(String monitor) { - builder.monitor(monitor); - return this; - } - - public ApplicationSettings isDefault(Boolean isDefault) { - builder.isDefault(isDefault); - return this; - } - - public ApplicationSettings dumpDirectory(String dumpDirectory) { - builder.dumpDirectory(dumpDirectory); - return this; - } - - public ApplicationSettings qosEnable(Boolean qosEnable) { - builder.qosEnable(qosEnable); - return this; - } - - public ApplicationSettings qosPort(Integer qosPort) { - builder.qosPort(qosPort); - return this; - } - - public ApplicationSettings qosAcceptForeignIp(Boolean qosAcceptForeignIp) { - builder.qosAcceptForeignIp(qosAcceptForeignIp); - return this; - } - - public ApplicationSettings shutwait(String shutwait) { - builder.shutwait(shutwait); - return this; - } - - public ApplicationSettings appendParameter(String key, String value) { - builder.appendParameter(key, value); - return this; - } - - public ApplicationSettings appendParameters(Map appendParameters) { - builder.appendParameters(appendParameters); - return this; - } - - ApplicationConfig build() { - return builder.build(); - } -} diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java index d20e3e0d025..1f92aeed5fa 100644 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java +++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java @@ -59,7 +59,6 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -71,9 +70,11 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import static java.util.Arrays.asList; import static java.util.concurrent.Executors.newSingleThreadExecutor; import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.config.context.ConfigManager.getInstance; import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries; /** @@ -91,6 +92,10 @@ public class DubboBootstrap { public static final String DEFAULT_REFERENCE_ID = "REFERENCE#DEFAULT"; + public static final String DEFAULT_PROVIDER_ID = "PROVIDER#DEFAULT"; + + public static final String DEFAULT_CONSUMER_ID = "CONSUMER#DEFAULT"; + private static final String NAME = DubboBootstrap.class.getSimpleName(); private final Logger logger = LoggerFactory.getLogger(getClass()); @@ -105,6 +110,8 @@ public class DubboBootstrap { private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + private final ConfigManager configManager = getInstance(); + /** * Is provider or not */ @@ -121,20 +128,6 @@ public class DubboBootstrap { private ServiceInstance serviceInstance; - private ApplicationBuilder applicationBuilder; - - private ConsumerBuilder consumerBuilder; - - private ProviderBuilder providerBuilder; - - private Map registryBuilders = new HashMap<>(); - - private Map protocolBuilders = new HashMap<>(); - - private Map> serviceBuilders = new HashMap<>(); - - private Map> referenceBuilders = new HashMap<>(); - public DubboBootstrap() { DubboShutdownHook.getDubboShutdownHook().register(); } @@ -150,96 +143,179 @@ public DubboBootstrap onlyRegisterProvider(boolean onlyRegisterProvider) { return this; } - /* accept Config instance */ - public DubboBootstrap application(ApplicationConfig applicationConfig) { - ConfigManager.getInstance().setApplication(applicationConfig); + public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) { + configManager.addMetadataReport(metadataReportConfig); return this; } - public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) { - ConfigManager.getInstance().addConfigCenter(configCenterConfig); + public DubboBootstrap metadataReport(List metadataReportConfigs) { + configManager.addMetadataReport(metadataReportConfigs); return this; } - public DubboBootstrap configCenter(List configCenterConfigs) { - ConfigManager.getInstance().addConfigCenter(configCenterConfigs); - return this; + // {@link ApplicationConfig} correlative methods + + /** + * Set the name of application + * + * @param name the name of application + * @return current {@link DubboBootstrap} instance + */ + public DubboBootstrap application(String name) { + return application(name, builder -> { + // DO NOTHING + }); } - public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) { - ConfigManager.getInstance().addMetadataReport(metadataReportConfig); - return this; + /** + * Set the name of application and it's future build + * + * @param name the name of application + * @param consumerBuilder {@link ApplicationBuilder} + * @return current {@link DubboBootstrap} instance + */ + public DubboBootstrap application(String name, Consumer consumerBuilder) { + ApplicationBuilder builder = createApplicationBuilder(name); + consumerBuilder.accept(builder); + return application(builder.build()); } - public DubboBootstrap metadataReport(List metadataReportConfigs) { - ConfigManager.getInstance().addMetadataReport(metadataReportConfigs); + /** + * Set the {@link ApplicationConfig} + * + * @param applicationConfig the {@link ApplicationConfig} + * @return current {@link DubboBootstrap} instance + */ + public DubboBootstrap application(ApplicationConfig applicationConfig) { + configManager.setApplication(applicationConfig); return this; } + // {@link RegistryConfig} correlative methods + + public DubboBootstrap registry(Consumer consumerBuilder) { + return registry(DEFAULT_REGISTRY_ID, consumerBuilder); + } + + public DubboBootstrap registry(String id, Consumer consumerBuilder) { + RegistryBuilder builder = createRegistryBuilder(id); + consumerBuilder.accept(builder); + return registry(builder.build()); + } + public DubboBootstrap registry(RegistryConfig registryConfig) { - ConfigManager.getInstance().addRegistry(registryConfig, true); - return this; + return registries(asList(registryConfig)); } - public DubboBootstrap registry(List registryConfigs) { - ConfigManager.getInstance().addRegistries(registryConfigs, true); + public DubboBootstrap registries(List registryConfigs) { + configManager.addRegistries(registryConfigs, true); return this; } + // {@link ProtocolConfig} correlative methods + + public DubboBootstrap protocol(Consumer consumerBuilder) { + return protocol(DEFAULT_PROTOCOL_ID, consumerBuilder); + } + + public DubboBootstrap protocol(String id, Consumer consumerBuilder) { + ProtocolBuilder builder = createProtocolBuilder(id); + consumerBuilder.accept(builder); + return protocol(builder.build()); + } + public DubboBootstrap protocol(ProtocolConfig protocolConfig) { - ConfigManager.getInstance().addProtocol(protocolConfig, true); - return this; + return protocols(asList(protocolConfig)); } public DubboBootstrap protocols(List protocolConfigs) { - ConfigManager.getInstance().addProtocols(protocolConfigs, true); + configManager.addProtocols(protocolConfigs, true); return this; } - public DubboBootstrap consumer(ConsumerConfig consumerConfig) { - ConfigManager.getInstance().addConsumer(consumerConfig); - return this; + // {@link ServiceConfig} correlative methods + + public DubboBootstrap service(Consumer> consumerBuilder) { + return service(DEFAULT_SERVICE_ID, consumerBuilder); } - public DubboBootstrap provider(ProviderConfig providerConfig) { - ConfigManager.getInstance().addProvider(providerConfig); - return this; + public DubboBootstrap service(String id, Consumer> consumerBuilder) { + ServiceBuilder builder = createServiceBuilder(id); + consumerBuilder.accept(builder); + return service(builder.build()); } public DubboBootstrap service(ServiceConfig serviceConfig) { - ConfigManager.getInstance().addService(serviceConfig); + configManager.addService(serviceConfig); return this; } + // {@link Reference} correlative methods + + public DubboBootstrap reference(Consumer> consumerBuilder) { + return reference(DEFAULT_REFERENCE_ID, consumerBuilder); + } + + public DubboBootstrap reference(String id, Consumer> consumerBuilder) { + ReferenceBuilder builder = createReferenceBuilder(id); + consumerBuilder.accept(builder); + return reference(builder.build()); + } + public DubboBootstrap reference(ReferenceConfig referenceConfig) { - ConfigManager.getInstance().addReference(referenceConfig); + configManager.addReference(referenceConfig); return this; } - /* accept builder functional interface */ - public DubboBootstrap application(String name, Consumer builder) { - initApplicationBuilder(name); - builder.accept(applicationBuilder); - return this; + // {@link ProviderConfig} correlative methods + + public DubboBootstrap provider(Consumer builderConsumer) { + return provider(DEFAULT_PROVIDER_ID, builderConsumer); } - public DubboBootstrap registry(String id, Consumer builder) { - builder.accept(initRegistryBuilder(id)); - return this; + public DubboBootstrap provider(String id, Consumer builderConsumer) { + ProviderBuilder builder = createProviderBuilder(id); + builderConsumer.accept(builder); + return provider(builder.build()); + } + + public DubboBootstrap provider(ProviderConfig providerConfig) { + return providers(asList(providerConfig)); } - public DubboBootstrap protocol(String id, Consumer builder) { - builder.accept(initProtocolBuilder(id)); + public DubboBootstrap providers(List providerConfigs) { + providerConfigs.forEach(configManager::addProvider); return this; } - public DubboBootstrap service(String id, Consumer> builder) { - builder.accept(initServiceBuilder(id)); + // {@link ConsumerConfig} correlative methods + + public DubboBootstrap consumer(Consumer builderConsumer) { + return consumer(DEFAULT_CONSUMER_ID, builderConsumer); + } + + public DubboBootstrap consumer(String id, Consumer builderConsumer) { + ConsumerBuilder builder = createConsumerBuilder(id); + builderConsumer.accept(builder); + return consumer(builder.build()); + } + + public DubboBootstrap consumer(ConsumerConfig consumerConfig) { + return consumers(asList(consumerConfig)); + } + + public DubboBootstrap consumers(List consumerConfigs) { + consumerConfigs.forEach(configManager::addConsumer); return this; } - public DubboBootstrap reference(String id, Consumer> builder) { - builder.accept(initReferenceBuilder(id)); + // {@link ConfigCenterConfig} correlative methods + public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) { + return configCenter(asList(configCenterConfig)); + } + + public DubboBootstrap configCenter(List configCenterConfigs) { + configManager.addConfigCenter(configCenterConfigs); return this; } @@ -252,30 +328,13 @@ public void init() { return; } - buildApplicationConfig(); - - buildRegistryConfigs(); - - buildProtocolConfigs(); - - buildServiceConfigs(); - - buildReferenceConfigs(); - - clearBuilders(); - startConfigCenter(); + startMetadataReport(); loadRemoteConfigs(); - useRegistryAsConfigCenterIfNecessary(); -// checkApplication(); -// checkProvider(); -// chcckConsumer(); -// checkRegistry(); -// checkProtocol(); -// checkMonitor(); + useRegistryAsConfigCenterIfNecessary(); initialized = true; @@ -285,8 +344,6 @@ public void init() { } private void loadRemoteConfigs() { - ConfigManager configManager = ConfigManager.getInstance(); - // registry ids to registry configs List tmpRegistries = new ArrayList<>(); Set registryIds = configManager.getRegistryIds(); @@ -325,7 +382,6 @@ private void loadRemoteConfigs() { * there's no config center specified explicitly. */ private void useRegistryAsConfigCenterIfNecessary() { - ConfigManager configManager = ConfigManager.getInstance(); configManager.getDefaultRegistries().ifPresent(registryConfigs -> { for (RegistryConfig registryConfig : registryConfigs) { if (registryConfig != null && registryConfig.isZookeeperProtocol()) { @@ -369,13 +425,12 @@ public DubboBootstrap start() { exportServices(); // Not only provider register and some services are exported - if (!onlyRegisterProvider && !ConfigManager.getInstance().getServiceConfigs().isEmpty()) { + if (!onlyRegisterProvider && !configManager.getServiceConfigs().isEmpty()) { /** * export {@link MetadataService} */ - ConfigManager configManager = ConfigManager.getInstance(); // TODO, only export to default registry? - List exportedURLs = exportMetadataService ( + List exportedURLs = exportMetadataService( configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")), configManager.getDefaultRegistries().orElseThrow(() -> new IllegalStateException("No default RegistryConfig")), configManager.getDefaultProtocols().orElseThrow(() -> new IllegalStateException("No default ProtocolConfig")) @@ -450,10 +505,10 @@ public boolean isStarted() { return started; } + /* serve for builder apis, begin */ - private ApplicationBuilder initApplicationBuilder(String name) { - applicationBuilder = new ApplicationBuilder().name(name); - return applicationBuilder; + private ApplicationBuilder createApplicationBuilder(String name) { + return new ApplicationBuilder().name(name); } private RegistryBuilder createRegistryBuilder(String id) { @@ -472,29 +527,21 @@ private ReferenceBuilder createReferenceBuilder(String id) { return new ReferenceBuilder().id(id); } - private RegistryBuilder initRegistryBuilder(String id) { - return registryBuilders.computeIfAbsent(id, this::createRegistryBuilder); + private ProviderBuilder createProviderBuilder(String id) { + return new ProviderBuilder().id(id); } - private ProtocolBuilder initProtocolBuilder(String id) { - return protocolBuilders.computeIfAbsent(id, this::createProtocolBuilder); - } - - private ServiceBuilder initServiceBuilder(String id) { - return serviceBuilders.computeIfAbsent(id, this::createServiceBuilder); - } - - private ReferenceBuilder initReferenceBuilder(String id) { - return referenceBuilders.computeIfAbsent(id, this::createReferenceBuilder); + private ConsumerBuilder createConsumerBuilder(String id) { + return new ConsumerBuilder().id(id); } /* serve for builder apis, end */ private void startMetadataReport() { - ApplicationConfig applicationConfig = ConfigManager.getInstance().getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified.")); + ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified.")); // FIXME, multiple metadata config support. - Set metadataReportConfigs = ConfigManager.getInstance().getMetadataConfigs(); + Set metadataReportConfigs = configManager.getMetadataConfigs(); if (CollectionUtils.isEmpty(metadataReportConfigs)) { if (CommonConstants.METADATA_REMOTE.equals(applicationConfig.getMetadata())) { throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'."); @@ -512,7 +559,7 @@ private void startMetadataReport() { } private void startConfigCenter() { - Set configCenters = ConfigManager.getInstance().getConfigCenters(); + Set configCenters = configManager.getConfigCenters(); if (CollectionUtils.isNotEmpty(configCenters)) { CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration(); @@ -522,7 +569,7 @@ private void startConfigCenter() { } Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration); } - ConfigManager.getInstance().refreshAll(); + configManager.refreshAll(); } private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) { @@ -533,7 +580,7 @@ private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl()); String configContent = dynamicConfiguration.getConfigs(configCenter.getConfigFile(), configCenter.getGroup()); - String appGroup = ConfigManager.getInstance().getApplication().orElse(new ApplicationConfig()).getName(); + String appGroup = configManager.getApplication().orElse(new ApplicationConfig()).getName(); String appConfigContent = null; if (StringUtils.isNotEmpty(appGroup)) { appConfigContent = dynamicConfiguration.getConfigs @@ -581,36 +628,8 @@ private List exportMetadataService(ApplicationConfig applicationConfig, return exporter.export(); } - private void buildApplicationConfig() { - ApplicationConfig applicationConfig = null; - if (applicationBuilder != null) { - applicationConfig = applicationBuilder.build(); - } - ConfigManager.getInstance().setApplication(applicationConfig); - } - - private void buildProtocolConfigs() { - List protocolConfigs = buildConfigs(protocolBuilders); - ConfigManager.getInstance().addProtocols(protocolConfigs, true); - } - - private void buildRegistryConfigs() { - List registryConfigs = buildConfigs(registryBuilders); - ConfigManager.getInstance().addRegistries(registryConfigs, true); - } - - private void buildServiceConfigs() { - List> serviceConfigs = buildConfigs(serviceBuilders); - serviceConfigs.forEach(ConfigManager.getInstance()::addService); - } - - private void buildReferenceConfigs() { - List> referenceConfigs = buildConfigs(referenceBuilders); - referenceConfigs.forEach(ConfigManager.getInstance()::addReference); - } - private void exportServices() { - ConfigManager.getInstance().getServiceConfigs().forEach(this::exportServiceConfig); + configManager.getServiceConfigs().forEach(this::exportServiceConfig); } public void exportServiceConfig(ServiceConfig serviceConfig) { @@ -658,46 +677,30 @@ private void destroy() { } private void destroyProtocolConfigs() { - ConfigManager.getInstance().getProtocols().values().forEach(ProtocolConfig::destroy); + configManager.getProtocols().values().forEach(ProtocolConfig::destroy); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s all ProtocolConfigs have been destroyed."); } } private void destroyReferenceConfigs() { - ConfigManager.getInstance().getReferenceConfigs().forEach(ReferenceConfig::destroy); + configManager.getReferenceConfigs().forEach(ReferenceConfig::destroy); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s all ReferenceConfigs have been destroyed."); } } private void clear() { - - clearBuilders(); - clearConfigs(); - - ConfigManager.getInstance().clear(); } private void clearConfigs() { - ConfigManager.getInstance().clear(); + configManager.clear(); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s configs have been clear."); } } - private void clearBuilders() { - this.applicationBuilder = null; - this.registryBuilders.clear(); - this.protocolBuilders.clear(); - this.serviceBuilders.clear(); - this.referenceBuilders.clear(); - if (logger.isDebugEnabled()) { - logger.debug(NAME + "'s builders have been clear."); - } - } - private void release() { executeMutually(() -> { while (awaited.compareAndSet(false, true)) { diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java deleted file mode 100644 index 5fc49caf524..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java +++ /dev/null @@ -1,215 +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.bootstrap; - -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.builders.ProtocolBuilder; - -import java.util.Map; - -/** - * The settings of {@link ProtocolConfig protcol} - * - * @see ProtocolBuilder - * @since 2.7.4 - */ -public class ProtocolSettings extends AbstractSettings { - - private final ProtocolBuilder builder; - - public ProtocolSettings(ProtocolBuilder builder, DubboBootstrap dubboBootstrap) { - super(dubboBootstrap); - this.builder = builder; - } - - public ProtocolSettings name(String name) { - builder.name(name); - return this; - } - - public ProtocolSettings host(String host) { - builder.host(host); - return this; - } - - public ProtocolSettings port(Integer port) { - builder.port(port); - return this; - } - - public ProtocolSettings contextpath(String contextpath) { - builder.contextpath(contextpath); - return this; - } - - @Deprecated - public ProtocolSettings path(String path) { - builder.path(path); - return this; - } - - public ProtocolSettings threadpool(String threadpool) { - builder.threadpool(threadpool); - return this; - } - - public ProtocolSettings corethreads(Integer corethreads) { - builder.corethreads(corethreads); - return this; - } - - public ProtocolSettings threads(Integer threads) { - builder.threads(threads); - return this; - } - - public ProtocolSettings iothreads(Integer iothreads) { - builder.iothreads(iothreads); - return this; - } - - public ProtocolSettings queues(Integer queues) { - builder.queues(queues); - return this; - } - - public ProtocolSettings accepts(Integer accepts) { - builder.accepts(accepts); - return this; - } - - public ProtocolSettings codec(String codec) { - builder.codec(codec); - return this; - } - - public ProtocolSettings serialization(String serialization) { - builder.serialization(serialization); - return this; - } - - public ProtocolSettings charset(String charset) { - builder.charset(charset); - return this; - } - - public ProtocolSettings payload(Integer payload) { - builder.payload(payload); - return this; - } - - public ProtocolSettings buffer(Integer buffer) { - builder.buffer(buffer); - return this; - } - - public ProtocolSettings heartbeat(Integer heartbeat) { - builder.heartbeat(heartbeat); - return this; - } - - public ProtocolSettings accesslog(String accesslog) { - builder.accesslog(accesslog); - return this; - } - - public ProtocolSettings transporter(String transporter) { - builder.transporter(transporter); - return this; - } - - public ProtocolSettings exchanger(String exchanger) { - builder.exchanger(exchanger); - return this; - } - - public ProtocolSettings dispatcher(String dispatcher) { - builder.dispatcher(dispatcher); - return this; - } - - @Deprecated - public ProtocolSettings dispather(String dispather) { - builder.dispather(dispather); - return this; - } - - public ProtocolSettings networker(String networker) { - builder.networker(networker); - return this; - } - - public ProtocolSettings server(String server) { - builder.server(server); - return this; - } - - public ProtocolSettings client(String client) { - builder.client(client); - return this; - } - - public ProtocolSettings telnet(String telnet) { - builder.telnet(telnet); - return this; - } - - public ProtocolSettings prompt(String prompt) { - builder.prompt(prompt); - return this; - } - - public ProtocolSettings status(String status) { - builder.status(status); - return this; - } - - public ProtocolSettings register(Boolean register) { - builder.register(register); - return this; - } - - public ProtocolSettings keepAlive(Boolean keepAlive) { - builder.keepAlive(keepAlive); - return this; - } - - public ProtocolSettings optimizer(String optimizer) { - builder.optimizer(optimizer); - return this; - } - - public ProtocolSettings extension(String extension) { - builder.extension(extension); - return this; - } - - public ProtocolSettings appendParameter(String key, String value) { - builder.appendParameter(key, value); - return this; - } - - public ProtocolSettings appendParameters(Map appendParameters) { - builder.appendParameters(appendParameters); - return this; - } - - public ProtocolSettings isDefault(Boolean isDefault) { - builder.isDefault(isDefault); - return this; - } -} diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java deleted file mode 100644 index bb24e6e30bf..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java +++ /dev/null @@ -1,334 +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.bootstrap; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConfigCenterConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.MetadataReportConfig; -import org.apache.dubbo.config.MethodConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ReferenceConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.builders.ReferenceBuilder; - -import java.util.List; -import java.util.Map; - -/** - * The settings of {@link ReferenceConfig} - * - * @since 2.7.4 - */ -public class ReferenceSettings extends AbstractSettings { - - private final ReferenceBuilder builder; - - public ReferenceSettings(ReferenceBuilder builder, DubboBootstrap dubboBootstrap) { - super(dubboBootstrap); - this.builder = builder; - } - - public ReferenceSettings interfaceName(String interfaceName) { - builder.interfaceName(interfaceName); - return this; - } - - public ReferenceSettings interfaceClass(Class interfaceClass) { - builder.interfaceClass(interfaceClass); - return this; - } - - public ReferenceSettings client(String client) { - builder.client(client); - return this; - } - - public ReferenceSettings url(String url) { - builder.url(url); - return this; - } - - public ReferenceSettings addMethods(List methods) { - builder.addMethods(methods); - return this; - } - - public ReferenceSettings addMethod(MethodConfig method) { - builder.addMethod(method); - return this; - } - - public ReferenceSettings consumer(ConsumerConfig consumer) { - builder.consumer(consumer); - return this; - } - - public ReferenceSettings protocol(String protocol) { - builder.protocol(protocol); - return this; - } - - public ReferenceSettings check(Boolean check) { - builder.check(check); - return this; - } - - public ReferenceSettings init(Boolean init) { - builder.init(init); - return this; - } - - public ReferenceSettings generic(String generic) { - builder.generic(generic); - return this; - } - - public ReferenceSettings generic(Boolean generic) { - builder.generic(generic); - return this; - } - - @Deprecated - public ReferenceSettings injvm(Boolean injvm) { - builder.injvm(injvm); - return this; - } - - public ReferenceSettings lazy(Boolean lazy) { - builder.lazy(lazy); - return this; - } - - public ReferenceSettings reconnect(String reconnect) { - builder.reconnect(reconnect); - return this; - } - - public ReferenceSettings sticky(Boolean sticky) { - builder.sticky(sticky); - return this; - } - - public ReferenceSettings version(String version) { - builder.version(version); - return this; - } - - public ReferenceSettings group(String group) { - builder.group(group); - return this; - } - - @Deprecated - public ReferenceSettings local(String local) { - builder.local(local); - return this; - } - - @Deprecated - public ReferenceSettings local(Boolean local) { - builder.local(local); - return this; - } - - public ReferenceSettings stub(String stub) { - builder.stub(stub); - return this; - } - - public ReferenceSettings stub(Boolean stub) { - builder.stub(stub); - return this; - } - - public ReferenceSettings monitor(MonitorConfig monitor) { - builder.monitor(monitor); - return this; - } - - public ReferenceSettings monitor(String monitor) { - builder.monitor(monitor); - return this; - } - - public ReferenceSettings proxy(String proxy) { - builder.proxy(proxy); - return this; - } - - public ReferenceSettings cluster(String cluster) { - builder.cluster(cluster); - return this; - } - - public ReferenceSettings filter(String filter) { - builder.filter(filter); - return this; - } - - public ReferenceSettings listener(String listener) { - builder.listener(listener); - return this; - } - - public ReferenceSettings owner(String owner) { - builder.owner(owner); - return this; - } - - public ReferenceSettings connections(Integer connections) { - builder.connections(connections); - return this; - } - - public ReferenceSettings layer(String layer) { - builder.layer(layer); - return this; - } - - public ReferenceSettings application(ApplicationConfig application) { - builder.application(application); - return this; - } - - public ReferenceSettings module(ModuleConfig module) { - builder.module(module); - return this; - } - - public ReferenceSettings addRegistries(List registries) { - builder.addRegistries(registries); - return this; - } - - public ReferenceSettings addRegistry(RegistryConfig registry) { - builder.addRegistry(registry); - return this; - } - - public ReferenceSettings registryIds(String registryIds) { - builder.registryIds(registryIds); - return this; - } - - public ReferenceSettings onconnect(String onconnect) { - builder.onconnect(onconnect); - return this; - } - - public ReferenceSettings ondisconnect(String ondisconnect) { - builder.ondisconnect(ondisconnect); - return this; - } - - public ReferenceSettings metadataReportConfig(MetadataReportConfig metadataReportConfig) { - builder.metadataReportConfig(metadataReportConfig); - return this; - } - - public ReferenceSettings configCenter(ConfigCenterConfig configCenter) { - builder.configCenter(configCenter); - return this; - } - - public ReferenceSettings callbacks(Integer callbacks) { - builder.callbacks(callbacks); - return this; - } - - public ReferenceSettings scope(String scope) { - builder.scope(scope); - return this; - } - - public ReferenceSettings tag(String tag) { - builder.tag(tag); - return this; - } - - public ReferenceSettings timeout(Integer timeout) { - builder.timeout(timeout); - return this; - } - - public ReferenceSettings retries(Integer retries) { - builder.retries(retries); - return this; - } - - public ReferenceSettings actives(Integer actives) { - builder.actives(actives); - return this; - } - - public ReferenceSettings loadbalance(String loadbalance) { - builder.loadbalance(loadbalance); - return this; - } - - public ReferenceSettings async(Boolean async) { - builder.async(async); - return this; - } - - public ReferenceSettings sent(Boolean sent) { - builder.sent(sent); - return this; - } - - public ReferenceSettings mock(String mock) { - builder.mock(mock); - return this; - } - - public ReferenceSettings mock(Boolean mock) { - builder.mock(mock); - return this; - } - - public ReferenceSettings merger(String merger) { - builder.merger(merger); - return this; - } - - public ReferenceSettings cache(String cache) { - builder.cache(cache); - return this; - } - - public ReferenceSettings validation(String validation) { - builder.validation(validation); - return this; - } - - public ReferenceSettings appendParameters(Map appendParameters) { - builder.appendParameters(appendParameters); - return this; - } - - public ReferenceSettings appendParameter(String key, String value) { - builder.appendParameter(key, value); - return this; - } - - public ReferenceSettings forks(Integer forks) { - builder.forks(forks); - return this; - } -} diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java deleted file mode 100644 index 89899acfb14..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java +++ /dev/null @@ -1,164 +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.bootstrap; - -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.builders.RegistryBuilder; - -import java.util.Map; - -/** - * The settings of {@link RegistryConfig} - * - * @since 2.7.4 - */ -public class RegistrySettings extends AbstractSettings { - - private final RegistryBuilder builder; - - public RegistrySettings(RegistryBuilder builder, DubboBootstrap dubboBootstrap) { - super(dubboBootstrap); - this.builder = builder; - } - - public RegistrySettings address(String address) { - builder.address(address); - return this; - } - - public RegistrySettings username(String username) { - builder.username(username); - return this; - } - - public RegistrySettings password(String password) { - builder.password(password); - return this; - } - - public RegistrySettings port(Integer port) { - builder.port(port); - return this; - } - - public RegistrySettings protocol(String protocol) { - builder.protocol(protocol); - return this; - } - - public RegistrySettings transporter(String transporter) { - builder.transporter(transporter); - return this; - } - - @Deprecated - public RegistrySettings transport(String transport) { - builder.transport(transport); - return this; - } - - public RegistrySettings server(String server) { - builder.server(server); - return this; - } - - public RegistrySettings client(String client) { - builder.client(client); - return this; - } - - public RegistrySettings cluster(String cluster) { - builder.cluster(cluster); - return this; - } - - public RegistrySettings group(String group) { - builder.group(group); - return this; - } - - public RegistrySettings version(String version) { - builder.version(version); - return this; - } - - public RegistrySettings timeout(Integer timeout) { - builder.timeout(timeout); - return this; - } - - public RegistrySettings session(Integer session) { - builder.session(session); - return this; - } - - public RegistrySettings file(String file) { - builder.file(file); - return this; - } - - @Deprecated - public RegistrySettings wait(Integer wait) { - builder.wait(wait); - return this; - } - - public RegistrySettings isCheck(Boolean check) { - builder.isCheck(check); - return this; - } - - public RegistrySettings isDynamic(Boolean dynamic) { - builder.isDynamic(dynamic); - return this; - } - - public RegistrySettings register(Boolean register) { - builder.register(register); - return this; - } - - public RegistrySettings subscribe(Boolean subscribe) { - builder.subscribe(subscribe); - return this; - } - - public RegistrySettings appendParameter(String key, String value) { - builder.appendParameter(key, value); - return this; - } - - public RegistrySettings appendParameters(Map appendParameters) { - builder.appendParameters(appendParameters); - return this; - } - - public RegistrySettings isDefault(Boolean isDefault) { - builder.isDefault(isDefault); - return this; - } - - public RegistrySettings simplified(Boolean simplified) { - builder.simplified(simplified); - return this; - } - - public RegistrySettings extraKeys(String extraKeys) { - builder.extraKeys(extraKeys); - return this; - } -} diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java deleted file mode 100644 index b17fa835d80..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java +++ /dev/null @@ -1,384 +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.bootstrap; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConfigCenterConfig; -import org.apache.dubbo.config.MetadataReportConfig; -import org.apache.dubbo.config.MethodConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.ServiceConfig; -import org.apache.dubbo.config.builders.ServiceBuilder; - -import java.util.List; -import java.util.Map; - -/** - * The settings of {@link ServiceConfig Dubbo service} - * - * @since 2.7.4 - */ -public class ServiceSettings extends AbstractSettings { - - private final ServiceBuilder builder; - - public ServiceSettings(ServiceBuilder builder, DubboBootstrap dubboBootstrap) { - super(dubboBootstrap); - this.builder = builder; - } - - public ServiceSettings interfaceName(String interfaceName) { - builder.interfaceName(interfaceName); - return this; - } - - public ServiceSettings interfaceClass(Class interfaceClass) { - builder.interfaceClass(interfaceClass); - return this; - } - - public ServiceSettings ref(S ref) { - builder.ref(ref); - return this; - } - - public ServiceSettings path(String path) { - builder.path(path); - return this; - } - - public ServiceSettings addMethod(MethodConfig method) { - builder.addMethod(method); - return this; - } - - public ServiceSettings addMethods(List methods) { - builder.addMethods(methods); - return this; - } - - public ServiceSettings provider(ProviderConfig provider) { - builder.provider(provider); - return this; - } - - public ServiceSettings providerIds(String providerIds) { - builder.providerIds(providerIds); - return this; - } - - public ServiceSettings generic(String generic) { - builder.generic(generic); - return this; - } - - public ServiceSettings mock(String mock) { - builder.mock(mock); - return this; - } - - public ServiceSettings mock(Boolean mock) { - builder.mock(mock); - return this; - } - - public ServiceSettings version(String version) { - builder.version(version); - return this; - } - - public ServiceSettings group(String group) { - builder.group(group); - return this; - } - - public ServiceSettings deprecated(Boolean deprecated) { - builder.deprecated(deprecated); - return this; - } - - public ServiceSettings delay(Integer delay) { - builder.delay(delay); - return this; - } - - public ServiceSettings export(Boolean export) { - builder.export(export); - return this; - } - - public ServiceSettings weight(Integer weight) { - builder.weight(weight); - return this; - } - - public ServiceSettings document(String document) { - builder.document(document); - return this; - } - - public ServiceSettings dynamic(Boolean dynamic) { - builder.dynamic(dynamic); - return this; - } - - public ServiceSettings token(String token) { - builder.token(token); - return this; - } - - public ServiceSettings token(Boolean token) { - builder.token(token); - return this; - } - - public ServiceSettings accesslog(String accesslog) { - builder.accesslog(accesslog); - return this; - } - - public ServiceSettings accesslog(Boolean accesslog) { - builder.accesslog(accesslog); - return this; - } - - public ServiceSettings addProtocols(List protocols) { - builder.addProtocols(protocols); - return this; - } - - public ServiceSettings addProtocol(ProtocolConfig protocol) { - builder.addProtocol(protocol); - return this; - } - - public ServiceSettings protocolIds(String protocolIds) { - builder.protocolIds(protocolIds); - return this; - } - - public ServiceSettings executes(Integer executes) { - builder.executes(executes); - return this; - } - - public ServiceSettings register(Boolean register) { - builder.register(register); - return this; - } - - public ServiceSettings warmup(Integer warmup) { - builder.warmup(warmup); - return this; - } - - public ServiceSettings serialization(String serialization) { - builder.serialization(serialization); - return this; - } - - @Deprecated - public ServiceSettings local(String local) { - builder.local(local); - return this; - } - - @Deprecated - public ServiceSettings local(Boolean local) { - builder.local(local); - return this; - } - - public ServiceSettings stub(String stub) { - builder.stub(stub); - return this; - } - - public ServiceSettings stub(Boolean stub) { - builder.stub(stub); - return this; - } - - public ServiceSettings monitor(MonitorConfig monitor) { - builder.monitor(monitor); - return this; - } - - public ServiceSettings monitor(String monitor) { - builder.monitor(monitor); - return this; - } - - public ServiceSettings proxy(String proxy) { - builder.proxy(proxy); - return this; - } - - public ServiceSettings cluster(String cluster) { - builder.cluster(cluster); - return this; - } - - public ServiceSettings filter(String filter) { - builder.filter(filter); - return this; - } - - public ServiceSettings listener(String listener) { - builder.listener(listener); - return this; - } - - public ServiceSettings owner(String owner) { - builder.owner(owner); - return this; - } - - public ServiceSettings connections(Integer connections) { - builder.connections(connections); - return this; - } - - public ServiceSettings layer(String layer) { - builder.layer(layer); - return this; - } - - public ServiceSettings application(ApplicationConfig application) { - builder.application(application); - return this; - } - - public ServiceSettings module(ModuleConfig module) { - builder.module(module); - return this; - } - - public ServiceSettings addRegistries(List registries) { - builder.addRegistries(registries); - return this; - } - - public ServiceSettings addRegistry(RegistryConfig registry) { - builder.addRegistry(registry); - return this; - } - - public ServiceSettings registryIds(String registryIds) { - builder.registryIds(registryIds); - return this; - } - - public ServiceSettings onconnect(String onconnect) { - builder.onconnect(onconnect); - return this; - } - - public ServiceSettings ondisconnect(String ondisconnect) { - builder.ondisconnect(ondisconnect); - return this; - } - - public ServiceSettings metadataReportConfig(MetadataReportConfig metadataReportConfig) { - builder.metadataReportConfig(metadataReportConfig); - return this; - } - - public ServiceSettings configCenter(ConfigCenterConfig configCenter) { - builder.configCenter(configCenter); - return this; - } - - public ServiceSettings callbacks(Integer callbacks) { - builder.callbacks(callbacks); - return this; - } - - public ServiceSettings scope(String scope) { - builder.scope(scope); - return this; - } - - public ServiceSettings tag(String tag) { - builder.tag(tag); - return this; - } - - public ServiceSettings timeout(Integer timeout) { - builder.timeout(timeout); - return this; - } - - public ServiceSettings retries(Integer retries) { - builder.retries(retries); - return this; - } - - public ServiceSettings actives(Integer actives) { - builder.actives(actives); - return this; - } - - public ServiceSettings loadbalance(String loadbalance) { - builder.loadbalance(loadbalance); - return this; - } - - public ServiceSettings async(Boolean async) { - builder.async(async); - return this; - } - - public ServiceSettings sent(Boolean sent) { - builder.sent(sent); - return this; - } - - public ServiceSettings merger(String merger) { - builder.merger(merger); - return this; - } - - public ServiceSettings cache(String cache) { - builder.cache(cache); - return this; - } - - public ServiceSettings validation(String validation) { - builder.validation(validation); - return this; - } - - public ServiceSettings appendParameters(Map appendParameters) { - builder.appendParameters(appendParameters); - return this; - } - - public ServiceSettings appendParameter(String key, String value) { - builder.appendParameter(key, value); - return this; - } - - public ServiceSettings forks(Integer forks) { - builder.forks(forks); - return this; - } -} diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java deleted file mode 100644 index 290bb7e4b97..00000000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java +++ /dev/null @@ -1,32 +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.bootstrap; - -/** - * The Dubbo settings - * - * @since 2.7.4 - */ -public interface Settings { - - /** - * Go next settings - * - * @return {@link DubboBootstrap} - */ - DubboBootstrap next(); -} diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java index 4e03c1be295..51250d4e0dc 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java @@ -16,9 +16,8 @@ */ package org.apache.dubbo.bootstrap; -import org.apache.dubbo.config.builders.ApplicationBuilder; -import org.apache.dubbo.config.builders.ReferenceBuilder; -import org.apache.dubbo.config.builders.RegistryBuilder; +import org.apache.dubbo.config.ReferenceConfig; +import org.apache.dubbo.config.context.ConfigManager; /** * Dubbo Provider Bootstrap @@ -29,23 +28,24 @@ public class DubboServiceConsumerBootstrap { public static void main(String[] args) throws Exception { - DubboBootstrap bootstrap = new DubboBootstrap() - .application(ApplicationBuilder.newBuilder().name("dubbo-consumer-demo").build()) - .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo&metadata=remote").build()) - .reference(ReferenceBuilder.newBuilder().id("ref").interfaceClass(EchoService.class).build()) + new DubboBootstrap() + .application("dubbo-consumer-demo") + .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo")) + .reference("ref", builder -> builder.interfaceClass(EchoService.class)) .onlyRegisterProvider(true) .start() .await(); - // TODO, -// ReferenceConfig referenceConfig = ReferenceConfigCache.getCache().get(EchoService.class.getName(), EchoService.class); -// -// EchoService echoService = referenceConfig.get(); -// -// for (int i = 0; i < 500; i++) { -// Thread.sleep(2000L); -// System.out.println(echoService.echo("Hello,World")); -// } + ConfigManager configManager = ConfigManager.getInstance(); + + ReferenceConfig referenceConfig = configManager.getReferenceConfig("ref"); + + EchoService echoService = referenceConfig.get(); + + for (int i = 0; i < 500; i++) { + Thread.sleep(2000L); + System.out.println(echoService.echo("Hello,World")); + } } } diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java index 7918bff172d..e957cf3af36 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java @@ -16,12 +16,6 @@ */ package org.apache.dubbo.bootstrap; -import org.apache.dubbo.config.builders.ApplicationBuilder; -import org.apache.dubbo.config.builders.MetadataReportBuilder; -import org.apache.dubbo.config.builders.ProtocolBuilder; -import org.apache.dubbo.config.builders.RegistryBuilder; -import org.apache.dubbo.config.builders.ServiceBuilder; - import java.io.IOException; /** @@ -34,12 +28,10 @@ public class DubboServiceProviderBootstrap { public static void main(String[] args) throws IOException { new DubboBootstrap() - .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").metadata("remote").build()) - .metadataReport(MetadataReportBuilder.newBuilder().address("zookeeper://127.0.0.1:2181").build()) -// .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build()) - .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service").build()) - .protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build()) - .service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build()) + .application("dubbo-provider-demo") + .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service")) + .protocol(builder -> builder.port(-1).name("dubbo")) + .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl())) .start() .await(); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java index 12d09bf05cf..1f51f1bc691 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java @@ -36,7 +36,7 @@ public abstract class AbstractBuilder protocolIds = new HashSet<>(); private List> serviceConfigs = new ArrayList<>(); - private List> referenceConfigs = new ArrayList<>(); + + private Map> referenceConfigs = new ConcurrentHashMap<>(); public static ConfigManager getInstance() { return CONFIG_MANAGER; @@ -201,7 +202,7 @@ public void addProvider(ProviderConfig providerConfig) { if (providers.containsKey(key) && !providerConfig.equals(providers.get(key))) { logger.warn("Duplicate ProviderConfig found, there already has one default ProviderConfig or more than two ProviderConfigs have the same id, " + - "you can try to give each ProviderConfig a different id. " + providerConfig); + "you can try to give each ProviderConfig a different id. " + providerConfig); } else { providers.put(key, providerConfig); } @@ -230,7 +231,7 @@ public void addConsumer(ConsumerConfig consumerConfig) { if (consumers.containsKey(key) && !consumerConfig.equals(consumers.get(key))) { logger.warn("Duplicate ConsumerConfig found, there already has one default ConsumerConfig or more than two ConsumerConfigs have the same id, " + - "you can try to give each ConsumerConfig a different id. " + consumerConfig); + "you can try to give each ConsumerConfig a different id. " + consumerConfig); } else { consumers.put(key, consumerConfig); } @@ -270,7 +271,7 @@ public void addProtocol(ProtocolConfig protocolConfig, boolean canBeDefault) { if (protocols.containsKey(key) && !protocolConfig.equals(protocols.get(key))) { logger.warn("Duplicate ProtocolConfig found, there already has one default ProtocolConfig or more than two ProtocolConfigs have the same id, " + - "you can try to give each ProtocolConfig a different id. " + protocolConfig); + "you can try to give each ProtocolConfig a different id. " + protocolConfig); } else { protocols.put(key, protocolConfig); } @@ -308,7 +309,7 @@ public void addRegistry(RegistryConfig registryConfig, boolean canBeDefault) { if (registries.containsKey(key) && !registryConfig.equals(registries.get(key))) { logger.warn("Duplicate RegistryConfig found, there already has one default RegistryConfig or more than two RegistryConfigs have the same id, " + - "you can try to give each RegistryConfig a different id. " + registryConfig); + "you can try to give each RegistryConfig a different id. " + registryConfig); } else { registries.put(key, registryConfig); } @@ -327,7 +328,7 @@ public void addService(ServiceConfig serviceConfig) { } public void addReference(ReferenceConfig referenceConfig) { - this.referenceConfigs.add(referenceConfig); + this.referenceConfigs.put(referenceConfig.getId(), referenceConfig); } public Set getRegistryIds() { @@ -375,12 +376,21 @@ public Map getConsumers() { return consumers; } + + public boolean hasServices() { + return getServiceConfigs().size() > 0; + } + public List> getServiceConfigs() { return serviceConfigs; } public List> getReferenceConfigs() { - return referenceConfigs; + return new ArrayList<>(referenceConfigs.values()); + } + + public ReferenceConfig getReferenceConfig(String id) { + return (ReferenceConfig) referenceConfigs.get(id); } public void refreshAll() { From 3218a1fd1fa99fecca776da1f089637230816e21 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Sat, 20 Jul 2019 14:55:24 +0800 Subject: [PATCH 12/30] Polish apache/dubbo#4541 : Fix the nulling URL issue --- .../file/FileSystemDynamicConfiguration.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index 867c581e2b9..b75527e8ccc 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -91,7 +91,7 @@ public class FileSystemDynamicConfiguration implements DynamicConfiguration { public static final String DEFAULT_THREAD_POOL_PREFIX = PARAM_NAME_PREFIX + "workers"; - public static final int DEFAULT_THREAD_POOL_SIZE = 1; + public static final String DEFAULT_THREAD_POOL_SIZE = "1"; public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8"; @@ -523,7 +523,7 @@ protected static boolean isBasedPoolingWatchService() { } private static String getThreadPoolPrefixName(URL url) { - return url.getParameter(THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); + return getParameter(url, THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX); } protected static ThreadPoolExecutor getWatchEventsLoopThreadPool() { @@ -595,8 +595,8 @@ private static Optional newWatchService() { } private static File initDirectory(URL url) { - String directoryPath = url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH); - File rootDirectory = new File(url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH)); + String directoryPath = getParameter(url, CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH); + File rootDirectory = new File(getParameter(url, CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH)); if (!rootDirectory.exists() && !rootDirectory.mkdirs()) { throw new IllegalStateException(format("Dubbo config center rootDirectory[%s] can't be created!", directoryPath)); @@ -604,12 +604,19 @@ private static File initDirectory(URL url) { return rootDirectory; } + private static String getParameter(URL url, String name, String defaultValue) { + if (url != null) { + return url.getParameter(name, defaultValue); + } + return defaultValue; + } + private static String getEncoding(URL url) { - return url.getParameter(CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); + return getParameter(url, CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING); } private static int getThreadPoolSize(URL url) { - return url.getParameter(THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE); + return Integer.parseInt(getParameter(url, THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE)); } private static ThreadPoolExecutor newWatchEventsLoopThreadPool() { From d5c78ac5ca852b11b0e8a72f2ec7abd371f638ff Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 25 Jul 2019 17:57:50 +0800 Subject: [PATCH 13/30] Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager --- dubbo-bootstrap/pom.xml | 6 + .../dubbo/bootstrap/DubboBootstrap.java | 81 ++-- .../dubbo/bootstrap/DubboBootstrapTest.java | 14 - .../DubboServiceConsumerBootstrap.java | 5 +- .../DubboServiceProviderBootstrap.java | 26 +- .../dubbo/common/utils/ReflectUtils.java | 30 +- .../dubbo/config/AbstractInterfaceConfig.java | 23 +- .../apache/dubbo/config/ServiceConfig.java | 17 +- .../dubbo/config/context/ConfigManager.java | 441 ++++++++++-------- .../config/context/ConfigManagerTest.java | 71 +++ ...nfigurableMetadataServiceExporterTest.java | 4 +- .../client/FileSystemServiceDiscovery.java | 114 +++++ 12 files changed, 557 insertions(+), 275 deletions(-) create mode 100644 dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java diff --git a/dubbo-bootstrap/pom.xml b/dubbo-bootstrap/pom.xml index 17df1344efa..e38e05d2073 100644 --- a/dubbo-bootstrap/pom.xml +++ b/dubbo-bootstrap/pom.xml @@ -90,6 +90,12 @@ test + + org.apache.curator + curator-test + test + + \ No newline at end of file diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java index 1f92aeed5fa..872ea883c9d 100644 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java +++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java @@ -59,6 +59,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; @@ -149,7 +150,7 @@ public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) } public DubboBootstrap metadataReport(List metadataReportConfigs) { - configManager.addMetadataReport(metadataReportConfigs); + configManager.addMetadataReports(metadataReportConfigs); return this; } @@ -193,22 +194,48 @@ public DubboBootstrap application(ApplicationConfig applicationConfig) { // {@link RegistryConfig} correlative methods + /** + * Add an instance of {@link RegistryConfig} with {@link #DEFAULT_REGISTRY_ID default ID} + * + * @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder} + * @return current {@link DubboBootstrap} instance + */ public DubboBootstrap registry(Consumer consumerBuilder) { return registry(DEFAULT_REGISTRY_ID, consumerBuilder); } + /** + * Add an instance of {@link RegistryConfig} with the specified ID + * + * @param id the {@link RegistryConfig#getId() id} of {@link RegistryConfig} + * @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder} + * @return current {@link DubboBootstrap} instance + */ public DubboBootstrap registry(String id, Consumer consumerBuilder) { RegistryBuilder builder = createRegistryBuilder(id); consumerBuilder.accept(builder); return registry(builder.build()); } + /** + * Add an instance of {@link RegistryConfig} + * + * @param registryConfig an instance of {@link RegistryConfig} + * @return current {@link DubboBootstrap} instance + */ public DubboBootstrap registry(RegistryConfig registryConfig) { - return registries(asList(registryConfig)); + configManager.addRegistry(registryConfig); + return this; } - public DubboBootstrap registries(List registryConfigs) { - configManager.addRegistries(registryConfigs, true); + /** + * Add an instance of {@link RegistryConfig} + * + * @param registryConfigs the multiple instances of {@link RegistryConfig} + * @return current {@link DubboBootstrap} instance + */ + public DubboBootstrap registries(Iterable registryConfigs) { + registryConfigs.forEach(this::registry); return this; } @@ -315,7 +342,7 @@ public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) { } public DubboBootstrap configCenter(List configCenterConfigs) { - configManager.addConfigCenter(configCenterConfigs); + configManager.addConfigCenters(configCenterConfigs); return this; } @@ -358,7 +385,7 @@ private void loadRemoteConfigs() { } }); - configManager.addRegistries(tmpRegistries, true); + configManager.addRegistries(tmpRegistries); // protocol ids to protocol configs List tmpProtocols = new ArrayList<>(); @@ -382,22 +409,20 @@ private void loadRemoteConfigs() { * there's no config center specified explicitly. */ private void useRegistryAsConfigCenterIfNecessary() { - configManager.getDefaultRegistries().ifPresent(registryConfigs -> { - for (RegistryConfig registryConfig : registryConfigs) { - if (registryConfig != null && registryConfig.isZookeeperProtocol()) { - // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. - Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { - Set configCenters = configManager.getConfigCenters(); - if (CollectionUtils.isEmpty(configCenters)) { - ConfigCenterConfig cc = new ConfigCenterConfig(); - cc.setProtocol(registryConfig.getProtocol()); - cc.setAddress(registryConfig.getAddress()); - cc.setHighestPriority(false); - configManager.addConfigCenter(cc); - } - return null; - }); - } + configManager.getDefaultRegistries().forEach(registryConfig -> { + if (registryConfig != null && registryConfig.isZookeeperProtocol()) { + // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. + Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { + Collection configCenters = configManager.getConfigCenters(); + if (CollectionUtils.isEmpty(configCenters)) { + ConfigCenterConfig cc = new ConfigCenterConfig(); + cc.setProtocol(registryConfig.getProtocol()); + cc.setAddress(registryConfig.getAddress()); + cc.setHighestPriority(false); + configManager.addConfigCenter(cc); + } + return null; + }); } startConfigCenter(); }); @@ -432,8 +457,8 @@ public DubboBootstrap start() { // TODO, only export to default registry? List exportedURLs = exportMetadataService( configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")), - configManager.getDefaultRegistries().orElseThrow(() -> new IllegalStateException("No default RegistryConfig")), - configManager.getDefaultProtocols().orElseThrow(() -> new IllegalStateException("No default ProtocolConfig")) + configManager.getRegistries().values(), + configManager.getProtocols().values() ); /** @@ -541,7 +566,7 @@ private void startMetadataReport() { ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified.")); // FIXME, multiple metadata config support. - Set metadataReportConfigs = configManager.getMetadataConfigs(); + Collection metadataReportConfigs = configManager.getMetadataConfigs(); if (CollectionUtils.isEmpty(metadataReportConfigs)) { if (CommonConstants.METADATA_REMOTE.equals(applicationConfig.getMetadata())) { throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'."); @@ -559,7 +584,7 @@ private void startMetadataReport() { } private void startConfigCenter() { - Set configCenters = configManager.getConfigCenters(); + Collection configCenters = configManager.getConfigCenters(); if (CollectionUtils.isNotEmpty(configCenters)) { CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration(); @@ -619,8 +644,8 @@ public DubboBootstrap addEventListener(EventListener listener) { } private List exportMetadataService(ApplicationConfig applicationConfig, - List globalRegistryConfigs, - List globalProtocolConfigs) { + Collection globalRegistryConfigs, + Collection globalProtocolConfigs) { ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); exporter.setApplicationConfig(applicationConfig); exporter.setRegistries(globalRegistryConfigs); diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java index f49c340dbaa..96fbcc76650 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java @@ -16,11 +16,6 @@ */ package org.apache.dubbo.bootstrap; -import org.apache.dubbo.config.builders.ApplicationBuilder; -import org.apache.dubbo.config.builders.ProtocolBuilder; -import org.apache.dubbo.config.builders.RegistryBuilder; -import org.apache.dubbo.config.builders.ServiceBuilder; - import org.junit.jupiter.api.Test; import java.io.IOException; @@ -35,14 +30,5 @@ public class DubboBootstrapTest { @Test public void test() throws IOException { - new DubboBootstrap() - .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build()) - .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&metadata=remote").build()) - .protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build()) - .service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build()) - .start() - .await(); - - System.in.read(); } } diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java index 51250d4e0dc..2757899befd 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java @@ -30,7 +30,10 @@ public static void main(String[] args) throws Exception { new DubboBootstrap() .application("dubbo-consumer-demo") - .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo")) + // Zookeeper +// .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo")) + // Nacos + .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo")) .reference("ref", builder -> builder.interfaceClass(EchoService.class)) .onlyRegisterProvider(true) .start() diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java index e957cf3af36..69d53c19c30 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java @@ -16,6 +16,8 @@ */ package org.apache.dubbo.bootstrap; +import org.apache.curator.test.TestingServer; + import java.io.IOException; /** @@ -25,14 +27,34 @@ */ public class DubboServiceProviderBootstrap { - public static void main(String[] args) throws IOException { + private static final String ZK_ADDRESS = "127.0.0.1"; + + private static final int ZK_PORT = 2181; + + public static void main(String[] args) throws Exception { + + String address = "zookeeper://" + ZK_ADDRESS + ":" + ZK_PORT + "?registry-type=service"; + + TestingServer testingServer = new TestingServer(2181, true); new DubboBootstrap() .application("dubbo-provider-demo") - .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service")) + // Zookeeper in service registry type + .registry("zookeeper", builder -> builder.address(address)) + // Nacos +// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service")) .protocol(builder -> builder.port(-1).name("dubbo")) .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl())) .start() .await(); + + + // shutdown Zookeeper server + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + testingServer.close(); + } catch (IOException e) { + } + })); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java index 27202299d2c..f8e987c0a44 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java @@ -21,6 +21,9 @@ import javassist.CtMethod; import javassist.NotFoundException; +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -48,6 +51,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import static java.util.Arrays.asList; import static java.util.Collections.unmodifiableSet; @@ -1127,7 +1131,7 @@ public static Type[] getReturnTypes(Method method) { } return new Type[]{returnType, genericReturnType}; } - + /** * Find the {@link Set} of {@link ParameterizedType} * @@ -1184,4 +1188,28 @@ public static Set> findHierarchicalTypes(Class sourceClass, Clas return unmodifiableSet(hierarchicalTypes); } + + public static T getProperty(Object bean, String propertyName) { + Class beanClass = bean.getClass(); + BeanInfo beanInfo = null; + T propertyValue = null; + try { + beanInfo = Introspector.getBeanInfo(beanClass); + propertyValue = (T) Stream.of(beanInfo.getPropertyDescriptors()) + .filter(propertyDescriptor -> propertyName.equals(propertyDescriptor.getName())) + .map(PropertyDescriptor::getReadMethod) + .findFirst() + .map(method -> { + try { + return method.invoke(bean); + } catch (Exception e) { + } + return null; + }).get(); + } catch (Exception e) { + + } + return propertyValue; + } + } \ No newline at end of file diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index 1ad15ecb725..874e38b9680 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -255,7 +255,6 @@ protected void checkMetadataReport() { } /** - * * Load the registry and conversion it to {@link URL}, the priority order is: system property > dubbo registry config * * @param provider whether it is the provider side @@ -298,7 +297,6 @@ protected List loadRegistries(boolean provider) { } /** - * * Load the monitor config from the system properties and conversation it to {@link URL} * * @param registryURL @@ -358,7 +356,7 @@ static void appendRuntimeParameters(Map map) { * methods configured in the configuration file are included in the interface of remote service * * @param interfaceClass the interface of remote service - * @param methods the methods configured + * @param methods the methods configured */ protected void checkInterfaceAndMethods(Class interfaceClass, List methods) { // interface cannot be null @@ -466,15 +464,14 @@ private void verify(Class interfaceClass, Class localClass) { private void convertRegistryIdsToRegistries() { if (StringUtils.isEmpty(registryIds)) { if (CollectionUtils.isEmpty(registries)) { - setRegistries( - ConfigManager.getInstance().getDefaultRegistries() - .filter(CollectionUtils::isNotEmpty) - .orElseGet(() -> { - RegistryConfig registryConfig = new RegistryConfig(); - registryConfig.refresh(); - return Arrays.asList(registryConfig); - }) - ); + List registryConfigs = ConfigManager.getInstance().getDefaultRegistries(); + if (registryConfigs.isEmpty()) { + registryConfigs = new ArrayList<>(); + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.refresh(); + registryConfigs.add(registryConfig); + } + setRegistries(registryConfigs); } } else { String[] ids = COMMA_SPLIT_PATTERN.split(registryIds); @@ -668,7 +665,7 @@ public List getRegistries() { @SuppressWarnings({"unchecked"}) public void setRegistries(List registries) { - ConfigManager.getInstance().addRegistries((List) registries, false); + ConfigManager.getInstance().addRegistries((List) registries); this.registries = (List) registries; } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index fb9d247d30a..c851ca133ea 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -882,15 +882,14 @@ private void checkProtocol() { private void convertProtocolIdsToProtocols() { if (StringUtils.isEmpty(protocolIds)) { if (CollectionUtils.isEmpty(protocols)) { - setProtocols( - ConfigManager.getInstance().getDefaultProtocols() - .filter(CollectionUtils::isNotEmpty) - .orElseGet(() -> { - ProtocolConfig protocolConfig = new ProtocolConfig(); - protocolConfig.refresh(); - return new ArrayList<>(Arrays.asList(protocolConfig)); - }) - ); + List protocolConfigs = ConfigManager.getInstance().getDefaultProtocols(); + if (protocolConfigs.isEmpty()) { + protocolConfigs = new ArrayList<>(1); + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.refresh(); + protocolConfigs.add(protocolConfig); + } + setProtocols(protocolConfigs); } } else { String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java index 4779412c5e6..5a50ab92762 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java @@ -19,8 +19,6 @@ import org.apache.dubbo.common.config.Environment; 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.config.AbstractConfig; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ConfigCenterConfig; @@ -34,16 +32,24 @@ import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.ServiceConfig; -import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.StampedLock; import java.util.stream.Collectors; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static java.util.Optional.ofNullable; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; +import static org.apache.dubbo.common.utils.ReflectUtils.getProperty; +import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX; import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX; @@ -82,41 +88,34 @@ * All workflow internally can rely on ConfigManager. */ public class ConfigManager { - private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class); - private static final ConfigManager CONFIG_MANAGER = new ConfigManager(); - private ApplicationConfig application; - private MonitorConfig monitor; - private ModuleConfig module; - - private Map protocols = new ConcurrentHashMap<>(); - private Map registries = new ConcurrentHashMap<>(); - private Map providers = new ConcurrentHashMap<>(); - private Map consumers = new ConcurrentHashMap<>(); + private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class); - private List defaultProtocols = new ArrayList<>(); - private List defaultRegistries = new ArrayList<>(); + private static final ConfigManager CONFIG_MANAGER = new ConfigManager(); - private Set configCenters = new HashSet<>(); - private Set metadataConfigs = new HashSet<>(); - private Set registryIds = new HashSet<>(); - private Set protocolIds = new HashSet<>(); + private volatile ModuleConfig module; + private volatile ApplicationConfig application; + private volatile MonitorConfig monitor; - private List> serviceConfigs = new ArrayList<>(); + private final Map protocols = new ConcurrentHashMap<>(); + private final Map registries = new ConcurrentHashMap<>(); + private final Map providers = new ConcurrentHashMap<>(); + private final Map consumers = new ConcurrentHashMap<>(); + private final Map configCenters = new ConcurrentHashMap<>(); + private final Map metadataConfigs = new ConcurrentHashMap<>(); + private final Map> serviceConfigs = new ConcurrentHashMap<>(); + private final Map> referenceConfigs = new ConcurrentHashMap<>(); - private Map> referenceConfigs = new ConcurrentHashMap<>(); + private final StampedLock lock = new StampedLock(); public static ConfigManager getInstance() { return CONFIG_MANAGER; } private ConfigManager() { - } - public Optional getApplication() { - return Optional.ofNullable(application); - } + // ApplicationConfig correlative methods public void setApplication(ApplicationConfig application) { if (application != null) { @@ -125,10 +124,12 @@ public void setApplication(ApplicationConfig application) { } } - public Optional getMonitor() { - return Optional.ofNullable(monitor); + public Optional getApplication() { + return ofNullable(application); } + // MonitorConfig correlative methods + public void setMonitor(MonitorConfig monitor) { if (monitor != null) { checkDuplicate(this.monitor, monitor); @@ -136,10 +137,12 @@ public void setMonitor(MonitorConfig monitor) { } } - public Optional getModule() { - return Optional.ofNullable(module); + public Optional getMonitor() { + return ofNullable(monitor); } + // ModuleConfig correlative methods + public void setModule(ModuleConfig module) { if (module != null) { checkDuplicate(this.module, module); @@ -147,210 +150,175 @@ public void setModule(ModuleConfig module) { } } - public Set getConfigCenters() { - return configCenters; + public Optional getModule() { + return ofNullable(module); } + // ConfigCenterConfig correlative methods + public void addConfigCenter(ConfigCenterConfig configCenter) { - if (configCenter != null && !configCenters.contains(configCenter)) { - this.configCenters.add(configCenter); - } + putIfAbsent(configCenter.getId(), configCenter, configCenters); } - public void addConfigCenter(List configCenters) { - if (CollectionUtils.isNotEmpty(configCenters)) { - this.configCenters.addAll(configCenters); - } + public void addConfigCenters(Iterable configCenters) { + configCenters.forEach(this::addConfigCenter); + } + + public ConfigCenterConfig getConfigCenter(String id) { + return configCenters.get(id); } - public Set getMetadataConfigs() { - return metadataConfigs; + public Collection getConfigCenters() { + return configCenters.values(); } + // MetadataReportConfig correlative methods + public void addMetadataReport(MetadataReportConfig metadataReportConfig) { - if (metadataReportConfig != null && !metadataConfigs.contains(metadataReportConfig)) { - this.metadataConfigs.add(metadataReportConfig); - } + putIfAbsent(metadataReportConfig.getId(), metadataReportConfig, metadataConfigs); } - public void addMetadataReport(List metadataReportConfigs) { - if (CollectionUtils.isNotEmpty(metadataReportConfigs)) { - this.metadataConfigs.addAll(metadataReportConfigs); - } + public void addMetadataReports(Iterable metadataReportConfigs) { + metadataReportConfigs.forEach(this::addMetadataReport); + } + + public Collection getMetadataConfigs() { + return metadataConfigs.values(); + } + + // MetadataReportConfig correlative methods + + public void addProvider(ProviderConfig providerConfig) { + putIfAbsent(providerConfig, providers); } public Optional getProvider(String id) { - return Optional.ofNullable(providers.get(id)); + return ofNullable(providers.get(id)); } public Optional getDefaultProvider() { - return Optional.ofNullable(providers.get(DEFAULT_KEY)); + return getProvider(DEFAULT_KEY); } - public void addProvider(ProviderConfig providerConfig) { - if (providerConfig == null) { - return; - } - - String key = StringUtils.isNotEmpty(providerConfig.getId()) - ? providerConfig.getId() - : (providerConfig.isDefault() == null || providerConfig.isDefault()) ? DEFAULT_KEY : null; + public Map getProviders() { + return unmodifiableMap(providers); + } - if (StringUtils.isEmpty(key)) { - throw new IllegalStateException("A ProviderConfig should either has an id or it's the default one, " + providerConfig); - } + // ConsumerConfig correlative methods - if (providers.containsKey(key) && !providerConfig.equals(providers.get(key))) { - logger.warn("Duplicate ProviderConfig found, there already has one default ProviderConfig or more than two ProviderConfigs have the same id, " + - "you can try to give each ProviderConfig a different id. " + providerConfig); - } else { - providers.put(key, providerConfig); - } + public void addConsumer(ConsumerConfig consumerConfig) { + putIfAbsent(consumerConfig, consumers); } public Optional getConsumer(String id) { - return Optional.ofNullable(consumers.get(id)); + return ofNullable(consumers.get(id)); } public Optional getDefaultConsumer() { - return Optional.ofNullable(consumers.get(DEFAULT_KEY)); + return getConsumer(DEFAULT_KEY); } - public void addConsumer(ConsumerConfig consumerConfig) { - if (consumerConfig == null) { - return; - } + public Map getConsumers() { + return unmodifiableMap(consumers); + } - String key = StringUtils.isNotEmpty(consumerConfig.getId()) - ? consumerConfig.getId() - : (consumerConfig.isDefault() == null || consumerConfig.isDefault()) ? DEFAULT_KEY : null; + // ProtocolConfig correlative methods - if (StringUtils.isEmpty(key)) { - throw new IllegalStateException("A ConsumerConfig should either has an id or it's the default one, " + consumerConfig); - } + public void addProtocol(ProtocolConfig protocolConfig) { + putIfAbsent(protocolConfig, protocols); + } - if (consumers.containsKey(key) && !consumerConfig.equals(consumers.get(key))) { - logger.warn("Duplicate ConsumerConfig found, there already has one default ConsumerConfig or more than two ConsumerConfigs have the same id, " + - "you can try to give each ConsumerConfig a different id. " + consumerConfig); - } else { - consumers.put(key, consumerConfig); + public void addProtocols(Iterable protocolConfigs, boolean canBeDefault) { + if (protocolConfigs != null) { + protocolConfigs.forEach(this::addProtocol); } } public Optional getProtocol(String id) { - return Optional.ofNullable(protocols.get(id)); + return ofNullable(protocols.get(id)); } - public Optional> getDefaultProtocols() { - return Optional.of(defaultProtocols); + public List getDefaultProtocols() { + return getDefaultConfigs(protocols); } - public void addProtocols(List protocolConfigs, boolean canBeDefault) { - if (protocolConfigs != null) { - protocolConfigs.forEach(pc -> this.addProtocol(pc, canBeDefault)); - } + public Map getProtocols() { + return unmodifiableMap(protocols); } - public void addProtocol(ProtocolConfig protocolConfig, boolean canBeDefault) { - if (protocolConfig == null) { - return; - } + public Set getProtocolIds() { + Set protocolIds = new HashSet<>(); + protocolIds.addAll(getSubProperties(Environment.getInstance() + .getExternalConfigurationMap(), PROTOCOLS_SUFFIX)); + protocolIds.addAll(getSubProperties(Environment.getInstance() + .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX)); - // if isDefault is not false and a ProtocolConfig is not specified being false. - if (canBeDefault && (protocolConfig.isDefault() == null || protocolConfig.isDefault())) { - this.defaultProtocols.add(protocolConfig); - } + protocolIds.addAll(protocols.keySet()); + return unmodifiableSet(protocolIds); + } - String key = StringUtils.isNotEmpty(protocolConfig.getId()) - ? protocolConfig.getId() - : DEFAULT_KEY; - if (StringUtils.isEmpty(key)) { - throw new IllegalStateException("A ProtocolConfig should either has an id or it's the default one, " + protocolConfig); - } + // RegistryConfig correlative methods - if (protocols.containsKey(key) && !protocolConfig.equals(protocols.get(key))) { - logger.warn("Duplicate ProtocolConfig found, there already has one default ProtocolConfig or more than two ProtocolConfigs have the same id, " + - "you can try to give each ProtocolConfig a different id. " + protocolConfig); - } else { - protocols.put(key, protocolConfig); + public void addRegistry(RegistryConfig registryConfig) { + putIfAbsent(registryConfig, registries); + } + + public void addRegistries(Iterable registryConfigs) { + if (registryConfigs != null) { + registryConfigs.forEach(this::addRegistry); } } public Optional getRegistry(String id) { - return Optional.ofNullable(registries.get(id)); + return ofNullable(registries.get(id)); } - public Optional> getDefaultRegistries() { - return Optional.of(defaultRegistries); + public List getDefaultRegistries() { + return getDefaultConfigs(registries); } - public void addRegistries(List registryConfigs, boolean canBeDefault) { - if (registryConfigs != null) { - registryConfigs.forEach(rc -> this.addRegistry(rc, canBeDefault)); - } + public Map getRegistries() { + return unmodifiableMap(registries); } - public void addRegistry(RegistryConfig registryConfig, boolean canBeDefault) { - if (registryConfig == null) { - return; - } + public Set getRegistryIds() { + Set registryIds = new HashSet<>(); + registryIds.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(), + REGISTRIES_SUFFIX)); + registryIds.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(), + REGISTRIES_SUFFIX)); - if (canBeDefault && (registryConfig.isDefault() == null || registryConfig.isDefault())) { - this.defaultRegistries.add(registryConfig); - } - String key = StringUtils.isNotEmpty(registryConfig.getId()) - ? registryConfig.getId() - : DEFAULT_KEY; + registryIds.addAll(registries.keySet()); + return unmodifiableSet(registryIds); + } - if (StringUtils.isEmpty(key)) { - throw new IllegalStateException("A RegistryConfig should either has an id or it's the default one, " + registryConfig); - } + // ServiceConfig correlative methods - if (registries.containsKey(key) && !registryConfig.equals(registries.get(key))) { - logger.warn("Duplicate RegistryConfig found, there already has one default RegistryConfig or more than two RegistryConfigs have the same id, " + - "you can try to give each RegistryConfig a different id. " + registryConfig); - } else { - registries.put(key, registryConfig); - } + public void addService(ServiceConfig serviceConfig) { + putIfAbsent(serviceConfig.getId(), serviceConfig, serviceConfigs); } - public void addProtocolIds(List protocolIds) { - this.protocolIds.addAll(protocolIds); + public Collection> getServiceConfigs() { + return serviceConfigs.values(); } - public void addRegistryIds(List registryIds) { - this.registryIds.addAll(registryIds); + public ServiceConfig getServiceConfig(String id) { + return (ServiceConfig) serviceConfigs.get(id); } - public void addService(ServiceConfig serviceConfig) { - this.serviceConfigs.add(serviceConfig); - } + // ReferenceConfig correlative methods public void addReference(ReferenceConfig referenceConfig) { - this.referenceConfigs.put(referenceConfig.getId(), referenceConfig); + putIfAbsent(referenceConfig.getId(), referenceConfig, referenceConfigs); } - public Set getRegistryIds() { - Set configedRegistries = new HashSet<>(); - configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(), - REGISTRIES_SUFFIX)); - configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(), - REGISTRIES_SUFFIX)); - - configedRegistries.addAll(registryIds); - return configedRegistries; + public Collection> getReferenceConfigs() { + return referenceConfigs.values(); } - public Set getProtocolIds() { - Set configedProtocols = new HashSet<>(); - configedProtocols.addAll(getSubProperties(Environment.getInstance() - .getExternalConfigurationMap(), PROTOCOLS_SUFFIX)); - configedProtocols.addAll(getSubProperties(Environment.getInstance() - .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX)); - - configedProtocols.addAll(protocolIds); - return configedProtocols; + public ReferenceConfig getReferenceConfig(String id) { + return (ReferenceConfig) referenceConfigs.get(id); } protected static Set getSubProperties(Map properties, String prefix) { @@ -360,71 +328,134 @@ protected static Set getSubProperties(Map properties, St }).collect(Collectors.toSet()); } - public Map getProtocols() { - return protocols; - } + public void refreshAll() { + write(() -> { + // refresh all configs here, + getApplication().ifPresent(ApplicationConfig::refresh); + getMonitor().ifPresent(MonitorConfig::refresh); + getModule().ifPresent(ModuleConfig::refresh); + + getProtocols().values().forEach(ProtocolConfig::refresh); + getRegistries().values().forEach(RegistryConfig::refresh); + getProviders().values().forEach(ProviderConfig::refresh); + getConsumers().values().forEach(ConsumerConfig::refresh); + }); - public Map getRegistries() { - return registries; } - public Map getProviders() { - return providers; + + // For test purpose + public void clear() { + write(() -> { + this.application = null; + this.monitor = null; + this.module = null; + this.registries.clear(); + this.protocols.clear(); + this.providers.clear(); + this.consumers.clear(); + this.configCenters.clear(); + this.metadataConfigs.clear(); + }); + } + + private V write(Callable callable) { + V value = null; + long stamp = lock.writeLock(); + try { + value = callable.call(); + } catch (Throwable e) { + throw new RuntimeException(e); + } finally { + lock.unlockWrite(stamp); + } + return value; } - public Map getConsumers() { - return consumers; + private void write(Runnable runnable) { + write(() -> { + runnable.run(); + return null; + }); } - public boolean hasServices() { - return getServiceConfigs().size() > 0; - } + private V read(Callable callable) { + long stamp = lock.tryOptimisticRead(); - public List> getServiceConfigs() { - return serviceConfigs; - } + boolean readLock = false; - public List> getReferenceConfigs() { - return new ArrayList<>(referenceConfigs.values()); - } + V value = null; - public ReferenceConfig getReferenceConfig(String id) { - return (ReferenceConfig) referenceConfigs.get(id); - } + try { + readLock = !lock.validate(stamp); - public void refreshAll() { - // refresh all configs here, - getApplication().ifPresent(ApplicationConfig::refresh); - getMonitor().ifPresent(MonitorConfig::refresh); - getModule().ifPresent(ModuleConfig::refresh); + if (readLock) { + stamp = lock.readLock(); + } + value = callable.call(); + } catch (Throwable e) { + throw new RuntimeException(e); + } finally { + if (readLock) { + lock.unlockRead(stamp); + } + } + + return value; + } - getProtocols().values().forEach(ProtocolConfig::refresh); - getRegistries().values().forEach(RegistryConfig::refresh); - getProviders().values().forEach(ProviderConfig::refresh); - getConsumers().values().forEach(ConsumerConfig::refresh); + private void putIfAbsent(String key, V value, Map map) { + if (read(() -> !map.containsKey(key) && !map.containsValue(value))) { + write(() -> { + map.putIfAbsent(key, value); + }); + } } - private void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) { + private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) { if (oldOne != null && !oldOne.equals(newOne)) { String configName = oldOne.getClass().getSimpleName(); throw new IllegalStateException("Duplicate Config found for " + configName + ", you should use only one unique " + configName + " for one application."); } } - // For test purpose - public void clear() { - this.application = null; - this.monitor = null; - this.module = null; - this.registries.clear(); - this.protocols.clear(); - this.providers.clear(); - this.consumers.clear(); - this.configCenters.clear(); - this.metadataConfigs.clear(); - this.registryIds.clear(); - this.protocolIds.clear(); + private static Map, Map> newMap() { + return new HashMap<>(); } + private static void putIfAbsent(C config, Map configsMap) { + + if (config == null) { + return; + } + + String id = config.getId(); + + Boolean isDefault = getProperty(config, "default"); + + String key = isNotEmpty(id) ? id : Boolean.TRUE.equals(isDefault) ? DEFAULT_KEY : null; + + C existedConfig = configsMap.get(key); + + if (existedConfig != null && !config.equals(existedConfig)) { + if (logger.isWarnEnabled()) { + String type = config.getClass().getSimpleName(); + logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " + + "you can try to give each %s a different id : %s", type, type, type, type, config)); + } + } else { + configsMap.put(key, config); + } + } + + private static List getDefaultConfigs(Map configsMap) { + return configsMap.values() + .stream() + .filter(config -> { + Boolean isDefault = getProperty(config, "default"); + return isDefault == null || Boolean.TRUE.equals(isDefault); + }) + .collect(Collectors.toList()); + } } diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java new file mode 100644 index 00000000000..44e896d517d --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java @@ -0,0 +1,71 @@ +/* + * 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.config.context; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ModuleConfig; +import org.apache.dubbo.config.MonitorConfig; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.apache.dubbo.config.context.ConfigManager.getInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * {@link ConfigManager} Test + * + * @since 2.7.4 + */ +public class ConfigManagerTest { + + private ConfigManager configManager = getInstance(); + + @BeforeEach + public void init() { + configManager.clear(); + assertFalse(configManager.getApplication().isPresent()); + assertFalse(configManager.getMonitor().isPresent()); + assertFalse(configManager.getMonitor().isPresent()); + } + + @Test + public void testApplicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(); + configManager.setApplication(applicationConfig); + assertTrue(configManager.getApplication().isPresent()); + assertEquals(applicationConfig, configManager.getApplication().get()); + } + + @Test + public void testMonitorConfig() { + MonitorConfig monitorConfig = new MonitorConfig(); + configManager.setMonitor(monitorConfig); + assertTrue(configManager.getMonitor().isPresent()); + assertEquals(monitorConfig, configManager.getMonitor().get()); + } + + @Test + public void tesModuleConfig() { + ModuleConfig config = new ModuleConfig(); + configManager.setModule(config); + assertTrue(configManager.getModule().isPresent()); + assertEquals(config, configManager.getModule().get()); + } +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java index e7db07d719b..43331e996de 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java @@ -49,9 +49,9 @@ public static void init() { configManager.setApplication(applicationConfig); // Add ProtocolConfig - configManager.addProtocol(protocolConfig(), true); + configManager.addProtocol(protocolConfig()); // Add RegistryConfig - configManager.addRegistry(registryConfig(), true); + configManager.addRegistry(registryConfig()); } private static ProtocolConfig protocolConfig() { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java new file mode 100644 index 00000000000..1dbf90d6121 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java @@ -0,0 +1,114 @@ +/* + * 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.registry.client; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; +import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration; +import org.apache.dubbo.event.EventListener; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; + +import java.util.Set; + +import static com.alibaba.fastjson.JSON.toJSONString; +import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; + +/** + * File System {@link ServiceDiscovery} implementation + * + * @see FileSystemDynamicConfiguration + * @since 2.7.4 + */ +public class FileSystemServiceDiscovery implements ServiceDiscovery, EventListener { + + private final URL connectionURL; + + private FileSystemDynamicConfiguration dynamicConfiguration; + + public FileSystemServiceDiscovery(URL connectionURL) { + this.connectionURL = connectionURL; + } + + @Override + public void onEvent(ServiceInstancesChangedEvent event) { + + } + + @Override + public void start() { + if (dynamicConfiguration == null) { + dynamicConfiguration = createDynamicConfiguration(connectionURL); + } + } + + @Override + public void stop() { + try { + if (dynamicConfiguration != null) { + dynamicConfiguration.close(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private String getConfigKey(ServiceInstance serviceInstance) { + return serviceInstance.getId(); + } + + private String getConfigGroup(ServiceInstance serviceInstance) { + return serviceInstance.getServiceName(); + } + + @Override + public void register(ServiceInstance serviceInstance) throws RuntimeException { + String key = getConfigKey(serviceInstance); + String group = getConfigGroup(serviceInstance); + String content = toJSONString(serviceInstance); + dynamicConfiguration.publishConfig(key, group, content); + } + + @Override + public void update(ServiceInstance serviceInstance) throws RuntimeException { + register(serviceInstance); + } + + @Override + public void unregister(ServiceInstance serviceInstance) throws RuntimeException { + String key = getConfigKey(serviceInstance); + String group = getConfigGroup(serviceInstance); + dynamicConfiguration.removeConfig(key, group); + } + + @Override + public Set getServices() { + return null; + } + + @Override + public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws + NullPointerException, IllegalArgumentException { + + } + + private static FileSystemDynamicConfiguration createDynamicConfiguration(URL connectionURL) { + String protocol = connectionURL.getProtocol(); + DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getExtension(protocol); + return (FileSystemDynamicConfiguration) factory.getDynamicConfiguration(connectionURL); + } +} From 1d54a1d1724a5f149d375fd5d6f5447eb5279e1b Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 25 Jul 2019 22:41:29 +0800 Subject: [PATCH 14/30] Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager --- .../dubbo/bootstrap/DubboBootstrap.java | 46 +++++++---------- .../DubboServiceConsumerBootstrap.java | 4 +- .../configcenter/DynamicConfiguration.java | 15 ++++++ .../DynamicConfigurationFactory.java | 16 ++++++ .../apache/dubbo/config/RegistryConfig.java | 3 +- .../dubbo/config/context/ConfigManager.java | 51 +++++++++---------- 6 files changed, 78 insertions(+), 57 deletions(-) diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java index 872ea883c9d..4e1b4df6531 100644 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java +++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java @@ -19,14 +19,11 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; -import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.extension.ExtensionLoader; 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.config.AbstractConfig; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ConfigCenterConfig; @@ -74,7 +71,9 @@ import static java.util.Arrays.asList; import static java.util.concurrent.Executors.newSingleThreadExecutor; import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties; +import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.context.ConfigManager.getInstance; import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries; @@ -410,20 +409,19 @@ private void loadRemoteConfigs() { */ private void useRegistryAsConfigCenterIfNecessary() { configManager.getDefaultRegistries().forEach(registryConfig -> { - if (registryConfig != null && registryConfig.isZookeeperProtocol()) { - // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. - Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { - Collection configCenters = configManager.getConfigCenters(); - if (CollectionUtils.isEmpty(configCenters)) { - ConfigCenterConfig cc = new ConfigCenterConfig(); - cc.setProtocol(registryConfig.getProtocol()); - cc.setAddress(registryConfig.getAddress()); - cc.setHighestPriority(false); - configManager.addConfigCenter(cc); - } - return null; - }); - } + // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. + Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { + Collection configCenters = configManager.getConfigCenters(); + if (CollectionUtils.isEmpty(configCenters)) { + String protocol = registryConfig.getProtocol(); + ConfigCenterConfig cc = new ConfigCenterConfig(); + cc.setProtocol(protocol); + cc.setAddress(registryConfig.getAddress()); + cc.setHighestPriority(false); + configManager.addConfigCenter(cc); + } + return null; + }); startConfigCenter(); }); } @@ -607,9 +605,9 @@ private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) String appGroup = configManager.getApplication().orElse(new ApplicationConfig()).getName(); String appConfigContent = null; - if (StringUtils.isNotEmpty(appGroup)) { + if (isNotEmpty(appGroup)) { appConfigContent = dynamicConfiguration.getConfigs - (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(), + (isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(), appGroup ); } @@ -625,13 +623,6 @@ private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) return null; } - private DynamicConfiguration getDynamicConfiguration(URL url) { - DynamicConfigurationFactory factory = ExtensionLoader - .getExtensionLoader(DynamicConfigurationFactory.class) - .getExtension(url.getProtocol()); - return factory.getDynamicConfiguration(url); - } - /** * Add an instance of {@link EventListener} * @@ -753,7 +744,8 @@ private void executeMutually(Runnable runnable) { } } - private static List buildConfigs(Map map) { + private static List buildConfigs(Map map) { List configs = new ArrayList<>(); map.entrySet().forEach(entry -> { configs.add((C) entry.getValue().build()); diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java index 2757899befd..0f7a958f021 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java @@ -31,9 +31,9 @@ public static void main(String[] args) throws Exception { new DubboBootstrap() .application("dubbo-consumer-demo") // Zookeeper -// .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo")) + .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo")) // Nacos - .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo")) +// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo")) .reference("ref", builder -> builder.interfaceClass(EchoService.class)) .onlyRegisterProvider(true) .start() diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java index 1bb31156a07..84b6ec337d9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.config.configcenter; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.Configuration; import org.apache.dubbo.common.config.Environment; @@ -25,6 +26,7 @@ import java.util.Optional; import java.util.Set; +import static org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory.getDynamicConfigurationFactory; import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; /** @@ -260,4 +262,17 @@ static DynamicConfiguration getDynamicConfiguration() { .getDefaultExtension() .getDynamicConfiguration(null)); } + + /** + * Get the instance of {@link DynamicConfiguration} by the specified connection {@link URL} + * + * @param connectionURL + * @return non-null + * @since 2.7.4 + */ + static DynamicConfiguration getDynamicConfiguration(URL connectionURL) { + String protocol = connectionURL.getProtocol(); + DynamicConfigurationFactory factory = getDynamicConfigurationFactory(protocol); + return factory.getDynamicConfiguration(connectionURL); + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java index 4875a1b8d19..649eec6420a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java @@ -17,8 +17,11 @@ package org.apache.dubbo.common.config.configcenter; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.SPI; +import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; + /** * The factory interface to create the instance of {@link DynamicConfiguration} */ @@ -27,4 +30,17 @@ public interface DynamicConfigurationFactory { DynamicConfiguration getDynamicConfiguration(URL url); + /** + * Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default + * extension of {@link DynamicConfigurationFactory} + * + * @param name the name of extension of {@link DynamicConfigurationFactory} + * @return non-null + * @see 2.7.4 + */ + static DynamicConfigurationFactory getDynamicConfigurationFactory(String name) { + Class factoryClass = DynamicConfigurationFactory.class; + ExtensionLoader loader = getExtensionLoader(factoryClass); + return loader.hasExtension(name) ? loader.getExtension(name) : loader.getDefaultExtension(); + } } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java index c9a96cb2a51..9bcf789b4b7 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java @@ -181,7 +181,8 @@ public void setAddress(String address) { if (address != null) { int i = address.indexOf("://"); if (i > 0) { - this.updateIdIfAbsent(address.substring(0, i)); + String protocol = address.substring(0, i); + this.setProtocol(protocol); } } } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java index 5a50ab92762..791d715a9f2 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java @@ -44,6 +44,7 @@ import java.util.concurrent.locks.StampedLock; import java.util.stream.Collectors; +import static java.lang.Boolean.TRUE; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; import static java.util.Optional.ofNullable; @@ -157,7 +158,7 @@ public Optional getModule() { // ConfigCenterConfig correlative methods public void addConfigCenter(ConfigCenterConfig configCenter) { - putIfAbsent(configCenter.getId(), configCenter, configCenters); + addIfAbsent(configCenter, configCenters); } public void addConfigCenters(Iterable configCenters) { @@ -175,7 +176,7 @@ public Collection getConfigCenters() { // MetadataReportConfig correlative methods public void addMetadataReport(MetadataReportConfig metadataReportConfig) { - putIfAbsent(metadataReportConfig.getId(), metadataReportConfig, metadataConfigs); + addIfAbsent(metadataReportConfig, metadataConfigs); } public void addMetadataReports(Iterable metadataReportConfigs) { @@ -189,7 +190,7 @@ public Collection getMetadataConfigs() { // MetadataReportConfig correlative methods public void addProvider(ProviderConfig providerConfig) { - putIfAbsent(providerConfig, providers); + addIfAbsent(providerConfig, providers); } public Optional getProvider(String id) { @@ -207,7 +208,7 @@ public Map getProviders() { // ConsumerConfig correlative methods public void addConsumer(ConsumerConfig consumerConfig) { - putIfAbsent(consumerConfig, consumers); + addIfAbsent(consumerConfig, consumers); } public Optional getConsumer(String id) { @@ -225,7 +226,7 @@ public Map getConsumers() { // ProtocolConfig correlative methods public void addProtocol(ProtocolConfig protocolConfig) { - putIfAbsent(protocolConfig, protocols); + addIfAbsent(protocolConfig, protocols); } public void addProtocols(Iterable protocolConfigs, boolean canBeDefault) { @@ -261,7 +262,7 @@ public Set getProtocolIds() { // RegistryConfig correlative methods public void addRegistry(RegistryConfig registryConfig) { - putIfAbsent(registryConfig, registries); + addIfAbsent(registryConfig, registries); } public void addRegistries(Iterable registryConfigs) { @@ -296,7 +297,7 @@ public Set getRegistryIds() { // ServiceConfig correlative methods public void addService(ServiceConfig serviceConfig) { - putIfAbsent(serviceConfig.getId(), serviceConfig, serviceConfigs); + addIfAbsent(serviceConfig, serviceConfigs); } public Collection> getServiceConfigs() { @@ -310,7 +311,7 @@ public ServiceConfig getServiceConfig(String id) { // ReferenceConfig correlative methods public void addReference(ReferenceConfig referenceConfig) { - putIfAbsent(referenceConfig.getId(), referenceConfig, referenceConfigs); + addIfAbsent(referenceConfig, referenceConfigs); } public Collection> getReferenceConfigs() { @@ -405,14 +406,6 @@ private V read(Callable callable) { return value; } - private void putIfAbsent(String key, V value, Map map) { - if (read(() -> !map.containsKey(key) && !map.containsValue(value))) { - write(() -> { - map.putIfAbsent(key, value); - }); - } - } - private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) { if (oldOne != null && !oldOne.equals(newOne)) { String configName = oldOne.getClass().getSimpleName(); @@ -424,17 +417,13 @@ private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) return new HashMap<>(); } - private static void putIfAbsent(C config, Map configsMap) { + private static void addIfAbsent(C config, Map configsMap) { if (config == null) { return; } - String id = config.getId(); - - Boolean isDefault = getProperty(config, "default"); - - String key = isNotEmpty(id) ? id : Boolean.TRUE.equals(isDefault) ? DEFAULT_KEY : null; + String key = getId(config); C existedConfig = configsMap.get(key); @@ -449,13 +438,21 @@ private static void putIfAbsent(C config, Map List getDefaultConfigs(Map configsMap) { + static String getId(C config) { + String id = config.getId(); + return isNotEmpty(id) ? id : isDefaultConfig(config) ? + config.getClass().getSimpleName() + "#" + DEFAULT_KEY : null; + } + + static boolean isDefaultConfig(C config) { + Boolean isDefault = getProperty(config, "default"); + return isDefault == null || TRUE.equals(isDefault); + } + + static List getDefaultConfigs(Map configsMap) { return configsMap.values() .stream() - .filter(config -> { - Boolean isDefault = getProperty(config, "default"); - return isDefault == null || Boolean.TRUE.equals(isDefault); - }) + .filter(ConfigManager::isDefaultConfig) .collect(Collectors.toList()); } } From 5071a04c1349d4c565d109d7997e113504ac337c Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 26 Jul 2019 09:47:00 +0800 Subject: [PATCH 15/30] Polish apache/dubbo#4622 : Support multiple configcenters --- .../dubbo/bootstrap/DubboBootstrap.java | 40 ++++++++++--------- .../DubboServiceConsumerBootstrap.java | 2 +- .../DubboServiceProviderBootstrap.java | 28 ++----------- .../CompositeDynamicConfiguration.java | 3 -- .../apache/dubbo/config/RegistryConfig.java | 13 ++++-- .../dubbo/config/context/ConfigManager.java | 25 ++++++------ .../ServiceInstancePortCustomizer.java | 1 - .../nacos/NacosDynamicConfiguration.java | 13 ++++-- 8 files changed, 57 insertions(+), 68 deletions(-) diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java index 4e1b4df6531..6a2237fa23b 100644 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java +++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java @@ -408,22 +408,26 @@ private void loadRemoteConfigs() { * there's no config center specified explicitly. */ private void useRegistryAsConfigCenterIfNecessary() { - configManager.getDefaultRegistries().forEach(registryConfig -> { - // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. - Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { - Collection configCenters = configManager.getConfigCenters(); - if (CollectionUtils.isEmpty(configCenters)) { - String protocol = registryConfig.getProtocol(); - ConfigCenterConfig cc = new ConfigCenterConfig(); - cc.setProtocol(protocol); - cc.setAddress(registryConfig.getAddress()); - cc.setHighestPriority(false); - configManager.addConfigCenter(cc); - } - return null; - }); - startConfigCenter(); + // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. + if (Environment.getInstance().getDynamicConfiguration().isPresent()) { + return; + } + + if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) { + return; + } + + configManager.getRegistries().forEach(registryConfig -> { + String protocol = registryConfig.getProtocol(); + String id = "config-center-" + protocol + "-" + registryConfig.getPort(); + ConfigCenterConfig cc = new ConfigCenterConfig(); + cc.setId(id); + cc.setProtocol(protocol); + cc.setAddress(registryConfig.getAddress()); + cc.setHighestPriority(false); + configManager.addConfigCenter(cc); }); + startConfigCenter(); } private List getServiceDiscoveries() { @@ -455,8 +459,8 @@ public DubboBootstrap start() { // TODO, only export to default registry? List exportedURLs = exportMetadataService( configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")), - configManager.getRegistries().values(), - configManager.getProtocols().values() + configManager.getRegistries(), + configManager.getProtocols() ); /** @@ -693,7 +697,7 @@ private void destroy() { } private void destroyProtocolConfigs() { - configManager.getProtocols().values().forEach(ProtocolConfig::destroy); + configManager.getProtocols().forEach(ProtocolConfig::destroy); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s all ProtocolConfigs have been destroyed."); } diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java index 0f7a958f021..191b2333131 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // Zookeeper .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo")) // Nacos -// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo")) + .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo")) .reference("ref", builder -> builder.interfaceClass(EchoService.class)) .onlyRegisterProvider(true) .start() diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java index 69d53c19c30..1ed573f0aeb 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java @@ -16,10 +16,6 @@ */ package org.apache.dubbo.bootstrap; -import org.apache.curator.test.TestingServer; - -import java.io.IOException; - /** * Dubbo Provider Bootstrap * @@ -27,34 +23,16 @@ */ public class DubboServiceProviderBootstrap { - private static final String ZK_ADDRESS = "127.0.0.1"; - - private static final int ZK_PORT = 2181; - - public static void main(String[] args) throws Exception { - - String address = "zookeeper://" + ZK_ADDRESS + ":" + ZK_PORT + "?registry-type=service"; - - TestingServer testingServer = new TestingServer(2181, true); - + public static void main(String[] args) { new DubboBootstrap() .application("dubbo-provider-demo") // Zookeeper in service registry type - .registry("zookeeper", builder -> builder.address(address)) + .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service")) // Nacos -// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service")) + .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service")) .protocol(builder -> builder.port(-1).name("dubbo")) .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl())) .start() .await(); - - - // shutdown Zookeeper server - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - try { - testingServer.close(); - } catch (IOException e) { - } - })); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java index 7f98d383d7d..016265df873 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java @@ -89,9 +89,6 @@ private Object iterateConfigOperation(Function fun Object value = null; for (DynamicConfiguration configuration : configurations) { value = func.apply(configuration); - if (value != null) { - break; - } } return value; } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java index 9bcf789b4b7..a5196df6144 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.config; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.remoting.Constants; @@ -179,10 +180,14 @@ public String getAddress() { public void setAddress(String address) { this.address = address; if (address != null) { - int i = address.indexOf("://"); - if (i > 0) { - String protocol = address.substring(0, i); - this.setProtocol(protocol); + try { + URL url = URL.valueOf(address); + setUsername(url.getUsername()); + setPassword(url.getPassword()); + setProtocol(url.getProtocol()); + setPort(url.getPort()); + setParameters(url.getParameters()); + } catch (Exception ignored) { } } } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java index 791d715a9f2..188881906be 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java @@ -45,7 +45,6 @@ import java.util.stream.Collectors; import static java.lang.Boolean.TRUE; -import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; import static java.util.Optional.ofNullable; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; @@ -201,8 +200,8 @@ public Optional getDefaultProvider() { return getProvider(DEFAULT_KEY); } - public Map getProviders() { - return unmodifiableMap(providers); + public Collection getProviders() { + return providers.values(); } // ConsumerConfig correlative methods @@ -219,8 +218,8 @@ public Optional getDefaultConsumer() { return getConsumer(DEFAULT_KEY); } - public Map getConsumers() { - return unmodifiableMap(consumers); + public Collection getConsumers() { + return consumers.values(); } // ProtocolConfig correlative methods @@ -243,8 +242,8 @@ public List getDefaultProtocols() { return getDefaultConfigs(protocols); } - public Map getProtocols() { - return unmodifiableMap(protocols); + public Collection getProtocols() { + return protocols.values(); } public Set getProtocolIds() { @@ -279,8 +278,8 @@ public List getDefaultRegistries() { return getDefaultConfigs(registries); } - public Map getRegistries() { - return unmodifiableMap(registries); + public Collection getRegistries() { + return registries.values(); } public Set getRegistryIds() { @@ -336,10 +335,10 @@ public void refreshAll() { getMonitor().ifPresent(MonitorConfig::refresh); getModule().ifPresent(ModuleConfig::refresh); - getProtocols().values().forEach(ProtocolConfig::refresh); - getRegistries().values().forEach(RegistryConfig::refresh); - getProviders().values().forEach(ProviderConfig::refresh); - getConsumers().values().forEach(ConsumerConfig::refresh); + getProtocols().forEach(ProtocolConfig::refresh); + getRegistries().forEach(RegistryConfig::refresh); + getProviders().forEach(ProviderConfig::refresh); + getConsumers().forEach(ConsumerConfig::refresh); }); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java index 37e9b3c16b6..25c4d203538 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java @@ -38,7 +38,6 @@ public void customize(ServiceInstance serviceInstance) { ConfigManager.getInstance() .getProtocols() - .values() .stream() .findFirst() .ifPresent(protocolConfig -> { diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java index 8c827a332f1..6bcafcd4ce9 100644 --- a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java @@ -94,12 +94,19 @@ private ConfigService buildConfigService(URL url) { } public void publishNacosConfig(String key, String value) { + String[] keyAndGroup = getKeyAndGroup(key); + publishConfig(keyAndGroup[0], keyAndGroup[1], value); + } + + @Override + public boolean publishConfig(String key, String group, String content) { + boolean published = false; try { - String[] keyAndGroup = getKeyAndGroup(key); - configService.publishConfig(keyAndGroup[0], keyAndGroup[1], value); + published = configService.publishConfig(key, group, content); } catch (NacosException e) { logger.error(e.getErrMsg()); } + return published; } private String[] getKeyAndGroup(String key) { @@ -107,7 +114,7 @@ private String[] getKeyAndGroup(String key) { if (i < 0) { return new String[]{key, null}; } else { - return new String[]{key.substring(0, i), key.substring(i+1)}; + return new String[]{key.substring(0, i), key.substring(i + 1)}; } } From ccf614cdadf23940112617f58efc09eb13e61a54 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 26 Jul 2019 14:37:13 +0800 Subject: [PATCH 16/30] Polish apache/dubbo#4671 : ServiceNameMapping will not map the group, version and protocol --- ...ynamicConfigurationServiceNameMapping.java | 13 ++++--- ...icConfigurationServiceNameMappingTest.java | 38 +++---------------- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java index 287ba734c52..db22c6cf9fe 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java @@ -70,7 +70,6 @@ public Set get(String serviceInterface, String group, String version, St DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration(); - String key = ApplicationModel.getApplication(); Set serviceNames = new LinkedHashSet<>(); execute(() -> { Set keys = dynamicConfiguration.getConfigKeys(buildGroup(serviceInterface, group, version, protocol)); @@ -80,11 +79,13 @@ public Set get(String serviceInterface, String group, String version, St } protected static String buildGroup(String serviceInterface, String group, String version, String protocol) { - StringBuilder groupBuilder = new StringBuilder(serviceInterface) - .append(SEPARATOR).append(defaultString(group)) - .append(SEPARATOR).append(defaultString(version)) - .append(SEPARATOR).append(defaultString(protocol)); - return groupBuilder.toString(); + // the issue : https://github.com/apache/dubbo/issues/4671 + // StringBuilder groupBuilder = new StringBuilder(serviceInterface) + // .append(SEPARATOR).append(defaultString(group)) + // .append(SEPARATOR).append(defaultString(version)) + // .append(SEPARATOR).append(defaultString(protocol)); + // return groupBuilder.toString(); + return serviceInterface; } private static String defaultString(String value) { diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java index 8b2743f968a..8afbeed9989 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java @@ -16,18 +16,11 @@ */ package org.apache.dubbo.metadata; -import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; -import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.rpc.model.ApplicationModel; -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.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -47,44 +40,25 @@ */ public class DynamicConfigurationServiceNameMappingTest { - private static CuratorFramework client; - - private static URL configUrl; - private static int zkServerPort = NetUtils.getAvailablePort(); - private static TestingServer zkServer; private final ServiceNameMapping serviceNameMapping = getDefaultExtension(); @BeforeAll public static void setUp() throws Exception { - zkServer = new TestingServer(zkServerPort, true); - - client = CuratorFrameworkFactory.newClient("localhost:" + zkServerPort, 60 * 1000, 60 * 1000, - new ExponentialBackoffRetry(1000, 3)); - - client.start(); - - configUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); - DynamicConfiguration configuration = getExtensionLoader(DynamicConfigurationFactory.class) - .getExtension(configUrl.getProtocol()) - .getDynamicConfiguration(configUrl); + .getDefaultExtension() + .getDynamicConfiguration(null); Environment.getInstance().setDynamicConfiguration(configuration); } - @AfterAll - public static void tearDown() throws Exception { - zkServer.stop(); - } - @Test public void testBuildGroup() { - assertEquals("test:::", buildGroup("test", null, null, null)); - assertEquals("test:default::", buildGroup("test", "default", null, null)); - assertEquals("test:default:1.0.0:", buildGroup("test", "default", "1.0.0", null)); - assertEquals("test:default:1.0.0:dubbo", buildGroup("test", "default", "1.0.0", "dubbo")); + assertEquals("test", buildGroup("test", null, null, null)); + assertEquals("test", buildGroup("test", "default", null, null)); + assertEquals("test", buildGroup("test", "default", "1.0.0", null)); + assertEquals("test", buildGroup("test", "default", "1.0.0", "dubbo")); } @Test From 87e88e28df5bb13f5f94dafdbfa72e4f93a83259 Mon Sep 17 00:00:00 2001 From: Haiyang Date: Mon, 29 Jul 2019 13:07:10 +0800 Subject: [PATCH 17/30] update referenceCount log (#4683) Add comments to support multiple shared connections --- .../org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java | 2 +- .../dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) 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 3cc20237f32..1a9640c796a 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 @@ -520,7 +520,7 @@ private boolean checkClientCanUse(List referenceCo } /** - * Add client references in bulk + * Increase the reference Count if we create new invoker shares same connection, the connection will be closed without any reference. * * @param referenceCountExchangeClients */ diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java index c7074aa9dbe..bda87cae7f7 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java @@ -192,6 +192,9 @@ public boolean isClosed() { return client.isClosed(); } + /** + * The reference count of current ExchangeClient, connection will be closed if all invokers destroyed. + */ public void incrementAndGetCount() { referenceCount.incrementAndGet(); } From 5d299aff2f31e1373c7e32a8ae37a2238c725267 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Mon, 29 Jul 2019 15:44:59 +0800 Subject: [PATCH 18/30] Polish /apache/dubbo#4687 : Remove the duplicated test code in dubbo-config-spring (#4688) --- .../annotation/EnableDubboConfigTest.java | 11 ++ .../DubboComponentScanRegistrarTest.java | 118 ------------- .../DubboConfigBindingRegistrarTest.java | 88 ---------- .../DubboConfigBindingsRegistrarTest.java | 63 ------- .../DubboConfigConfigurationTest.java | 99 ----------- .../annotation/EnableDubboConfigTest.java | 120 ------------- .../context/annotation/EnableDubboTest.java | 162 ------------------ .../consumer/ConsumerConfiguration.java | 126 -------------- .../test/TestConsumerConfiguration.java | 96 ----------- .../provider/DefaultHelloService.java | 40 ----- .../annotation/provider/DemoServiceImpl.java | 55 ------ .../annotation/provider/HelloServiceImpl.java | 34 ---- .../provider/ProviderConfiguration.java | 109 ------------ .../DefaultDubboConfigBinderTest.java | 94 ---------- 14 files changed, 11 insertions(+), 1204 deletions(-) delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboComponentScanRegistrarTest.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingRegistrarTest.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingsRegistrarTest.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigConfigurationTest.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboConfigTest.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboTest.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/ConsumerConfiguration.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/test/TestConsumerConfiguration.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DemoServiceImpl.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/HelloServiceImpl.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/ProviderConfiguration.java delete mode 100644 dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/properties/DefaultDubboConfigBinderTest.java diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java index b611c060196..559553e7404 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java @@ -24,11 +24,14 @@ import org.apache.dubbo.config.ProviderConfig; import org.apache.dubbo.config.RegistryConfig; +import org.junit.Assert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.PropertySource; +import java.util.Map; + /** * {@link EnableDubboConfig} Test * @@ -92,6 +95,14 @@ public void testMultiple() { ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class); Assertions.assertEquals("dubbo-demo-application3", applicationBean3.getName()); + Map protocolConfigs = context.getBeansOfType(ProtocolConfig.class); + + for (Map.Entry entry : protocolConfigs.entrySet()) { + String beanName = entry.getKey(); + ProtocolConfig protocol = entry.getValue(); + Assert.assertEquals(beanName, protocol.getName()); + } + } @EnableDubboConfig diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboComponentScanRegistrarTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboComponentScanRegistrarTest.java deleted file mode 100644 index 6ed8a857528..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboComponentScanRegistrarTest.java +++ /dev/null @@ -1,118 +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.config.spring.context.context.annotation; - -import org.apache.dubbo.config.spring.api.DemoService; -import org.apache.dubbo.config.spring.context.annotation.DubboComponentScanRegistrar; -import org.apache.dubbo.config.spring.context.annotation.consumer.ConsumerConfiguration; -import org.apache.dubbo.config.spring.context.annotation.provider.DemoServiceImpl; -import org.apache.dubbo.config.spring.context.annotation.provider.ProviderConfiguration; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.aop.support.AopUtils; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.transaction.annotation.Transactional; - -import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; - -/** - * {@link DubboComponentScanRegistrar} Test - * - * @since 2.5.8 - */ -public class DubboComponentScanRegistrarTest { - - @Test - public void test() { - - AnnotationConfigApplicationContext providerContext = new AnnotationConfigApplicationContext(); - - providerContext.register(ProviderConfiguration.class); - - providerContext.refresh(); - - DemoService demoService = providerContext.getBean(DemoService.class); - - String value = demoService.sayName("Mercy"); - - Assertions.assertEquals("Hello,Mercy", value); - - Class beanClass = AopUtils.getTargetClass(demoService); - - // DemoServiceImpl with @Transactional - Assertions.assertEquals(DemoServiceImpl.class, beanClass); - - // Test @Transactional is present or not - Assertions.assertNotNull(findAnnotation(beanClass, Transactional.class)); - - AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext(); - - consumerContext.register(ConsumerConfiguration.class); - - consumerContext.refresh(); - - ConsumerConfiguration consumerConfiguration = consumerContext.getBean(ConsumerConfiguration.class); - - demoService = consumerConfiguration.getDemoService(); - - value = demoService.sayName("Mercy"); - - Assertions.assertEquals("Hello,Mercy", value); - - ConsumerConfiguration.Child child = consumerContext.getBean(ConsumerConfiguration.Child.class); - - // From Child - - demoService = child.getDemoServiceFromChild(); - - Assertions.assertNotNull(demoService); - - value = demoService.sayName("Mercy"); - - Assertions.assertEquals("Hello,Mercy", value); - - Assertions.assertEquals("Hello,Mercy", child.getDemoService().sayName("Mercy")); - - // From Parent - - demoService = child.getDemoServiceFromParent(); - - Assertions.assertNotNull(demoService); - - value = demoService.sayName("Mercy"); - - Assertions.assertEquals("Hello,Mercy", value); - - // From Ancestor - - demoService = child.getDemoServiceFromAncestor(); - - Assertions.assertNotNull(demoService); - - value = demoService.sayName("Mercy"); - - Assertions.assertEquals("Hello,Mercy", value); - - providerContext.close(); - consumerContext.close(); - - - } - - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingRegistrarTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingRegistrarTest.java deleted file mode 100644 index 48c06d4b47d..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingRegistrarTest.java +++ /dev/null @@ -1,88 +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.config.spring.context.context.annotation; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.spring.context.annotation.DubboConfigBindingRegistrar; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfigBinding; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.PropertySource; - -/** - * {@link DubboConfigBindingRegistrar} - * - * @since 2.5.8 - */ -public class DubboConfigBindingRegistrarTest { - - @Test - public void testRegisterBeanDefinitionsForSingle() { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - - context.register(TestApplicationConfig.class); - - context.refresh(); - - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - - } - - @Test - public void testRegisterBeanDefinitionsForMultiple() { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - - context.register(TestMultipleApplicationConfig.class); - - context.refresh(); - - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - applicationConfig = context.getBean("applicationBean2", ApplicationConfig.class); - - Assertions.assertEquals("dubbo-demo-application2", applicationConfig.getName()); - - applicationConfig = context.getBean("applicationBean3", ApplicationConfig.class); - - Assertions.assertEquals("dubbo-demo-application3", applicationConfig.getName()); - - - } - - @EnableDubboConfigBinding(prefix = "${application.prefixes}", type = ApplicationConfig.class, multiple = true) - @PropertySource("META-INF/config.properties") - private static class TestMultipleApplicationConfig { - - } - - @EnableDubboConfigBinding(prefix = "${application.prefix}", type = ApplicationConfig.class) - @PropertySource("META-INF/config.properties") - private static class TestApplicationConfig { - - } - - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingsRegistrarTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingsRegistrarTest.java deleted file mode 100644 index f09782913d3..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigBindingsRegistrarTest.java +++ /dev/null @@ -1,63 +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.config.spring.context.context.annotation; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.spring.context.annotation.DubboConfigBindingsRegistrar; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfigBinding; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfigBindings; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.PropertySource; - -/** - * {@link DubboConfigBindingsRegistrar} Test - * - * @since DubboConfigBindingsRegistrar - */ -public class DubboConfigBindingsRegistrarTest { - - @Test - public void test() { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - - context.register(TestConfig.class); - - context.refresh(); - - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - Assertions.assertEquals(2, context.getBeansOfType(ApplicationConfig.class).size()); - - } - - - @EnableDubboConfigBindings({ - @EnableDubboConfigBinding(prefix = "${application.prefix}", type = ApplicationConfig.class), - @EnableDubboConfigBinding(prefix = "dubbo.applications.applicationBean", type = ApplicationConfig.class) - }) - @PropertySource("META-INF/config.properties") - private static class TestConfig { - - } - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigConfigurationTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigConfigurationTest.java deleted file mode 100644 index d4f28aae301..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/DubboConfigConfigurationTest.java +++ /dev/null @@ -1,99 +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.config.spring.context.context.annotation; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.context.annotation.DubboConfigConfiguration; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.core.io.support.ResourcePropertySource; - -import java.io.IOException; - -/** - * {@link DubboConfigConfiguration} Test - * - * @since 2.5.8 - */ -public class DubboConfigConfigurationTest { - - private AnnotationConfigApplicationContext context; - - @BeforeEach - public void before() throws IOException { - - context = new AnnotationConfigApplicationContext(); - ResourcePropertySource propertySource = new ResourcePropertySource("META-INF/config.properties"); - context.getEnvironment().getPropertySources().addFirst(propertySource); - - } - - @AfterEach - public void after() { - context.close(); - } - - @Test - public void testSingle() throws IOException { - - context.register(DubboConfigConfiguration.Single.class); - context.refresh(); - - // application - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - // module - ModuleConfig moduleConfig = context.getBean("moduleBean", ModuleConfig.class); - Assertions.assertEquals("dubbo-demo-module", moduleConfig.getName()); - - // registry - RegistryConfig registryConfig = context.getBean(RegistryConfig.class); - Assertions.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress()); - - // protocol - ProtocolConfig protocolConfig = context.getBean(ProtocolConfig.class); - Assertions.assertEquals("dubbo", protocolConfig.getName()); - Assertions.assertEquals(Integer.valueOf(20880), protocolConfig.getPort()); - } - - @Test - public void testMultiple() { - - context.register(DubboConfigConfiguration.Multiple.class); - context.refresh(); - - // application - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - ApplicationConfig applicationBean2 = context.getBean("applicationBean2", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application2", applicationBean2.getName()); - - ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application3", applicationBean3.getName()); - - } - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboConfigTest.java deleted file mode 100644 index 691f251dac6..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboConfigTest.java +++ /dev/null @@ -1,120 +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.config.spring.context.context.annotation; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; - -import org.junit.Assert; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.PropertySource; - -import java.util.Map; - -/** - * {@link EnableDubboConfig} Test - * - * @since 2.5.8 - */ -public class EnableDubboConfigTest { - - @Test - public void testSingle() { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(TestConfig.class); - context.refresh(); - - // application - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - // module - ModuleConfig moduleConfig = context.getBean("moduleBean", ModuleConfig.class); - Assertions.assertEquals("dubbo-demo-module", moduleConfig.getName()); - - // registry - RegistryConfig registryConfig = context.getBean(RegistryConfig.class); - Assertions.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress()); - - // protocol - ProtocolConfig protocolConfig = context.getBean(ProtocolConfig.class); - Assertions.assertEquals("dubbo", protocolConfig.getName()); - Assertions.assertEquals(Integer.valueOf(20880), protocolConfig.getPort()); - - // monitor - MonitorConfig monitorConfig = context.getBean(MonitorConfig.class); - Assertions.assertEquals("zookeeper://127.0.0.1:32770", monitorConfig.getAddress()); - - // provider - ProviderConfig providerConfig = context.getBean(ProviderConfig.class); - Assertions.assertEquals("127.0.0.1", providerConfig.getHost()); - - - // consumer - ConsumerConfig consumerConfig = context.getBean(ConsumerConfig.class); - Assertions.assertEquals("netty", consumerConfig.getClient()); - - } - - @Test - public void testMultiple() { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(TestMultipleConfig.class); - context.refresh(); - - // application - ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - ApplicationConfig applicationBean2 = context.getBean("applicationBean2", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application2", applicationBean2.getName()); - - ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class); - Assertions.assertEquals("dubbo-demo-application3", applicationBean3.getName()); - - Map protocolConfigs = context.getBeansOfType(ProtocolConfig.class); - - for (Map.Entry entry : protocolConfigs.entrySet()) { - String beanName = entry.getKey(); - ProtocolConfig protocol = entry.getValue(); - Assert.assertEquals(beanName, protocol.getName()); - } - - } - - @EnableDubboConfig - @PropertySource("META-INF/config.properties") - private static class TestMultipleConfig { - - } - - @EnableDubboConfig(multiple = false) - @PropertySource("META-INF/config.properties") - private static class TestConfig { - - } -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboTest.java deleted file mode 100644 index 1366a35d252..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/EnableDubboTest.java +++ /dev/null @@ -1,162 +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.config.spring.context.context.annotation; - -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.api.DemoService; -import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; -import org.apache.dubbo.config.spring.context.annotation.consumer.test.TestConsumerConfiguration; -import org.apache.dubbo.config.spring.context.annotation.provider.DemoServiceImpl; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.PropertySource; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.springframework.transaction.annotation.Transactional; - -import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; - -/** - * {@link EnableDubbo} Test - * - * @since 2.5.8 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {EnableDubboTest.class}) -@TestPropertySource(locations = "classpath:/META-INF/dubbb-provider.properties", - properties = "demo.service.version = 2.5.7") -@EnableDubbo(scanBasePackages = "org.apache.dubbo.config.spring.context.annotation.provider") -@ComponentScan(basePackages = "org.apache.dubbo.config.spring.context.annotation.provider") -@EnableTransactionManagement -public class EnableDubboTest { - - @Autowired - private ApplicationContext providerContext; - - @Test - public void test() { - - DemoService demoService = providerContext.getBean(DemoService.class); - - String value = demoService.sayName("Mercy"); - - Assert.assertEquals("Hello,Mercy", value); - - Class beanClass = AopUtils.getTargetClass(demoService); - - // DemoServiceImpl with @Transactional - Assert.assertEquals(DemoServiceImpl.class, beanClass); - - // Test @Transactional is present or not - Assert.assertNotNull(findAnnotation(beanClass, Transactional.class)); - - AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext(TestConsumerConfiguration.class); - - TestConsumerConfiguration consumerConfiguration = consumerContext.getBean(TestConsumerConfiguration.class); - - demoService = consumerConfiguration.getDemoService(); - - value = demoService.sayName("Mercy"); - - Assert.assertEquals("Hello,Mercy", value); - - TestConsumerConfiguration.Child child = consumerContext.getBean(TestConsumerConfiguration.Child.class); - - // From Child - - demoService = child.getDemoServiceFromChild(); - - Assert.assertNotNull(demoService); - - value = demoService.sayName("Mercy"); - - Assert.assertEquals("Hello,Mercy", value); - - // From Parent - - demoService = child.getDemoServiceFromParent(); - - Assert.assertNotNull(demoService); - - value = demoService.sayName("Mercy"); - - Assert.assertEquals("Hello,Mercy", value); - - // From Ancestor - - demoService = child.getDemoServiceFromAncestor(); - - Assert.assertNotNull(demoService); - - value = demoService.sayName("Mercy"); - - Assert.assertEquals("Hello,Mercy", value); - - // Test my-registry2 bean presentation - RegistryConfig registryConfig = consumerContext.getBean("my-registry2", RegistryConfig.class); - - // Test multiple binding - Assert.assertEquals("N/A", registryConfig.getAddress()); - - } - - @EnableDubbo(scanBasePackages = "org.apache.dubbo.config.spring.context.annotation.provider") - @ComponentScan(basePackages = "org.apache.dubbo.config.spring.context.annotation.provider") - @PropertySource("classpath:/META-INF/dubbb-provider.properties") - @EnableTransactionManagement - public static class TestProviderConfiguration { - - @Primary - @Bean - public PlatformTransactionManager platformTransactionManager() { - return new PlatformTransactionManager() { - - @Override - public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { - return null; - } - - @Override - public void commit(TransactionStatus status) throws TransactionException { - - } - - @Override - public void rollback(TransactionStatus status) throws TransactionException { - - } - }; - } - } - - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/ConsumerConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/ConsumerConfiguration.java deleted file mode 100644 index 04866986197..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/ConsumerConfiguration.java +++ /dev/null @@ -1,126 +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.config.spring.context.context.annotation.consumer; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.annotation.Reference; -import org.apache.dubbo.config.spring.api.DemoService; -import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; - -@Configuration("consumerConfiguration") -@DubboComponentScan( - basePackageClasses = ConsumerConfiguration.class -) -@PropertySource("META-INF/default.properties") -public class ConsumerConfiguration { - - /** - * Current application configuration, to replace XML config: - * - * <dubbo:application name="dubbo-demo-application"/> - * - * - * @return {@link ApplicationConfig} Bean - */ - @Bean("dubbo-demo-application") - public ApplicationConfig applicationConfig() { - ApplicationConfig applicationConfig = new ApplicationConfig(); - applicationConfig.setName("dubbo-demo-application"); - return applicationConfig; - } - - /** - * Current registry center configuration, to replace XML config: - * - * <dubbo:registry address="N/A"/> - * - * - * @return {@link RegistryConfig} Bean - */ - @Bean - public RegistryConfig registryConfig() { - RegistryConfig registryConfig = new RegistryConfig(); - registryConfig.setAddress("N/A"); - return registryConfig; - } - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345") - private DemoService demoService; - - public DemoService getDemoService() { - return demoService; - } - - public void setDemoService(DemoService demoService) { - this.demoService = demoService; - } - - - @Bean - public Child c() { - return new Child(); - } - - public static abstract class Ancestor { - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345") - private DemoService demoServiceFromAncestor; - - public DemoService getDemoServiceFromAncestor() { - return demoServiceFromAncestor; - } - - public void setDemoServiceFromAncestor(DemoService demoServiceFromAncestor) { - this.demoServiceFromAncestor = demoServiceFromAncestor; - } - } - - public static abstract class Parent extends Ancestor { - - private DemoService demoServiceFromParent; - - public DemoService getDemoServiceFromParent() { - return demoServiceFromParent; - } - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345") - public void setDemoServiceFromParent(DemoService demoServiceFromParent) { - this.demoServiceFromParent = demoServiceFromParent; - } - - } - - public static class Child extends Parent { - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345") - private DemoService demoServiceFromChild; - - public DemoService getDemoServiceFromChild() { - return demoServiceFromChild; - } - - public void setDemoServiceFromChild(DemoService demoServiceFromChild) { - this.demoServiceFromChild = demoServiceFromChild; - } - } - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/test/TestConsumerConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/test/TestConsumerConfiguration.java deleted file mode 100644 index dc41c614cd8..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/consumer/test/TestConsumerConfiguration.java +++ /dev/null @@ -1,96 +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.config.spring.context.context.annotation.consumer.test; - -import org.apache.dubbo.config.annotation.Reference; -import org.apache.dubbo.config.spring.api.DemoService; -import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.PropertySource; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -/** - * Test Consumer Configuration - * - * @since 2.5.7 - */ -@EnableDubbo(scanBasePackageClasses = TestConsumerConfiguration.class, multipleConfig = true) -@PropertySource("META-INF/dubbb-consumer.properties") -@EnableTransactionManagement -public class TestConsumerConfiguration { - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-demo-application") - private DemoService demoService; - - public DemoService getDemoService() { - return demoService; - } - - public void setDemoService(DemoService demoService) { - this.demoService = demoService; - } - - - @Bean - public TestConsumerConfiguration.Child c() { - return new TestConsumerConfiguration.Child(); - } - - public static abstract class Ancestor { - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-demo-application") - private DemoService demoServiceFromAncestor; - - public DemoService getDemoServiceFromAncestor() { - return demoServiceFromAncestor; - } - - public void setDemoServiceFromAncestor(DemoService demoServiceFromAncestor) { - this.demoServiceFromAncestor = demoServiceFromAncestor; - } - } - - public static abstract class Parent extends TestConsumerConfiguration.Ancestor { - - private DemoService demoServiceFromParent; - - public DemoService getDemoServiceFromParent() { - return demoServiceFromParent; - } - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-demo-application") - public void setDemoServiceFromParent(DemoService demoServiceFromParent) { - this.demoServiceFromParent = demoServiceFromParent; - } - - } - - public static class Child extends TestConsumerConfiguration.Parent { - - @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-demo-application") - private DemoService demoServiceFromChild; - - public DemoService getDemoServiceFromChild() { - return demoServiceFromChild; - } - - public void setDemoServiceFromChild(DemoService demoServiceFromChild) { - this.demoServiceFromChild = demoServiceFromChild; - } - } -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java deleted file mode 100644 index 8277bc9b4e8..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java +++ /dev/null @@ -1,40 +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.config.spring.context.context.annotation.provider; - -import org.apache.dubbo.config.spring.annotation.merged.MergedService; -import org.apache.dubbo.config.spring.api.HelloService; - -import org.springframework.stereotype.Service; - -/** - * Default {@link HelloService} annotation with Spring's {@link Service} - * and Dubbo's {@link org.apache.dubbo.config.annotation.Service} - * - * @since TODO - */ -@Service -//@org.apache.dubbo.config.annotation.Service -@MergedService -public class DefaultHelloService implements HelloService { - - @Override - public String sayHello(String name) { - return "Greeting, " + name; - } - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DemoServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DemoServiceImpl.java deleted file mode 100644 index 155bd2a5539..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DemoServiceImpl.java +++ /dev/null @@ -1,55 +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.config.spring.context.context.annotation.provider; - -import org.apache.dubbo.config.spring.api.Box; -import org.apache.dubbo.config.spring.api.DemoService; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - - -/** - * {@link DemoService} Service implementation - * - * @since 2.5.8 - */ -@org.apache.dubbo.config.annotation.Service( - version = "${demo.service.version}", - application = "${demo.service.application}", - protocol = "${demo.service.protocol}", - registry = "${demo.service.registry}" -) -@Service -@Transactional -public class DemoServiceImpl implements DemoService { - - @Override - public String sayName(String name) { - return "Hello," + name; - } - - @Override - public Box getBox() { - return new Box() { - @Override - public String getName() { - return "MyBox"; - } - }; - } -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/HelloServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/HelloServiceImpl.java deleted file mode 100644 index 10b00a8f5b3..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/HelloServiceImpl.java +++ /dev/null @@ -1,34 +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.config.spring.context.context.annotation.provider; - -import org.apache.dubbo.config.annotation.Service; -import org.apache.dubbo.config.spring.api.HelloService; - -/** - * {@link HelloService} Implementation just annotating Dubbo's {@link Service} - * - * @since 2.5.9 - */ -@Service(interfaceName = "org.apache.dubbo.config.spring.api.HelloService") -public class HelloServiceImpl implements HelloService { - - @Override - public String sayHello(String name) { - return "Hello, " + name; - } -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/ProviderConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/ProviderConfiguration.java deleted file mode 100644 index 9c45d7134a5..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/ProviderConfiguration.java +++ /dev/null @@ -1,109 +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.config.spring.context.context.annotation.provider; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.PropertySource; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@DubboComponentScan(basePackages = "org.apache.dubbo") -@ComponentScan(basePackages = "org.apache.dubbo") -@PropertySource("META-INF/default.properties") -@EnableTransactionManagement -public class ProviderConfiguration { - - /** - * Current application configuration, to replace XML config: - * - * <dubbo:application name="dubbo-demo-application"/> - * - * - * @return {@link ApplicationConfig} Bean - */ - @Bean("dubbo-demo-application") - public ApplicationConfig applicationConfig() { - ApplicationConfig applicationConfig = new ApplicationConfig(); - applicationConfig.setName("dubbo-demo-application"); - return applicationConfig; - } - - /** - * Current registry center configuration, to replace XML config: - * - * <dubbo:registry id="my-registry" address="N/A"/> - * - * - * @return {@link RegistryConfig} Bean - */ - @Bean("my-registry") - public RegistryConfig registryConfig() { - RegistryConfig registryConfig = new RegistryConfig(); - registryConfig.setAddress("N/A"); - return registryConfig; - } - - /** - * Current protocol configuration, to replace XML config: - * - * <dubbo:protocol name="dubbo" port="12345"/> - * - * - * @return {@link ProtocolConfig} Bean - */ - @Bean("dubbo") - public ProtocolConfig protocolConfig() { - ProtocolConfig protocolConfig = new ProtocolConfig(); - protocolConfig.setName("dubbo"); - protocolConfig.setPort(12345); - return protocolConfig; - } - - @Primary - @Bean - public PlatformTransactionManager platformTransactionManager() { - return new PlatformTransactionManager() { - - @Override - public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { - return null; - } - - @Override - public void commit(TransactionStatus status) throws TransactionException { - - } - - @Override - public void rollback(TransactionStatus status) throws TransactionException { - - } - }; - } - -} - diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/properties/DefaultDubboConfigBinderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/properties/DefaultDubboConfigBinderTest.java deleted file mode 100644 index 1caddb0b31b..00000000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/properties/DefaultDubboConfigBinderTest.java +++ /dev/null @@ -1,94 +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.config.spring.context.context.properties; - - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.beans.factory.config.YamlPropertySourceFactory; -import org.apache.dubbo.config.spring.context.properties.DefaultDubboConfigBinder; -import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@TestPropertySource(locations = "classpath:/dubbo.properties") -@PropertySource(name = "yaml-source", value = {"classpath:/META-INF/dubbo.yml"}, factory = YamlPropertySourceFactory.class) -@Configuration -@ContextConfiguration(classes = {DefaultDubboConfigBinder.class, DefaultDubboConfigBinderTest.class}) -public class DefaultDubboConfigBinderTest { - - @Autowired - private DubboConfigBinder dubboConfigBinder; - - @Value("${dubbo.consumer.default}") - private Boolean isDefault; - - @Value("${dubbo.consumer.client}") - private String client; - - @Value("${dubbo.consumer.threadpool}") - private String threadPool; - - @Value("${dubbo.consumer.corethreads}") - private Integer coreThreads; - - @Value("${dubbo.consumer.threads}") - private Integer threads; - - @Value("${dubbo.consumer.queues}") - private Integer queues; - - @Test - public void testBinder() { - - ApplicationConfig applicationConfig = new ApplicationConfig(); - dubboConfigBinder.bind("dubbo.application", applicationConfig); - Assert.assertEquals("hello", applicationConfig.getName()); - Assert.assertEquals("world", applicationConfig.getOwner()); - - RegistryConfig registryConfig = new RegistryConfig(); - dubboConfigBinder.bind("dubbo.registry", registryConfig); - Assert.assertEquals("10.20.153.17", registryConfig.getAddress()); - - ProtocolConfig protocolConfig = new ProtocolConfig(); - dubboConfigBinder.bind("dubbo.protocol", protocolConfig); - Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort()); - - ConsumerConfig consumerConfig = new ConsumerConfig(); - dubboConfigBinder.bind("dubbo.consumer", consumerConfig); - - Assert.assertEquals(isDefault, consumerConfig.isDefault()); - Assert.assertEquals(client, consumerConfig.getClient()); - Assert.assertEquals(threadPool, consumerConfig.getThreadpool()); - Assert.assertEquals(coreThreads, consumerConfig.getCorethreads()); - Assert.assertEquals(threads, consumerConfig.getThreads()); - Assert.assertEquals(queues, consumerConfig.getQueues()); - } -} - From 25ec31ea169260712193e2bfba375637c6d4b1bf Mon Sep 17 00:00:00 2001 From: smipo <53416128+smipo@users.noreply.github.com> Date: Tue, 30 Jul 2019 13:18:52 +0800 Subject: [PATCH 19/30] =?UTF-8?q?#4685=20=20=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81if=E5=88=A4=E6=96=ADfalse=E9=97=AE=E9=A2=98=20if=20(ha?= =?UTF-8?q?sException=20=3D=3D=20false)=E4=BF=AE=E6=94=B9=E6=88=90if=20(!h?= =?UTF-8?q?asException)=20(#4695)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/java/org/apache/dubbo/filter/LegacyInvoker.java | 2 +- .../org/apache/dubbo/remoting/PerformanceClientFixedTest.java | 2 +- .../test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java | 2 +- .../src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java b/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java index f77e0a523d0..b1d19b57c31 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java @@ -59,7 +59,7 @@ public boolean isAvailable() { public Result invoke(Invocation invocation) throws RpcException { AppResponse result = new AppResponse(); - if (hasException == false) { + if (!hasException) { result.setValue("alibaba"); } else { result.setException(new RuntimeException("mocked exception")); diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java index 93ccc76e515..8380f5a675a 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java @@ -80,7 +80,7 @@ public void testClient() throws Exception { } catch (Throwable t) { t.printStackTrace(); } finally { - if (client != null && client.isConnected() == false) { + if (client != null && !client.isConnected()) { f++; System.out.println("open client failed, try again " + f); client.close(); diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java index 7fec8d49fdb..ee6e1bea9f7 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java @@ -40,7 +40,7 @@ public BlockMyInvoker(URL url, boolean hasException, long blockTime) { @Override public Result invoke(Invocation invocation) throws RpcException { AppResponse result = new AppResponse(); - if (hasException == false) { + if (!hasException) { try { Thread.sleep(blockTime); } catch (InterruptedException e) { diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java index 57f1f1e6cc5..ffccff64ea8 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java @@ -60,7 +60,7 @@ public boolean isAvailable() { public Result invoke(Invocation invocation) throws RpcException { AppResponse result = new AppResponse(); - if (hasException == false) { + if (!hasException) { result.setValue("alibaba"); } else { result.setException(new RuntimeException("mocked exception")); From c3132b8343de5ba8ce289822a633c32de79c2799 Mon Sep 17 00:00:00 2001 From: huaifeng <791825162@qq.com> Date: Wed, 31 Jul 2019 11:07:55 +0800 Subject: [PATCH 20/30] Fixed Service annotation method parameters are not in effect (#4598) --- .../ServiceAnnotationBeanPostProcessor.java | 14 +++ .../config/spring/util/AnnotationUtils.java | 12 --- ...erenceAnnotationBeanPostProcessorTest.java | 89 +++++++++++-------- ...erviceAnnotationBeanPostProcessorTest.java | 14 +++ .../annotation/provider/DemoServiceImpl.java | 4 +- .../consumer/comp/DemoServiceComponent.java | 3 +- .../spring/dubbo-consumer.properties | 2 +- .../dubbo/demo/provider/Application.java | 2 +- .../dubbo/demo/provider/DemoServiceImpl.java | 8 +- 9 files changed, 92 insertions(+), 56 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java index 06deb57fdd9..c3e3dca907e 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java @@ -16,9 +16,12 @@ */ package org.apache.dubbo.config.spring.beans.factory.annotation; +import java.util.Collections; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.config.MethodConfig; +import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.config.spring.ServiceBean; import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner; @@ -387,6 +390,11 @@ private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnno builder.addPropertyValue("interface", interfaceClass.getName()); // Convert parameters into map builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters"))); + // Add methods parameters + List methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods")); + if (!methodConfigs.isEmpty()) { + builder.addPropertyValue("methods", methodConfigs); + } /** * Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference @@ -447,6 +455,12 @@ private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnno } + private List convertMethodConfigs(Object methodsAnnotation) { + if (methodsAnnotation == null){ + return Collections.EMPTY_LIST; + } + return MethodConfig.constructMethodConfig((Method[])methodsAnnotation); + } private ManagedList toRuntimeBeanReferences(String... beanNames) { diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java index 19ced2b3065..ea13daf10e8 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java @@ -343,21 +343,9 @@ public static Map getAttributes(Annotation annotation, PropertyR if (ignoreDefaultValue && nullSafeEquals(attributeValue, getDefaultValue(annotation, attributeName))) { continue; } - - /** - * @since 2.7.1 - * ignore annotation member - */ - if (attributeValue.getClass().isAnnotation()) { - continue; - } - if (attributeValue.getClass().isArray() && attributeValue.getClass().getComponentType().isAnnotation()) { - continue; - } actualAttributes.put(attributeName, attributeValue); } - return resolvePlaceholders(actualAttributes, propertyResolver, ignoreAttributeNames); } diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java index 56fd2970b29..d1a695f8d3c 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.config.spring.beans.factory.annotation; +import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.spring.ReferenceBean; import org.apache.dubbo.config.spring.api.DemoService; @@ -47,14 +48,14 @@ */ @RunWith(SpringRunner.class) @ContextConfiguration( - classes = { - ServiceAnnotationTestConfiguration.class, - ReferenceAnnotationBeanPostProcessorTest.class - }) + classes = { + ServiceAnnotationTestConfiguration.class, + ReferenceAnnotationBeanPostProcessorTest.class + }) @TestPropertySource(properties = { - "packagesToScan = org.apache.dubbo.config.spring.context.annotation.provider", - "consumer.version = ${demo.service.version}", - "consumer.url = dubbo://127.0.0.1:12345?version=2.5.7", + "packagesToScan = org.apache.dubbo.config.spring.context.annotation.provider", + "consumer.version = ${demo.service.version}", + "consumer.url = dubbo://127.0.0.1:12345?version=2.5.7", }) public class ReferenceAnnotationBeanPostProcessorTest { @@ -79,7 +80,7 @@ public ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor @Qualifier("helloServiceImpl") private HelloService helloServiceImpl; - @Reference(id = "helloService") + @Reference(id = "helloService", methods = @Method(name = "sayName", timeout = 100)) private HelloService helloService; @Test @@ -131,7 +132,7 @@ public void test() throws Exception { public void testGetReferenceBeans() { ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, - ReferenceAnnotationBeanPostProcessor.class); + ReferenceAnnotationBeanPostProcessor.class); Collection> referenceBeans = beanPostProcessor.getReferenceBeans(); @@ -139,8 +140,6 @@ public void testGetReferenceBeans() { ReferenceBean referenceBean = referenceBeans.iterator().next(); - TestBean testBean = context.getBean(TestBean.class); - Assert.assertNotNull(referenceBean.get()); } @@ -149,11 +148,10 @@ public void testGetReferenceBeans() { public void testGetInjectedFieldReferenceBeanMap() { ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, - ReferenceAnnotationBeanPostProcessor.class); - + ReferenceAnnotationBeanPostProcessor.class); Map> referenceBeanMap = - beanPostProcessor.getInjectedFieldReferenceBeanMap(); + beanPostProcessor.getInjectedFieldReferenceBeanMap(); Assert.assertEquals(2, referenceBeanMap.size()); @@ -162,7 +160,7 @@ public void testGetInjectedFieldReferenceBeanMap() { InjectionMetadata.InjectedElement injectedElement = entry.getKey(); Assert.assertEquals("org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedFieldElement", - injectedElement.getClass().getName()); + injectedElement.getClass().getName()); } @@ -172,11 +170,10 @@ public void testGetInjectedFieldReferenceBeanMap() { public void testGetInjectedMethodReferenceBeanMap() { ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, - ReferenceAnnotationBeanPostProcessor.class); - + ReferenceAnnotationBeanPostProcessor.class); Map> referenceBeanMap = - beanPostProcessor.getInjectedMethodReferenceBeanMap(); + beanPostProcessor.getInjectedMethodReferenceBeanMap(); Assert.assertEquals(2, referenceBeanMap.size()); @@ -185,33 +182,32 @@ public void testGetInjectedMethodReferenceBeanMap() { InjectionMetadata.InjectedElement injectedElement = entry.getKey(); Assert.assertEquals("org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedMethodElement", - injectedElement.getClass().getName()); + injectedElement.getClass().getName()); } } -// @Test -// public void testModuleInfo() { -// -// ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, -// ReferenceAnnotationBeanPostProcessor.class); -// -// -// Map> referenceBeanMap = -// beanPostProcessor.getInjectedMethodReferenceBeanMap(); -// -// for (Map.Entry> entry : referenceBeanMap.entrySet()) { -// ReferenceBean referenceBean = entry.getValue(); -// -// assertThat(referenceBean.getModule().getName(), is("defaultModule")); -// assertThat(referenceBean.getMonitor(), not(nullValue())); -// } -// } + // @Test + // public void testModuleInfo() { + // + // ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, + // ReferenceAnnotationBeanPostProcessor.class); + // + // + // Map> referenceBeanMap = + // beanPostProcessor.getInjectedMethodReferenceBeanMap(); + // + // for (Map.Entry> entry : referenceBeanMap.entrySet()) { + // ReferenceBean referenceBean = entry.getValue(); + // + // assertThat(referenceBean.getModule().getName(), is("defaultModule")); + // assertThat(referenceBean.getMonitor(), not(nullValue())); + // } + // } private static class AncestorBean { - private DemoService demoServiceFromAncestor; @Autowired @@ -232,7 +228,6 @@ public ApplicationContext getApplicationContext() { } - private static class ParentBean extends AncestorBean { @Reference(version = "${consumer.version}", url = "${consumer.url}") @@ -242,7 +237,6 @@ public DemoService getDemoServiceFromParent() { return demoServiceFromParent; } - } static class TestBean extends ParentBean { @@ -265,4 +259,21 @@ public void setDemoService(DemoService demoService) { } } + @Test + public void testReferenceBeansMethodAnnotation() { + + ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, + ReferenceAnnotationBeanPostProcessor.class); + + Collection> referenceBeans = beanPostProcessor.getReferenceBeans(); + + Assert.assertEquals(2, referenceBeans.size()); + + ReferenceBean referenceBean = referenceBeans.iterator().next(); + + if ("helloService".equals(referenceBean.getId())) { + Assert.assertNotNull(referenceBean.getMethods()); + } + } + } \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java index 22325d96ebf..17d3023dc61 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java @@ -17,6 +17,7 @@ package org.apache.dubbo.config.spring.beans.factory.annotation; import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.api.DemoService; import org.apache.dubbo.config.spring.api.HelloService; import org.junit.Assert; @@ -79,4 +80,17 @@ public void test() { } + @Test + public void testMethodAnnotation() { + + Map serviceBeansMap = beanFactory.getBeansOfType(ServiceBean.class); + + Assert.assertEquals(2, serviceBeansMap.size()); + + ServiceBean demoServiceBean = serviceBeansMap.get("ServiceBean:org.apache.dubbo.config.spring.api.DemoService:2.5.7"); + + Assert.assertNotNull(demoServiceBean.getMethods()); + + } + } diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/DemoServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/DemoServiceImpl.java index 3aa1e86f4e6..8ee2a8a09f6 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/DemoServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/DemoServiceImpl.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.config.spring.context.annotation.provider; +import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.spring.api.Box; import org.apache.dubbo.config.spring.api.DemoService; @@ -32,7 +33,8 @@ version = "2.5.7", application = "${demo.service.application}", protocol = "${demo.service.protocol}", - registry = "${demo.service.registry}" + registry = "${demo.service.registry}", + methods = @Method(timeout = 100,name = "sayName") ) @Service @Transactional diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java index 4305ed6c05f..757994db0da 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java @@ -19,6 +19,7 @@ package org.apache.dubbo.demo.consumer.comp; +import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.demo.DemoService; @@ -26,7 +27,7 @@ @Component("demoServiceComponent") public class DemoServiceComponent implements DemoService { - @Reference + @Reference(timeout = 100,methods = @Method(timeout = 500,name = "sayHello")) private DemoService demoService; @Override diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/spring/dubbo-consumer.properties b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/spring/dubbo-consumer.properties index 5ec658ba925..bda13add464 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/spring/dubbo-consumer.properties +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/spring/dubbo-consumer.properties @@ -18,4 +18,4 @@ # dubbo.application.name=dubbo-demo-annotation-consumer -dubbo.registry.address=multicast://224.5.6.7:1234 +dubbo.registry.address=zookeeper://127.0.0.1:2181 diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java index b848865dee3..9190d08c668 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java @@ -44,7 +44,7 @@ static class ProviderConfiguration { @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); - registryConfig.setAddress("multicast://224.5.6.7:1234"); + registryConfig.setAddress("zookeeper://127.0.0.1:2181"); return registryConfig; } } diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java index cb06537ae01..96971db10b5 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java @@ -18,6 +18,7 @@ */ package org.apache.dubbo.demo.provider; +import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.demo.DemoService; import org.apache.dubbo.rpc.RpcContext; @@ -25,12 +26,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Service +@Service(timeout = 100,methods = @Method(timeout = 1000,name = "sayHello")) public class DemoServiceImpl implements DemoService { private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); @Override public String sayHello(String name) { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress(); } From f490df87de45b57be8c224581a8a1a7dd9a20946 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Wed, 31 Jul 2019 14:25:27 +0800 Subject: [PATCH 21/30] keep demo simple, and switch to use zookeeper as registry center (#4705) * keep demo simple, and switch to use zookeeper as registry center * remove comment --- .../dubbo/demo/consumer/comp/DemoServiceComponent.java | 3 +-- .../java/org/apache/dubbo/demo/provider/Application.java | 4 ---- .../org/apache/dubbo/demo/provider/DemoServiceImpl.java | 8 +------- .../java/org/apache/dubbo/demo/consumer/Application.java | 6 +----- .../java/org/apache/dubbo/demo/provider/Application.java | 6 +----- .../java/org/apache/dubbo/demo/consumer/Application.java | 4 ---- .../src/main/resources/spring/dubbo-consumer.xml | 4 +--- .../java/org/apache/dubbo/demo/provider/Application.java | 4 ---- .../src/main/resources/spring/dubbo-provider.xml | 6 +----- 9 files changed, 6 insertions(+), 39 deletions(-) diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java index 757994db0da..4305ed6c05f 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java @@ -19,7 +19,6 @@ package org.apache.dubbo.demo.consumer.comp; -import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.demo.DemoService; @@ -27,7 +26,7 @@ @Component("demoServiceComponent") public class DemoServiceComponent implements DemoService { - @Reference(timeout = 100,methods = @Method(timeout = 500,name = "sayHello")) + @Reference private DemoService demoService; @Override diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java index 9190d08c668..737b10ea8f1 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java @@ -27,10 +27,6 @@ import org.springframework.context.annotation.PropertySource; public class Application { - /** - * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before - * launch the application - */ public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class); context.start(); diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java index 96971db10b5..cb06537ae01 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java @@ -18,7 +18,6 @@ */ package org.apache.dubbo.demo.provider; -import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.demo.DemoService; import org.apache.dubbo.rpc.RpcContext; @@ -26,17 +25,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Service(timeout = 100,methods = @Method(timeout = 1000,name = "sayHello")) +@Service public class DemoServiceImpl implements DemoService { private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); @Override public String sayHello(String name) { - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress(); } diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java index b062d6e65f6..9591a69b7ab 100644 --- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java +++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java @@ -24,14 +24,10 @@ import org.apache.dubbo.demo.DemoService; public class Application { - /** - * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before - * launch the application - */ public static void main(String[] args) { ReferenceConfig reference = new ReferenceConfig<>(); reference.setApplication(new ApplicationConfig("dubbo-demo-api-consumer")); - reference.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234")); + reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181")); reference.setInterface(DemoService.class); DemoService service = reference.get(); String message = service.sayHello("dubbo"); diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java index 857e03f1169..5990d750638 100644 --- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java +++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java @@ -24,14 +24,10 @@ import org.apache.dubbo.demo.DemoService; public class Application { - /** - * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before - * launch the application - */ public static void main(String[] args) throws Exception { ServiceConfig service = new ServiceConfig<>(); service.setApplication(new ApplicationConfig("dubbo-demo-api-provider")); - service.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234")); + service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181")); service.setInterface(DemoService.class); service.setRef(new DemoServiceImpl()); service.export(); diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java index 90ed7c0b6a6..f448a184a57 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java @@ -21,10 +21,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { - /** - * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before - * launch the application - */ public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml"); context.start(); diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml index 6b5efc32f00..742195fcf24 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml @@ -23,10 +23,8 @@ - + - diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java index 25a9dd4be0f..d1ab5be7489 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/Application.java @@ -19,10 +19,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { - /** - * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before - * launch the application - */ public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider.xml"); context.start(); diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/spring/dubbo-provider.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/spring/dubbo-provider.xml index 95e730682d5..56a07cd2b00 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/spring/dubbo-provider.xml +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/spring/dubbo-provider.xml @@ -21,18 +21,14 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> - - + - - - From c8dbd7d83527e91588d541316ba4a75791f40dec Mon Sep 17 00:00:00 2001 From: "Mr.Z" <15869103363@163.com> Date: Wed, 31 Jul 2019 20:29:32 +0800 Subject: [PATCH 22/30] @Reference auto-wires the instance of generic interface #4594 (#4677) --- .../beans/factory/annotation/ReferenceBeanBuilder.java | 10 +++++++++- .../dubbo/config/spring/util/AnnotationUtils.java | 9 ++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java index 2054473587d..ae620f4a0ea 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java @@ -22,7 +22,6 @@ import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.spring.ReferenceBean; - import org.springframework.beans.propertyeditors.StringTrimmerEditor; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationAttributes; @@ -57,6 +56,15 @@ private ReferenceBeanBuilder(AnnotationAttributes attributes, ApplicationContext } private void configureInterface(AnnotationAttributes attributes, ReferenceBean referenceBean) { + Boolean generic = getAttribute(attributes, "generic"); + if (generic != null && generic) { + // it's a generic reference + String interfaceClassName = getAttribute(attributes, "interfaceName"); + Assert.hasText(interfaceClassName, + "@Reference interfaceName() must be present when reference a generic service!"); + referenceBean.setInterface(interfaceClassName); + return; + } Class serviceInterfaceClass = resolveServiceInterfaceClass(attributes, interfaceClass); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java index ea13daf10e8..154edb634f3 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java @@ -18,7 +18,6 @@ import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.annotation.Service; - import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.env.PropertyResolver; @@ -93,6 +92,14 @@ public static String resolveInterfaceName(Service service, Class defaultInter * @throws IllegalStateException if interface name was not found */ public static String resolveInterfaceName(AnnotationAttributes attributes, Class defaultInterfaceClass) { + Boolean generic = getAttribute(attributes, "generic"); + if (generic != null && generic) { + // it's a generic reference + String interfaceClassName = getAttribute(attributes, "interfaceName"); + Assert.hasText(interfaceClassName, + "@Reference interfaceName() must be present when reference a generic service!"); + return interfaceClassName; + } return resolveServiceInterfaceClass(attributes, defaultInterfaceClass).getName(); } From 65a014075c03c70bc4da5cfbce4db925dcf80021 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Thu, 1 Aug 2019 11:08:57 +0800 Subject: [PATCH 23/30] try to shorten maven output to make travis build pass (#4710) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a0bacc78df7..dedcc15d9a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ cache: install: true script: - - travis_wait 30 ./mvnw clean install -DskipTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true + - travis_wait 30 ./mvnw --quiet clean install -DskipTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true after_success: - bash <(curl -s https://codecov.io/bash) From 5b38331036746f8c6740872eda05bff3e2c701ea Mon Sep 17 00:00:00 2001 From: Taosheng Wei Date: Thu, 1 Aug 2019 15:15:44 +0800 Subject: [PATCH 24/30] use CountDownLatch to check zk registry if establish connection (#4589) --- .../apache/dubbo/registry/zookeeper/ZookeeperRegistry.java | 2 -- .../dubbo/registry/zookeeper/ZookeeperRegistryTest.java | 3 ++- .../remoting/zookeeper/curator/CuratorZookeeperClient.java | 5 +++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java index 4ddf1518e6d..fbfc750bb90 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java @@ -60,8 +60,6 @@ public class ZookeeperRegistry extends FailbackRegistry { private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class); - private final static int DEFAULT_ZOOKEEPER_PORT = 2181; - private final static String DEFAULT_ROOT = "dubbo"; private final String root; diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java index b645408bd5b..c0a080c98d2 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java @@ -55,8 +55,9 @@ public class ZookeeperRegistryTest { public void setUp() throws Exception { int zkServerPort = NetUtils.getAvailablePort(); this.zkServer = new TestingServer(zkServerPort, true); - this.registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); + this.zkServer.start(); + this.registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); zookeeperRegistryFactory = new ZookeeperRegistryFactory(); zookeeperRegistryFactory.setZookeeperTransporter(new CuratorZookeeperTransporter()); this.zookeeperRegistry = (ZookeeperRegistry) zookeeperRegistryFactory.createRegistry(registryUrl); diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java index c142d009414..75aa256b558 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java @@ -46,6 +46,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; @@ -84,6 +85,10 @@ public void stateChanged(CuratorFramework client, ConnectionState state) { } }); client.start(); + boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS); + if (!connected) { + throw new IllegalStateException("zookeeper not connected"); + } } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } From a646874a071f626e3ace534331d9bfb2eb2c4f49 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 1 Aug 2019 16:48:20 +0800 Subject: [PATCH 25/30] Minor change --- .../dubbo/bootstrap/DubboBootstrap.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java index 6a2237fa23b..9d066c6dd84 100644 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java +++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java @@ -112,19 +112,14 @@ public class DubboBootstrap { private final ConfigManager configManager = getInstance(); - /** - * Is provider or not - */ - private boolean isProvider; + private volatile boolean initialized = false; - private boolean initialized = false; - - private boolean started = false; + private volatile boolean started = false; /** * Only Provider Register */ - private boolean onlyRegisterProvider = false; + private volatile boolean onlyRegisterProvider = false; private ServiceInstance serviceInstance; @@ -153,8 +148,8 @@ public DubboBootstrap metadataReport(List metadataReportCo return this; } - // {@link ApplicationConfig} correlative methods + // {@link ApplicationConfig} correlative methods /** * Set the name of application * @@ -191,8 +186,8 @@ public DubboBootstrap application(ApplicationConfig applicationConfig) { return this; } - // {@link RegistryConfig} correlative methods + // {@link RegistryConfig} correlative methods /** * Add an instance of {@link RegistryConfig} with {@link #DEFAULT_REGISTRY_ID default ID} * @@ -238,8 +233,8 @@ public DubboBootstrap registries(Iterable registryConfigs) { return this; } - // {@link ProtocolConfig} correlative methods + // {@link ProtocolConfig} correlative methods public DubboBootstrap protocol(Consumer consumerBuilder) { return protocol(DEFAULT_PROTOCOL_ID, consumerBuilder); } @@ -259,8 +254,8 @@ public DubboBootstrap protocols(List protocolConfigs) { return this; } - // {@link ServiceConfig} correlative methods + // {@link ServiceConfig} correlative methods public DubboBootstrap service(Consumer> consumerBuilder) { return service(DEFAULT_SERVICE_ID, consumerBuilder); } @@ -276,8 +271,8 @@ public DubboBootstrap service(ServiceConfig serviceConfig) { return this; } - // {@link Reference} correlative methods + // {@link Reference} correlative methods public DubboBootstrap reference(Consumer> consumerBuilder) { return reference(DEFAULT_REFERENCE_ID, consumerBuilder); } @@ -293,8 +288,8 @@ public DubboBootstrap reference(ReferenceConfig referenceConfig) { return this; } - // {@link ProviderConfig} correlative methods + // {@link ProviderConfig} correlative methods public DubboBootstrap provider(Consumer builderConsumer) { return provider(DEFAULT_PROVIDER_ID, builderConsumer); } @@ -314,8 +309,8 @@ public DubboBootstrap providers(List providerConfigs) { return this; } - // {@link ConsumerConfig} correlative methods + // {@link ConsumerConfig} correlative methods public DubboBootstrap consumer(Consumer builderConsumer) { return consumer(DEFAULT_CONSUMER_ID, builderConsumer); } @@ -336,10 +331,10 @@ public DubboBootstrap consumers(List consumerConfigs) { } // {@link ConfigCenterConfig} correlative methods + public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) { return configCenter(asList(configCenterConfig)); } - public DubboBootstrap configCenter(List configCenterConfigs) { configManager.addConfigCenters(configCenterConfigs); return this; @@ -456,7 +451,6 @@ public DubboBootstrap start() { /** * export {@link MetadataService} */ - // TODO, only export to default registry? List exportedURLs = exportMetadataService( configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")), configManager.getRegistries(), @@ -534,10 +528,10 @@ public boolean isStarted() { /* serve for builder apis, begin */ + private ApplicationBuilder createApplicationBuilder(String name) { return new ApplicationBuilder().name(name); } - private RegistryBuilder createRegistryBuilder(String id) { return new RegistryBuilder().id(id); } @@ -562,8 +556,8 @@ private ConsumerBuilder createConsumerBuilder(String id) { return new ConsumerBuilder().id(id); } - /* serve for builder apis, end */ + /* serve for builder apis, end */ private void startMetadataReport() { ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified.")); @@ -656,6 +650,10 @@ public void exportServiceConfig(ServiceConfig serviceConfig) { serviceConfig.export(); } + public boolean isOnlyRegisterProvider() { + return onlyRegisterProvider; + } + private void registerServiceInstance(List exportedURLs) { exportedURLs From 0644fe1b4dcd9c7808e4106822f5f05801c77ff2 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 5 Aug 2019 14:40:09 +0800 Subject: [PATCH 26/30] Rename the extension name of WritableMetadataService --- .../java/org/apache/dubbo/metadata/WritableMetadataService.java | 2 +- .../internal/org.apache.dubbo.metadata.WritableMetadataService | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java index f1a1ea40ae9..662cb6930a2 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java @@ -30,7 +30,7 @@ * * @since 2.7.4 */ -@SPI("local") +@SPI("in-memory") public interface WritableMetadataService extends MetadataService { /** diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService index 26bc942e704..e924ed8aff7 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService +++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService @@ -1,2 +1,2 @@ -local=org.apache.dubbo.metadata.store.InMemoryWritableMetadataService +in-memory=org.apache.dubbo.metadata.store.InMemoryWritableMetadataService remote=org.apache.dubbo.metadata.store.RemoteWritableMetadataService \ No newline at end of file From 9f405d731688442e6532ae3985440b46b05637de Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 7 Aug 2019 11:07:46 +0800 Subject: [PATCH 27/30] Polish apache/dubbo#4759 : [Refactor] Change the signature of methods of MetadataService #4759 --- .../dubbo/metadata/MetadataService.java | 82 ++++++++++---- .../InMemoryWritableMetadataService.java | 100 +++++++----------- .../store/RemoteWritableMetadataService.java | 20 ++-- .../InMemoryWritableMetadataServiceTest.java | 32 +++--- 4 files changed, 136 insertions(+), 98 deletions(-) diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java index 9e817785061..7e5102f887b 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java @@ -19,8 +19,14 @@ import org.apache.dubbo.common.URL; import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import static java.util.Collections.unmodifiableSortedSet; import static java.util.stream.StreamSupport.stream; /** @@ -72,78 +78,88 @@ default String version() { /** * the list of String that presents all Dubbo subscribed {@link URL urls} * - * @return non-null read-only {@link List} + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting the {@link URL URLs} + * @see #toSortedStrings(Stream) + * @see URL#toFullString() */ - List getSubscribedURLs(); + SortedSet getSubscribedURLs(); /** - * Get the list of String that presents all Dubbo exported {@link URL urls} + * Get the {@link SortedSet sorted set} of String that presents all Dubbo exported {@link URL urls} * - * @return non-null read-only {@link List} + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting the {@link URL URLs} + * @see #toSortedStrings(Stream) + * @see URL#toFullString() */ - default List getExportedURLs() { + default SortedSet getExportedURLs() { return getExportedURLs(ALL_SERVICE_INTERFACES); } /** - * Get the list of String that presents the specified Dubbo exported {@link URL urls} by the serviceInterface + * Get the {@link SortedSet sorted set} of String that presents the specified Dubbo exported {@link URL urls} by the serviceInterface * * @param serviceInterface The class name of Dubbo service interface - * @return non-null read-only {@link List} - * @see URL + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting the {@link URL URLs} + * @see #toSortedStrings(Stream) + * @see URL#toFullString() */ - default List getExportedURLs(String serviceInterface) { + default SortedSet getExportedURLs(String serviceInterface) { return getExportedURLs(serviceInterface, null); } /** - * Get the list of String that presents the specified Dubbo exported {@link URL urls} by the + * Get the {@link SortedSet sorted set} of String that presents the specified Dubbo exported {@link URL urls} by the * serviceInterface and group * * @param serviceInterface The class name of Dubbo service interface * @param group the Dubbo Service Group (optional) - * @return non-null read-only {@link List} - * @see URL + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting the {@link URL URLs} + * @see #toSortedStrings(Stream) + * @see URL#toFullString() */ - default List getExportedURLs(String serviceInterface, String group) { + default SortedSet getExportedURLs(String serviceInterface, String group) { return getExportedURLs(serviceInterface, group, null); } /** - * Get the list of String that presents the specified Dubbo exported {@link URL urls} by the + * Get the {@link SortedSet sorted set} of String that presents the specified Dubbo exported {@link URL urls} by the * serviceInterface, group and version * * @param serviceInterface The class name of Dubbo service interface * @param group the Dubbo Service Group (optional) * @param version the Dubbo Service Version (optional) - * @return non-null read-only {@link List} - * @see URL + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting the {@link URL URLs} + * @see #toSortedStrings(Stream) + * @see URL#toFullString() */ - default List getExportedURLs(String serviceInterface, String group, String version) { + default SortedSet getExportedURLs(String serviceInterface, String group, String version) { return getExportedURLs(serviceInterface, group, version, null); } /** - * Get the list of String that presents the specified Dubbo exported {@link URL urls} by the + * Get the sorted set of String that presents the specified Dubbo exported {@link URL urls} by the * serviceInterface, group, version and protocol * * @param serviceInterface The class name of Dubbo service interface * @param group the Dubbo Service Group (optional) * @param version the Dubbo Service Version (optional) * @param protocol the Dubbo Service Protocol (optional) - * @return non-null read-only {@link List} - * @see URL + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting the {@link URL URLs} + * @see #toSortedStrings(Stream) + * @see URL#toFullString() */ - List getExportedURLs(String serviceInterface, String group, String version, String protocol); + SortedSet getExportedURLs(String serviceInterface, String group, String version, String protocol); /** * Interface definition. + * * @return */ String getServiceDefinition(String interfaceName, String version, String group); /** * Interface definition. + * * @return */ String getServiceDefinition(String serviceKey); @@ -159,4 +175,28 @@ static List toURLs(Iterable urls) { .map(URL::valueOf) .collect(Collectors.toList()); } + + /** + * Convert the specified {@link Iterable} of {@link URL URLs} to be the {@link URL#toFullString() strings} presenting + * the {@link URL URLs} + * + * @param iterable {@link Iterable} of {@link URL} + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting + * @see URL#toFullString() + */ + static SortedSet toSortedStrings(Iterable iterable) { + return toSortedStrings(StreamSupport.stream(iterable.spliterator(), false)); + } + + /** + * Convert the specified {@link Stream} of {@link URL URLs} to be the {@link URL#toFullString() strings} presenting + * the {@link URL URLs} + * + * @param stream {@link Stream} of {@link URL} + * @return the non-null read-only {@link SortedSet sorted set} of {@link URL#toFullString() strings} presenting + * @see URL#toFullString() + */ + static SortedSet toSortedStrings(Stream stream) { + return unmodifiableSortedSet(stream.map(URL::toFullString).collect(TreeSet::new, Set::add, Set::addAll)); + } } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java index 6b3d815f2d7..863bad49675 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java @@ -28,18 +28,18 @@ import com.google.gson.Gson; import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.Comparator; import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; -import static java.util.Collections.emptyList; -import static java.util.Collections.unmodifiableList; +import static java.util.Collections.emptySortedSet; +import static java.util.Collections.unmodifiableSortedSet; import static org.apache.dubbo.common.URL.buildKey; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; @@ -55,11 +55,6 @@ */ public class InMemoryWritableMetadataService implements WritableMetadataService { - /** - * The class name of {@link MetadataService} - */ - static final String METADATA_SERVICE_CLASS_NAME = MetadataService.class.getName(); - private final Logger logger = LoggerFactory.getLogger(getClass()); private final Lock lock = new ReentrantLock(); @@ -68,9 +63,9 @@ public class InMemoryWritableMetadataService implements WritableMetadataService /** * All exported {@link URL urls} {@link Map} whose key is the return value of {@link URL#getServiceKey()} method - * and value is the {@link List} of the {@link URL URLs} + * and value is the {@link SortedSet sorted set} of the {@link URL URLs} */ - private ConcurrentMap> exportedServiceURLs = new ConcurrentHashMap<>(); + private ConcurrentNavigableMap> exportedServiceURLs = new ConcurrentSkipListMap<>(); // ==================================================================================== // @@ -78,42 +73,36 @@ public class InMemoryWritableMetadataService implements WritableMetadataService /** * The subscribed {@link URL urls} {@link Map} of {@link MetadataService}, - * whose key is the return value of {@link URL#getServiceKey()} method and value is the {@link List} of - * the {@link URL URLs} + * whose key is the return value of {@link URL#getServiceKey()} method and value is + * the {@link SortedSet sorted set} of the {@link URL URLs} */ - private final ConcurrentMap> subscribedServiceURLs = new ConcurrentHashMap<>(); + private final ConcurrentNavigableMap> subscribedServiceURLs = new ConcurrentSkipListMap<>(); - private final ConcurrentHashMap serviceDefinitions = new ConcurrentHashMap<>(); + private final ConcurrentNavigableMap serviceDefinitions = new ConcurrentSkipListMap<>(); // ==================================================================================== // @Override - public List getSubscribedURLs() { + public SortedSet getSubscribedURLs() { return getAllUnmodifiableServiceURLs(subscribedServiceURLs); } @Override - public List getExportedURLs(String serviceInterface, String group, String version, String protocol) { + public SortedSet getExportedURLs(String serviceInterface, String group, String version, String protocol) { if (ALL_SERVICE_INTERFACES.equals(serviceInterface)) { return getAllUnmodifiableServiceURLs(exportedServiceURLs); } String serviceKey = buildKey(serviceInterface, group, version); - return unmodifiableList(getServiceURLs(exportedServiceURLs, serviceKey, protocol)); + return unmodifiableSortedSet(getServiceURLs(exportedServiceURLs, serviceKey, protocol)); } @Override public boolean exportURL(URL url) { -// if (isMetadataServiceURL(url)) { // ignore MetadataService in the export phase -// return true; -// } return addURL(exportedServiceURLs, url); } @Override public boolean unexportURL(URL url) { -// if (isMetadataServiceURL(url)) { // ignore MetadataService in the export phase -// return true; -// } return removeURL(exportedServiceURLs, url); } @@ -156,22 +145,20 @@ public String getServiceDefinition(String serviceKey) { return serviceDefinitions.get(serviceKey); } - private boolean addURL(Map> serviceURLs, URL url) { + private boolean addURL(Map> serviceURLs, URL url) { return executeMutually(() -> { - List urls = serviceURLs.computeIfAbsent(url.getServiceKey(), s -> new LinkedList()); - if (!urls.contains(url)) { - return urls.add(url); - } - return false; + SortedSet urls = serviceURLs.computeIfAbsent(url.getServiceKey(), this::newSortedURLs); + return urls.add(url); }); } - private boolean removeURL(Map> serviceURLs, URL url) { + private SortedSet newSortedURLs(String serviceKey) { + return new TreeSet<>(URLComparator.INSTANCE); + } + + private boolean removeURL(Map> serviceURLs, URL url) { return executeMutually(() -> { - List urls = serviceURLs.get(url.getServiceKey()); - if (isEmpty(urls)) { - return false; - } + SortedSet urls = serviceURLs.getOrDefault(url.getServiceKey(), emptySortedSet()); return urls.remove(url); }); } @@ -193,19 +180,15 @@ private boolean executeMutually(Callable callable) { return success; } - private static List getServiceURLs(Map> exportedServiceURLs, String serviceKey, - String protocol) { - List serviceURLs = exportedServiceURLs.get(serviceKey); + private static SortedSet getServiceURLs(Map> exportedServiceURLs, String serviceKey, + String protocol) { + SortedSet serviceURLs = exportedServiceURLs.get(serviceKey); if (isEmpty(serviceURLs)) { - return emptyList(); + return emptySortedSet(); } - return serviceURLs - .stream() - .filter(url -> isAcceptableProtocol(protocol, url)) - .map(URL::toFullString) - .collect(Collectors.toList()); + return MetadataService.toSortedStrings(serviceURLs.stream().filter(url -> isAcceptableProtocol(protocol, url))); } private static boolean isAcceptableProtocol(String protocol, URL url) { @@ -214,18 +197,17 @@ private static boolean isAcceptableProtocol(String protocol, URL url) { || protocol.equals(url.getProtocol()); } -// private static boolean isMetadataServiceURL(URL url) { -// String serviceInterface = url.getServiceInterface(); -// return METADATA_SERVICE_CLASS_NAME.equals(serviceInterface); -// } + private static SortedSet getAllUnmodifiableServiceURLs(Map> serviceURLs) { + return MetadataService.toSortedStrings(serviceURLs.values().stream().flatMap(Collection::stream)); + } + + private static class URLComparator implements Comparator { - private static List getAllUnmodifiableServiceURLs(Map> serviceURLs) { - return unmodifiableList( - serviceURLs - .values() - .stream() - .flatMap(Collection::stream) - .map(URL::toFullString) - .collect(Collectors.toList())); + public static final URLComparator INSTANCE = new URLComparator(); + + @Override + public int compare(URL o1, URL o2) { + return o1.toFullString().compareTo(o2.toFullString()); + } } } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java index c52f5c8aa12..f31e9369404 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java @@ -33,7 +33,10 @@ import org.apache.dubbo.remoting.Constants; import org.apache.dubbo.rpc.RpcException; -import java.util.List; +import java.util.Collection; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.function.Consumer; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; @@ -57,7 +60,8 @@ public class RemoteWritableMetadataService implements WritableMetadataService { private MetadataReportFactory metadataReportFactory = ExtensionLoader.getExtensionLoader(MetadataReportFactory.class).getAdaptiveExtension(); private MetadataReport metadataReport; - public RemoteWritableMetadataService() {} + public RemoteWritableMetadataService() { + } public void initMetadataReport(URL metadataReportURL) { if (METADATA_REPORT_KEY.equals(metadataReportURL.getProtocol())) { @@ -148,14 +152,18 @@ public boolean unsubscribeURL(URL url) { } @Override - public List getSubscribedURLs() { - return metadataReport.getSubscribedURLs(); + public SortedSet getSubscribedURLs() { + return toSortedStrings(metadataReport.getSubscribedURLs()); } // TODO, protocol should be used @Override - public List getExportedURLs(String serviceInterface, String group, String version, String protocol) { - return metadataReport.getExportedURLs(new MetadataIdentifier(serviceInterface, group, version, null, null)); + public SortedSet getExportedURLs(String serviceInterface, String group, String version, String protocol) { + return toSortedStrings(metadataReport.getExportedURLs(new MetadataIdentifier(serviceInterface, group, version, null, null))); + } + + private static SortedSet toSortedStrings(Collection values) { + return Collections.unmodifiableSortedSet(new TreeSet<>(values)); } @Override diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java index 64771b0f572..c5b319129d9 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java @@ -23,9 +23,12 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableSortedSet; import static org.apache.dubbo.common.URL.valueOf; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; @@ -71,9 +74,9 @@ public void testVersion() { public void testGetExportedURLs() { assertTrue(metadataService.exportURL(BASE_URL)); - List exportedURLs = metadataService.getExportedURLs(TEST_SERVICE); + Set exportedURLs = metadataService.getExportedURLs(TEST_SERVICE); assertEquals(1, exportedURLs.size()); - assertEquals(asList(BASE_URL.toFullString()), exportedURLs); + assertEquals(asSortedSet(BASE_URL.toFullString()), exportedURLs); assertTrue(metadataService.unexportURL(BASE_URL)); assertTrue(metadataService.exportURL(BASE_URL)); @@ -83,21 +86,21 @@ public void testGetExportedURLs() { assertTrue(metadataService.exportURL(BASE_URL_GROUP_AND_VERSION)); exportedURLs = metadataService.getExportedURLs(TEST_SERVICE); - assertEquals(asList(BASE_URL.toFullString()), exportedURLs); - assertEquals(asList( + assertEquals(asSortedSet(BASE_URL.toFullString()), exportedURLs); + assertEquals(asSortedSet( BASE_URL.toFullString(), BASE_URL_GROUP.toFullString(), BASE_URL_GROUP_AND_VERSION.toFullString()), metadataService.getExportedURLs()); assertTrue(metadataService.exportURL(REST_BASE_URL)); exportedURLs = metadataService.getExportedURLs(TEST_SERVICE); - assertEquals(asList(BASE_URL.toFullString(), REST_BASE_URL.toFullString()), exportedURLs); + assertEquals(asSortedSet(BASE_URL.toFullString(), REST_BASE_URL.toFullString()), exportedURLs); metadataService.exportURL(BASE_URL_GROUP_AND_VERSION_AND_PROTOCOL); exportedURLs = metadataService.getExportedURLs(TEST_SERVICE, "test", "1.0.0", "rest"); - assertEquals(asList(BASE_URL_GROUP_AND_VERSION_AND_PROTOCOL.toFullString()), exportedURLs); + assertEquals(asSortedSet(BASE_URL_GROUP_AND_VERSION_AND_PROTOCOL.toFullString()), exportedURLs); } @Test @@ -109,9 +112,9 @@ public void testGetSubscribedURLs() { assertTrue(metadataService.subscribeURL(BASE_URL_GROUP_AND_VERSION)); assertTrue(metadataService.subscribeURL(REST_BASE_URL)); - List subscribedURLs = metadataService.getSubscribedURLs(); + Set subscribedURLs = metadataService.getSubscribedURLs(); assertEquals(4, subscribedURLs.size()); - assertEquals(asList( + assertEquals(asSortedSet( BASE_URL.toFullString(), REST_BASE_URL.toFullString(), BASE_URL_GROUP.toFullString(), @@ -120,7 +123,7 @@ public void testGetSubscribedURLs() { assertTrue(metadataService.unsubscribeURL(REST_BASE_URL)); subscribedURLs = metadataService.getSubscribedURLs(); assertEquals(3, subscribedURLs.size()); - assertEquals(asList( + assertEquals(asSortedSet( BASE_URL.toFullString(), BASE_URL_GROUP.toFullString(), BASE_URL_GROUP_AND_VERSION.toFullString()), subscribedURLs); @@ -128,14 +131,19 @@ public void testGetSubscribedURLs() { assertTrue(metadataService.unsubscribeURL(BASE_URL_GROUP)); subscribedURLs = metadataService.getSubscribedURLs(); assertEquals(2, subscribedURLs.size()); - assertEquals(asList( + assertEquals(asSortedSet( BASE_URL.toFullString(), BASE_URL_GROUP_AND_VERSION.toFullString()), subscribedURLs); assertTrue(metadataService.unsubscribeURL(BASE_URL_GROUP_AND_VERSION)); subscribedURLs = metadataService.getSubscribedURLs(); assertEquals(1, subscribedURLs.size()); - assertEquals(asList( + assertEquals(asSortedSet( BASE_URL.toFullString()), subscribedURLs); } + + private static > SortedSet asSortedSet(T... values) { + return unmodifiableSortedSet(new TreeSet<>(asList(values))); + } + } \ No newline at end of file From a344121634fbf7e5f6548893be3dc1ba75cda073 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 7 Aug 2019 13:27:36 +0800 Subject: [PATCH 28/30] Merge remote-tracking branch 'upstream/master' into dubbo-cloud-native # Conflicts: # dubbo-all/pom.xml # dubbo-bom/pom.xml # dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java # dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java # dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java # dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java # dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java # dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java # dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java # dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java # dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java # dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java # dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java # dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java # dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java # dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java # dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java # dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java # dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java # dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java # dubbo-metadata/dubbo-metadata-definition-protobuf/src/main/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilder.java # dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java # dubbo-metadata/pom.xml # dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java # dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java # dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java # dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java --- .../common/constants/CommonConstants.java | 2 +- .../dubbo/metadata/MetadataService.java | 17 ++++ .../metadata/WritableMetadataService.java | 2 +- .../InMemoryWritableMetadataService.java | 9 +- ...che.dubbo.metadata.WritableMetadataService | 2 +- .../registry/client/ServiceInstance.java | 43 ---------- .../CompositeMetadataServiceURLBuilder.java | 81 ++++++++++++++++++ ...tedServicesRevisionMetadataCustomizer.java | 4 +- .../client/metadata/MetadataServiceProxy.java | 9 +- .../metadata/MetadataServiceURLBuilder.java | 60 ++++--------- ...ataServiceURLParamsMetadataCustomizer.java | 4 +- .../ServiceInstanceMetadataUtils.java | 14 ++- .../SpringCloudMetadataServiceURLBuilder.java | 49 +++++++++++ .../StandardMetadataServiceURLBuilder.java | 74 ++++++++++++++++ .../DefaultMetadataServiceProxyFactory.java | 11 +-- .../proxy/MetadataServiceProxyFactory.java | 2 +- .../support/ServiceOrientedRegistry.java | 32 ++++++- ...lient.metadata.MetadataServiceProxyFactory | 1 - ...metadata.proxy.MetadataServiceProxyFactory | 2 +- ....client.metadata.MetadataServiceURLBuilder | 2 + .../client/DefaultServiceInstanceTest.java | 36 ++++---- ...stomizableServiceInstanceListenerTest.java | 39 +++++++++ .../listener/LoggingEventListenerTest.java | 85 +++++++++++++++++++ .../ServiceInstancesChangedListenerTest.java | 54 ++++++++++++ .../MetadataServiceURLBuilderTest.java | 53 ++++++++++++ ...ingCloudMetadataServiceURLBuilderTest.java | 51 +++++++++++ .../support/ServiceOrientedRegistryTest.java | 32 ++++--- 27 files changed, 630 insertions(+), 140 deletions(-) create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java delete mode 100644 dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.MetadataServiceProxyFactory create mode 100644 dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListenerTest.java create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index 120b6fb8ed8..517df71a234 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -165,7 +165,7 @@ public interface CommonConstants { String METADATA_KEY = "metadata"; - String METADATA_DEFAULT = "local"; + String METADATA_DEFAULT = "default"; String METADATA_REMOTE = "remote"; diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java index 7e5102f887b..71b48d3aa89 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java @@ -43,6 +43,7 @@ */ public interface MetadataService { + /** * The value of all service names */ @@ -53,6 +54,11 @@ public interface MetadataService { */ String ALL_SERVICE_INTERFACES = "*"; + /** + * The service interface name of {@link MetadataService} + */ + String SERVICE_INTERFACE_NAME = MetadataService.class.getName(); + /** * The contract version of {@link MetadataService}, the future update must make sure compatible. */ @@ -164,6 +170,17 @@ default SortedSet getExportedURLs(String serviceInterface, String group, */ String getServiceDefinition(String serviceKey); + /** + * Is the {@link URL} for the {@link MetadataService} or not? + * + * @param url {@link URL url} + * @return + */ + static boolean isMetadataServiceURL(URL url) { + String serviceInterface = url.getServiceInterface(); + return SERVICE_INTERFACE_NAME.equals(serviceInterface); + } + /** * Convert the multiple {@link URL urls} to a {@link List list} of {@link URL urls} * diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java index 662cb6930a2..0af21637d2f 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java @@ -30,7 +30,7 @@ * * @since 2.7.4 */ -@SPI("in-memory") +@SPI("default") public interface WritableMetadataService extends MetadataService { /** diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java index 863bad49675..fa30c212dc2 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java @@ -98,11 +98,17 @@ public SortedSet getExportedURLs(String serviceInterface, String group, @Override public boolean exportURL(URL url) { + if (MetadataService.isMetadataServiceURL(url)) { + return false; + } return addURL(exportedServiceURLs, url); } @Override public boolean unexportURL(URL url) { + if (MetadataService.isMetadataServiceURL(url)) { + return false; + } return removeURL(exportedServiceURLs, url); } @@ -180,7 +186,8 @@ private boolean executeMutually(Callable callable) { return success; } - private static SortedSet getServiceURLs(Map> exportedServiceURLs, String serviceKey, + private static SortedSet getServiceURLs(Map> exportedServiceURLs, String + serviceKey, String protocol) { SortedSet serviceURLs = exportedServiceURLs.get(serviceKey); diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService index e924ed8aff7..cbf9324508b 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService +++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService @@ -1,2 +1,2 @@ -in-memory=org.apache.dubbo.metadata.store.InMemoryWritableMetadataService +default=org.apache.dubbo.metadata.store.InMemoryWritableMetadataService remote=org.apache.dubbo.metadata.store.RemoteWritableMetadataService \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java index 9949bab20d6..251372d033e 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java @@ -16,19 +16,8 @@ */ package org.apache.dubbo.registry.client; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; -import org.apache.dubbo.metadata.MetadataService; - -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import static java.lang.String.valueOf; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort; - /** * The model class of an instance of a service, which is used for service registration and discovery. *

    @@ -103,36 +92,4 @@ default boolean isHealthy() { */ boolean equals(Object another); - /** - * Build the {@link URL urls} from {@link ServiceInstance#getMetadata() the metadata} of {@link ServiceInstance} - * - * @param serviceInstance {@link ServiceInstance} - * @return the not-null {@link List} - */ - static List toUrls(ServiceInstance serviceInstance) { - - Map> paramsMap = getMetadataServiceURLsParams(serviceInstance); - - List urls = new ArrayList<>(paramsMap.size()); - - for (Map.Entry> entry : paramsMap.entrySet()) { - - URLBuilder urlBuilder = new URLBuilder(); - String protocol = entry.getKey(); - Map urlParams = entry.getValue(); - String host = getProviderHost(urlParams); - Integer port = getProviderPort(urlParams); - urlBuilder.setHost(host) - .setPort(port) - .setProtocol(protocol) - .setPath(MetadataService.class.getName()); - - // add parameters - entry.getValue().forEach((name, value) -> urlBuilder.addParameter(name, valueOf(value))); - - urls.add(urlBuilder.build()); - } - - return urls; - } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java new file mode 100644 index 00000000000..9ced03aed3c --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java @@ -0,0 +1,81 @@ +/* + * 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.registry.client.metadata; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.registry.client.ServiceInstance; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ServiceLoader; + +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; +import static java.util.ServiceLoader.load; +import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty; + +/** + * The implementation of {@link MetadataServiceURLBuilder} composites the multiple {@link MetadataServiceURLBuilder} + * instances are loaded by Java standard {@link ServiceLoader} will aggregate {@link URL URLs} for + * {@link MetadataServiceProxy} + * + * @see MetadataServiceURLBuilder + * @see MetadataServiceProxy + * @see MetadataService + * @see URL + * @see ServiceLoader + * @since 2.7.4 + */ +class CompositeMetadataServiceURLBuilder implements MetadataServiceURLBuilder { + + private final Class builderClass; + + private final Iterator builders; + + private final ClassLoader classLoader; + + public CompositeMetadataServiceURLBuilder() { + this.builderClass = MetadataServiceURLBuilder.class; + this.classLoader = getClass().getClassLoader(); + this.builders = initBuilders(); + } + + private Iterator initBuilders() { + return load(builderClass, classLoader).iterator(); + } + + @Override + public List build(ServiceInstance serviceInstance) { + if (serviceInstance == null) { + return emptyList(); + } + + List allURLs = new LinkedList<>(); + + while (builders.hasNext()) { + MetadataServiceURLBuilder builder = builders.next(); + List urls = builder.build(serviceInstance); + if (isNotEmpty(urls)) { + allURLs.addAll(urls); + } + } + + return unmodifiableList(allURLs); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java index 920096a00b9..188312edabf 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java @@ -25,7 +25,7 @@ import java.util.Arrays; import java.util.Collection; -import java.util.List; +import java.util.SortedSet; import static java.lang.String.valueOf; import static java.util.Objects.hash; @@ -48,7 +48,7 @@ protected String buildMetadataKey(ServiceInstance serviceInstance) { @Override protected String buildMetadataValue(ServiceInstance serviceInstance) { WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(); - List exportedURLs = writableMetadataService.getExportedURLs(); + SortedSet exportedURLs = writableMetadataService.getExportedURLs(); Object[] data = exportedURLs.stream() .map(URL::valueOf) // String to URL .map(URL::getServiceInterface) // get the service interface diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java index e22b2b80bbe..45ce42a041e 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java @@ -27,10 +27,11 @@ import java.util.Iterator; import java.util.List; +import java.util.SortedSet; import java.util.function.Function; import static java.lang.reflect.Proxy.newProxyInstance; -import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder.INSTANCE; +import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder.composite; /** * The Proxy object for the {@link MetadataService} whose {@link ServiceInstance} providers may export multiple @@ -49,7 +50,7 @@ class MetadataServiceProxy implements MetadataService { private final Protocol protocol; public MetadataServiceProxy(ServiceInstance serviceInstance, Protocol protocol) { - this(INSTANCE.build(serviceInstance), protocol); + this(composite().build(serviceInstance), protocol); } public MetadataServiceProxy(List urls, Protocol protocol) { @@ -63,12 +64,12 @@ public String serviceName() { } @Override - public List getSubscribedURLs() { + public SortedSet getSubscribedURLs() { return doInMetadataService(MetadataService::getSubscribedURLs); } @Override - public List getExportedURLs(String serviceInterface, String group, String version, String protocol) { + public SortedSet getExportedURLs(String serviceInterface, String group, String version, String protocol) { return doInMetadataService(metadataService -> metadataService.getExportedURLs(serviceInterface, group, version, protocol)); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilder.java index 896cd4845f7..f96f725fd26 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilder.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilder.java @@ -17,65 +17,37 @@ package org.apache.dubbo.registry.client.metadata; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.registry.client.ServiceInstance; -import java.util.ArrayList; import java.util.List; -import java.util.Map; - -import static java.lang.String.valueOf; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort; +import java.util.ServiceLoader; /** - * The {@link URL} builder for {@link MetadataService} + * The builder interface of {@link MetadataService} to build {@link URL URLs}, the multiple implementations + * will be loaded by Java standard {@link ServiceLoader} and {@link #composite() composited}, + * whose building {@link URL URLs} will be aggregated * - * @see MetadataService + * @see CompositeMetadataServiceURLBuilder * @since 2.7.4 */ -class MetadataServiceURLBuilder { +public interface MetadataServiceURLBuilder { /** - * The singleton instance of {@link MetadataServiceURLBuilder} + * Build the {@link URL URLs} from the specified {@link ServiceInstance} + * + * @param serviceInstance {@link ServiceInstance} + * @return non-null */ - public static final MetadataServiceURLBuilder INSTANCE = new MetadataServiceURLBuilder(); - - private MetadataServiceURLBuilder() { - } + List build(ServiceInstance serviceInstance); /** - * Build the {@link URL urls} from {@link ServiceInstance#getMetadata() the metadata} of {@link ServiceInstance} + * Get the composite implementation of {@link MetadataServiceURLBuilder} * - * @param serviceInstance {@link ServiceInstance} - * @return the not-null {@link List} + * @return the instance of {@link CompositeMetadataServiceURLBuilder} + * @see CompositeMetadataServiceURLBuilder */ - public List build(ServiceInstance serviceInstance) { - - Map> paramsMap = getMetadataServiceURLsParams(serviceInstance); - - List urls = new ArrayList<>(paramsMap.size()); - - for (Map.Entry> entry : paramsMap.entrySet()) { - - URLBuilder urlBuilder = new URLBuilder(); - String protocol = entry.getKey(); - Map urlParams = entry.getValue(); - String host = getProviderHost(urlParams); - Integer port = getProviderPort(urlParams); - urlBuilder.setHost(host) - .setPort(port) - .setProtocol(protocol) - .setPath(MetadataService.class.getName()); - - // add parameters - entry.getValue().forEach((name, value) -> urlBuilder.addParameter(name, valueOf(value))); - - urls.add(urlBuilder.build()); - } - - return urls; + static MetadataServiceURLBuilder composite() { + return new CompositeMetadataServiceURLBuilder(); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java index 754a2751686..fadc9c46a87 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java @@ -22,7 +22,7 @@ import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.ServiceInstanceMetadataCustomizer; -import java.util.List; +import java.util.SortedSet; import static org.apache.dubbo.metadata.MetadataService.toURLs; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_KEY; @@ -53,7 +53,7 @@ public String buildMetadataValue(ServiceInstance serviceInstance) { String version = MetadataService.VERSION; - List urls = writableMetadataService.getExportedURLs(serviceInterface, group, version); + SortedSet urls = writableMetadataService.getExportedURLs(serviceInterface, group, version); return getMetadataServiceParameter(toURLs(urls)); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java index 5a9dd6a4a6c..dcebcec42d0 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java @@ -42,10 +42,22 @@ */ public class ServiceInstanceMetadataUtils { + /** + * The prefix of {@link MetadataService} : "dubbo.metadata-service." + */ + public static final String DUBBO_METADATA_SERVICE_PREFIX = "dubbo.metadata-service."; + /** * The key of metadata JSON of {@link MetadataService}'s {@link URL} */ - public static String METADATA_SERVICE_URL_PARAMS_KEY = "dubbo.metadata-service.url-params"; + public static String METADATA_SERVICE_URL_PARAMS_KEY = DUBBO_METADATA_SERVICE_PREFIX + "url-params"; + + /** + * The {@link URL URLs} property name of {@link MetadataService} : + * "dubbo.metadata-service.urls", which is used to be compatible with Dubbo Spring Cloud and + * discovery the metadata of instance + */ + public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = DUBBO_METADATA_SERVICE_PREFIX + "urls"; /** * The key of The revision for all exported Dubbo services. diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java new file mode 100644 index 00000000000..7eb3664d1cf --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java @@ -0,0 +1,49 @@ +/* + * 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.registry.client.metadata; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.registry.client.ServiceInstance; + +import com.alibaba.fastjson.JSON; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME; + +/** + * The {@link MetadataServiceURLBuilder} implementation for The standard Dubbo scenario + * + * @since 2.7.4 + */ +public class SpringCloudMetadataServiceURLBuilder implements MetadataServiceURLBuilder { + + @Override + public List build(ServiceInstance serviceInstance) { + Map metadata = serviceInstance.getMetadata(); + String dubboURLsJSON = metadata.get(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME); + if (StringUtils.isBlank(dubboURLsJSON)) { + return Collections.emptyList(); + } + List urlStrings = JSON.parseArray(dubboURLsJSON, String.class); + return urlStrings.stream().map(URL::valueOf).collect(Collectors.toList()); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java new file mode 100644 index 00000000000..48022af20a6 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java @@ -0,0 +1,74 @@ +/* + * 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.registry.client.metadata; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.registry.client.ServiceInstance; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static java.lang.String.valueOf; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort; + +/** + * The {@link MetadataServiceURLBuilder} implementation for The standard Dubbo scenario + * + * @see MetadataService + * @since 2.7.4 + */ +public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuilder { + + /** + * Build the {@link URL urls} from {@link ServiceInstance#getMetadata() the metadata} of {@link ServiceInstance} + * + * @param serviceInstance {@link ServiceInstance} + * @return the not-null {@link List} + */ + @Override + public List build(ServiceInstance serviceInstance) { + + Map> paramsMap = getMetadataServiceURLsParams(serviceInstance); + + List urls = new ArrayList<>(paramsMap.size()); + + for (Map.Entry> entry : paramsMap.entrySet()) { + + URLBuilder urlBuilder = new URLBuilder(); + String protocol = entry.getKey(); + Map urlParams = entry.getValue(); + String host = getProviderHost(urlParams); + Integer port = getProviderPort(urlParams); + urlBuilder.setHost(host) + .setPort(port) + .setProtocol(protocol) + .setPath(MetadataService.class.getName()); + + // add parameters + entry.getValue().forEach((name, value) -> urlBuilder.addParameter(name, valueOf(value))); + + urls.add(urlBuilder.build()); + } + + return urls; + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java index 2e5840b7ec8..06248f97002 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java @@ -27,20 +27,21 @@ import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; import org.apache.dubbo.rpc.cluster.support.AvailableCluster; -import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder.composite; + /** - * The factory of {@link MetadataService}'s {@link Proxy} + * The default {@link MetadataServiceProxyFactory} to get the proxy of {@link MetadataService} * * @since 2.7.4 */ public class DefaultMetadataServiceProxyFactory implements MetadataServiceProxyFactory { - private final Map proxys = new HashMap<>(); + private final Map proxies = new HashMap<>(); private ProxyFactory proxyFactory; @@ -58,11 +59,11 @@ public void setProxyFactory(ProxyFactory proxyFactory) { @Override public MetadataService getProxy(ServiceInstance serviceInstance) { - return proxys.computeIfAbsent(serviceInstance.getId(), id -> createProxy(serviceInstance)); + return proxies.computeIfAbsent(serviceInstance.getId(), id -> createProxy(serviceInstance)); } protected MetadataService createProxy(ServiceInstance serviceInstance) { - List urls = ServiceInstance.toUrls(serviceInstance); + List urls = composite().build(serviceInstance); List> invokers = urls.stream() .map(url -> protocol.refer(MetadataService.class, url)) .collect(Collectors.toList()); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java index ffc097244cf..fd55bb776f1 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java @@ -29,7 +29,7 @@ * @see MetadataService * @since 2.7.4 */ -@SPI("local") +@SPI("default") public interface MetadataServiceProxyFactory { /** diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java index 8018effc711..9d388c87596 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java @@ -40,6 +40,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.SortedSet; import java.util.stream.Collectors; import static java.lang.String.format; @@ -139,10 +140,15 @@ protected boolean shouldSubscribe(URL subscribedURL) { } @Override - public void doRegister(URL url) { + public final void register(URL url) { if (!shouldRegister(url)) { // Should Not Register return; } + super.register(url); + } + + @Override + public void doRegister(URL url) { if (writableMetadataService.exportURL(url)) { if (logger.isInfoEnabled()) { logger.info(format("The URL[%s] registered successfully.", url.toString())); @@ -155,10 +161,15 @@ public void doRegister(URL url) { } @Override - public void doUnregister(URL url) { + public final void unregister(URL url) { if (!shouldRegister(url)) { return; } + super.unregister(url); + } + + @Override + public void doUnregister(URL url) { if (writableMetadataService.unexportURL(url)) { if (logger.isInfoEnabled()) { logger.info(format("The URL[%s] deregistered successfully.", url.toString())); @@ -171,13 +182,26 @@ public void doUnregister(URL url) { } @Override - public void doSubscribe(URL url, NotifyListener listener) { + public final void subscribe(URL url, NotifyListener listener) { if (!shouldSubscribe(url)) { // Should Not Subscribe return; } + super.subscribe(url, listener); + } + + @Override + public void doSubscribe(URL url, NotifyListener listener) { subscribeURLs(url, listener); } + @Override + public final void unsubscribe(URL url, NotifyListener listener) { + if (!shouldSubscribe(url)) { // Should Not Subscribe + return; + } + super.unsubscribe(url, listener); + } + @Override public void doUnsubscribe(URL url, NotifyListener listener) { writableMetadataService.unsubscribeURL(url); @@ -401,7 +425,7 @@ protected List getProviderExportedURLs(URL subscribedURL, ServiceInstance p try { MetadataService metadataService = metadataServiceProxyFactory.getProxy(providerInstance); - List urls = metadataService.getExportedURLs(serviceInterface, group, version, protocol); + SortedSet urls = metadataService.getExportedURLs(serviceInterface, group, version, protocol); exportedURLs = urls.stream().map(URL::valueOf).collect(Collectors.toList()); } catch (Throwable e) { if (logger.isErrorEnabled()) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.MetadataServiceProxyFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.MetadataServiceProxyFactory deleted file mode 100644 index 48860587024..00000000000 --- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.MetadataServiceProxyFactory +++ /dev/null @@ -1 +0,0 @@ -default=org.apache.dubbo.registry.client.metadata.DefaultMetadataServiceProxyFactory \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory index d9283dec444..359dbe8b9ba 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory @@ -1,2 +1,2 @@ -local=org.apache.dubbo.registry.client.metadata.proxy.DefaultMetadataServiceProxyFactory +default=org.apache.dubbo.registry.client.metadata.proxy.DefaultMetadataServiceProxyFactory remote=org.apache.dubbo.registry.client.metadata.proxy.RemoteMetadataServiceProxyFactory \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder new file mode 100644 index 00000000000..418ebb7d92e --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder @@ -0,0 +1,2 @@ +org.apache.dubbo.registry.client.metadata.StandardMetadataServiceURLBuilder +org.apache.dubbo.registry.client.metadata.SpringCloudMetadataServiceURLBuilder \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java index 38739f18b94..c48bfa97584 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java @@ -30,31 +30,37 @@ */ public class DefaultServiceInstanceTest { - public static DefaultServiceInstance INSTANCE = - new DefaultServiceInstance("A", "127.0.0.1", 8080); + public DefaultServiceInstance instance; + + public static DefaultServiceInstance createInstance() { + DefaultServiceInstance instance = new DefaultServiceInstance("A", "127.0.0.1", 8080); + instance.getMetadata().put("dubbo.metadata-service.urls", "[ \"dubbo://192.168.0.102:20881/com.alibaba.cloud.dubbo.service.DubboMetadataService?anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20881&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=com.alibaba.cloud.dubbo.service.DubboMetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExportedURLs,getAllExportedURLs&pid=17134&qos.enable=false®ister=true&release=2.7.3&revision=1.0.0&side=provider×tamp=1564826098503&version=1.0.0\" ]"); + instance.getMetadata().put("dubbo.metadata-service.url-params", "{\"dubbo\":{\"application\":\"dubbo-provider-demo\",\"deprecated\":\"false\",\"group\":\"dubbo-provider-demo\",\"version\":\"1.0.0\",\"timestamp\":\"1564845042651\",\"dubbo\":\"2.0.2\",\"provider.host\":\"192.168.0.102\",\"provider.port\":\"20880\"}}"); + return instance; + } @BeforeEach public void init() { - INSTANCE = new DefaultServiceInstance("A", "127.0.0.1", 8080); + instance = createInstance(); } @Test public void testDefaultValues() { - assertTrue(INSTANCE.isEnabled()); - assertTrue(INSTANCE.isHealthy()); - assertTrue(INSTANCE.getMetadata().isEmpty()); + assertTrue(instance.isEnabled()); + assertTrue(instance.isHealthy()); + assertFalse(instance.getMetadata().isEmpty()); } @Test public void testSetAndGetValues() { - INSTANCE.setEnabled(false); - INSTANCE.setHealthy(false); - - assertEquals("A", INSTANCE.getServiceName()); - assertEquals("127.0.0.1", INSTANCE.getHost()); - assertEquals(8080, INSTANCE.getPort()); - assertFalse(INSTANCE.isEnabled()); - assertFalse(INSTANCE.isHealthy()); - assertTrue(INSTANCE.getMetadata().isEmpty()); + instance.setEnabled(false); + instance.setHealthy(false); + + assertEquals("A", instance.getServiceName()); + assertEquals("127.0.0.1", instance.getHost()); + assertEquals(8080, instance.getPort()); + assertFalse(instance.isEnabled()); + assertFalse(instance.isHealthy()); + assertFalse(instance.getMetadata().isEmpty()); } } diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListenerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListenerTest.java new file mode 100644 index 00000000000..0b022b0c1b7 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListenerTest.java @@ -0,0 +1,39 @@ +/* + * 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.registry.client.event.listener; + +import org.apache.dubbo.registry.client.DefaultServiceInstanceTest; +import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; + +import org.junit.jupiter.api.Test; + +/** + * {@link CustomizableServiceInstanceListener} Test + * + * @since 2.7.4 + */ +public class CustomizableServiceInstanceListenerTest { + + private CustomizableServiceInstanceListener listener = new CustomizableServiceInstanceListener(); + + @Test + public void testOnEvent() { + ServiceInstancePreRegisteredEvent event = new ServiceInstancePreRegisteredEvent(this, DefaultServiceInstanceTest.createInstance()); + // breaking test + listener.onEvent(event); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java new file mode 100644 index 00000000000..ddd3aecd08e --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java @@ -0,0 +1,85 @@ +/* + * 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.registry.client.event.listener; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.client.FileSystemServiceDiscovery; +import org.apache.dubbo.registry.client.ServiceDiscovery; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartingEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppingEvent; +import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; +import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent; +import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent; +import org.apache.dubbo.registry.client.event.ServiceInstanceUnregisteredEvent; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static java.util.Collections.singleton; +import static org.apache.dubbo.registry.client.DefaultServiceInstanceTest.createInstance; + +/** + * {@link LoggingEventListener} Test + * + * @since 2.7.4 + */ +public class LoggingEventListenerTest { + + private LoggingEventListener listener; + + @BeforeEach + public void init() { + listener = new LoggingEventListener(); + } + + @Test + public void testOnEvent() { + + URL connectionURL = URL.valueOf("file:///Users/Home"); + ServiceDiscovery serviceDiscovery = new FileSystemServiceDiscovery(connectionURL); + + // ServiceDiscoveryStartingEvent + listener.onEvent(new ServiceDiscoveryStartingEvent(serviceDiscovery)); + + // ServiceDiscoveryStartedEvent + listener.onEvent(new ServiceDiscoveryStartedEvent(serviceDiscovery)); + + // ServiceInstancePreRegisteredEvent + listener.onEvent(new ServiceInstancePreRegisteredEvent(serviceDiscovery, createInstance())); + + // ServiceInstanceRegisteredEvent + listener.onEvent(new ServiceInstanceRegisteredEvent(serviceDiscovery, createInstance())); + + // ServiceInstancesChangedEvent + listener.onEvent(new ServiceInstancesChangedEvent("test", singleton(createInstance()))); + + // ServiceInstancePreUnregisteredEvent + listener.onEvent(new ServiceInstancePreUnregisteredEvent(serviceDiscovery, createInstance())); + + // ServiceInstanceUnregisteredEvent + listener.onEvent(new ServiceInstanceUnregisteredEvent(serviceDiscovery, createInstance())); + + // ServiceDiscoveryStoppingEvent + listener.onEvent(new ServiceDiscoveryStoppingEvent(serviceDiscovery)); + + // ServiceDiscoveryStoppedEvent + listener.onEvent(new ServiceDiscoveryStoppedEvent(serviceDiscovery)); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java new file mode 100644 index 00000000000..898e7324057 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java @@ -0,0 +1,54 @@ +/* + * 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.registry.client.event.listener; + +import org.apache.dubbo.event.Event; +import org.apache.dubbo.event.EventDispatcher; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicReference; + +import static java.util.Collections.emptyList; +import static org.apache.dubbo.event.EventDispatcher.getDefaultExtension; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link ServiceInstancesChangedListener} Test + * + * @since 2.7.4 + */ +public class ServiceInstancesChangedListenerTest { + + @Test + public void testOnEvent() { + + EventDispatcher eventDispatcher = getDefaultExtension(); + + Event event = new ServiceInstancesChangedEvent("test", emptyList()); + + AtomicReference eventRef = new AtomicReference<>(); + + eventDispatcher.addEventListener((ServiceInstancesChangedListener) eventRef::set); + + // Dispatch a ServiceInstancesChangedEvent + eventDispatcher.dispatch(event); + + assertEquals(eventRef.get(), event); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java new file mode 100644 index 00000000000..5c905779d20 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java @@ -0,0 +1,53 @@ +/* + * 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.registry.client.metadata; + +import org.apache.dubbo.registry.client.DefaultServiceInstance; +import org.apache.dubbo.registry.client.ServiceInstance; + +import org.junit.jupiter.api.Test; + +import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilder.composite; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * {@link MetadataServiceURLBuilder} Test + * + * @since 2.7.4 + */ +public class MetadataServiceURLBuilderTest { + + static ServiceInstance serviceInstance = new DefaultServiceInstance("127.0.0.1", "test", 8080); + + static { + serviceInstance.getMetadata().put("dubbo.metadata-service.urls", "[ \"dubbo://192.168.0.102:20881/com.alibaba.cloud.dubbo.service.DubboMetadataService?anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20881&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=com.alibaba.cloud.dubbo.service.DubboMetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExportedURLs,getAllExportedURLs&pid=17134&qos.enable=false®ister=true&release=2.7.3&revision=1.0.0&side=provider×tamp=1564826098503&version=1.0.0\" ]"); + serviceInstance.getMetadata().put("dubbo.metadata-service.url-params", "{\"dubbo\":{\"application\":\"dubbo-provider-demo\",\"deprecated\":\"false\",\"group\":\"dubbo-provider-demo\",\"version\":\"1.0.0\",\"timestamp\":\"1564845042651\",\"dubbo\":\"2.0.2\",\"provider.host\":\"192.168.0.102\",\"provider.port\":\"20880\"}}"); + } + + @Test + public void testComposite() { + assertEquals(CompositeMetadataServiceURLBuilder.class, composite().getClass()); + } + + @Test + public void testBuild() { + assertTrue(composite().build(null).isEmpty()); + assertTrue(composite().build(new DefaultServiceInstance("127.0.0.1", "test", 8080)).isEmpty()); + assertEquals(2, composite().build(serviceInstance).size()); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java new file mode 100644 index 00000000000..0a2b9f4a466 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java @@ -0,0 +1,51 @@ +/* + * 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.registry.client.metadata; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.client.DefaultServiceInstance; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilderTest.serviceInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link SpringCloudMetadataServiceURLBuilder} Test + * + * @since 2.7.4 + */ +public class SpringCloudMetadataServiceURLBuilderTest { + + private SpringCloudMetadataServiceURLBuilder builder = new SpringCloudMetadataServiceURLBuilder(); + + @Test + public void testBuild() { + List urls = builder.build(new DefaultServiceInstance("127.0.0.1", "test", 8080)); + assertEquals(0, urls.size()); + + urls = builder.build(serviceInstance); + assertEquals(1, urls.size()); + URL url = urls.get(0); + assertEquals("192.168.0.102", url.getHost()); + assertEquals(20881, url.getPort()); + assertEquals("com.alibaba.cloud.dubbo.service.DubboMetadataService", url.getServiceInterface()); + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java index 9840a255f85..ec40682284c 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java @@ -25,8 +25,11 @@ import java.util.LinkedList; import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; -import static java.util.Collections.emptyList; +import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableSortedSet; import static org.apache.dubbo.common.URL.valueOf; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; @@ -51,7 +54,7 @@ public class ServiceOrientedRegistryTest { private static final String SERVICE_INTERFACE = "org.apache.dubbo.metadata.MetadataService"; - private static final String GROUP = "spring-cloud-alibaba-dubbo-provider"; + private static final String GROUP = "dubbo-provider"; private static final String VERSION = "1.0.0"; @@ -94,11 +97,11 @@ public void testRegister() { registry.register(url); - List urls = metadataService.getExportedURLs(); + SortedSet urls = metadataService.getExportedURLs(); - assertEquals(emptyList(), urls); - assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE), urls); - assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP), urls); + assertTrue(urls.isEmpty()); + assertEquals(toSortedSet(), metadataService.getExportedURLs(SERVICE_INTERFACE)); + assertEquals(toSortedSet(), metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP)); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP, VERSION), urls); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP, VERSION, DEFAULT_PROTOCOL), urls); @@ -110,8 +113,8 @@ public void testRegister() { urls = metadataService.getExportedURLs(); - assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION), urls); - assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION, DEFAULT_PROTOCOL), urls); + assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION), toSortedSet(urls.first())); + assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION, DEFAULT_PROTOCOL), toSortedSet(urls.first())); } @@ -125,7 +128,7 @@ public void testUnregister() { // register registry.register(newURL); - List urls = metadataService.getExportedURLs(); + SortedSet urls = metadataService.getExportedURLs(); assertFalse(urls.isEmpty()); assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION), urls); @@ -136,7 +139,7 @@ public void testUnregister() { urls = metadataService.getExportedURLs(); - assertEquals(emptyList(), urls); + assertEquals(toSortedSet(), urls); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE), urls); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP), urls); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP, VERSION), urls); @@ -148,10 +151,9 @@ public void testSubscribe() { registry.subscribe(url, new MyNotifyListener()); - List urls = metadataService.getSubscribedURLs(); + SortedSet urls = metadataService.getSubscribedURLs(); - assertFalse(urls.isEmpty()); - assertEquals(url, urls.get(0)); + assertTrue(urls.isEmpty()); } @@ -170,4 +172,8 @@ public List getURLs() { } } + private static > SortedSet toSortedSet(T... values) { + return unmodifiableSortedSet(new TreeSet<>(asList(values))); + } + } From 8c7f37aff35db7b763cf11d00649b8472cb2fb8f Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 7 Aug 2019 15:24:42 +0800 Subject: [PATCH 29/30] Polish apache/dubbo#3984 : Add the implementation of Page getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly) --- .../zookeeper/ZookeeperServiceDiscovery.java | 37 +++++++++++++++++++ .../ZookeeperServiceDiscoveryTest.java | 2 + 2 files changed, 39 insertions(+) diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java index 6776a7457cf..a8de39c7b81 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java @@ -21,6 +21,8 @@ import org.apache.dubbo.common.function.ThrowableFunction; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.DefaultPage; +import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.event.EventListener; import org.apache.dubbo.registry.client.ServiceDiscovery; @@ -32,7 +34,9 @@ import org.apache.curator.framework.api.CuratorWatcher; import org.apache.zookeeper.KeeperException; +import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -113,6 +117,39 @@ public List getInstances(String serviceName) throws NullPointer return doInServiceDiscovery(s -> build(s.queryForInstances(serviceName))); } + @Override + public Page getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly) { + String path = buildServicePath(serviceName); + + return execute(path, p -> { + + List serviceInstances = new LinkedList<>(); + + List serviceIds = new LinkedList<>(curatorFramework.getChildren().forPath(p)); + + int totalSize = serviceIds.size(); + + Iterator iterator = serviceIds.iterator(); + + for (int i = 0; i < offset; i++) { + if (iterator.hasNext()) { // remove the elements from 0 to offset + iterator.next(); + iterator.remove(); + } + } + + for (int i = 0; i < pageSize; i++) { + if (iterator.hasNext()) { + String serviceId = iterator.next(); + ServiceInstance serviceInstance = build(serviceDiscovery.queryForInstance(serviceName, serviceId)); + serviceInstances.add(serviceInstance); + } + } + + return new DefaultPage<>(offset, pageSize, serviceInstances, totalSize); + }); + } + @Override public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java index 61870224ca8..5f14ec5849e 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.Page; +import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceInstance; @@ -60,6 +61,7 @@ public class ZookeeperServiceDiscoveryTest { @BeforeEach public void init() throws Exception { + EventDispatcher.getDefaultExtension().removeAllEventListeners(); zkServerPort = getAvailablePort(); zkServer = new TestingServer(zkServerPort, true); zkServer.start(); From 2a883232b0a119e67d96704141d09b2ba81e380d Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 7 Aug 2019 17:27:53 +0800 Subject: [PATCH 30/30] Code merge --- .../dubbo/config/ApplicationConfig.java | 48 +++++++++++++++++++ ...nfigurableMetadataServiceExporterTest.java | 5 +- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java index 1400b76b101..535a1829102 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java @@ -17,17 +17,24 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.compiler.support.AdaptiveCompiler; +import org.apache.dubbo.common.config.ConfigurationUtils; 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.config.support.Parameter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_ENV_KEYS; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_LABELS; import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY; +import static org.apache.dubbo.common.constants.CommonConstants.EQUAL_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_COMPATIBLE; @@ -387,4 +394,45 @@ public String getMetadata() { public void setMetadata(String metadata) { this.metadata = metadata; } + + @Override + public void refresh() { + super.refresh(); + appendEnvironmentProperties(); + } + + /** + * 1. OS Environment: DUBBO_LABELS=tag=pre;key=value + * 2. JVM Options: -Denv_keys = DUBBO_KEY1, DUBBO_KEY2 + */ + private void appendEnvironmentProperties() { + String rawLabels = ConfigurationUtils.getProperty(DUBBO_LABELS); + if (StringUtils.isNotEmpty(rawLabels)) { + String[] labelPairs = SEMICOLON_SPLIT_PATTERN.split(rawLabels); + for (String pair : labelPairs) { + String[] label = EQUAL_SPLIT_PATTERN.split(pair); + if (label.length == 2) { + updateParameters(parameters, label[0], label[1]); + } + } + } + + String rawKeys = ConfigurationUtils.getProperty(DUBBO_ENV_KEYS); + if (StringUtils.isNotEmpty(rawKeys)) { + String[] keys = COMMA_SPLIT_PATTERN.split(rawKeys); + for (String key : keys) { + String value = ConfigurationUtils.getProperty(key); + if (value != null) { + updateParameters(parameters, key, value); + } + } + } + } + + private void updateParameters(Map map, String key, String value) { + if (parameters == null) { + parameters = new HashMap<>(); + } + parameters.put(key, value); + } } diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java index 43331e996de..c53eb7df27c 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java @@ -22,7 +22,6 @@ import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.metadata.MetadataService; -import org.apache.dubbo.metadata.MetadataServiceExporter; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -44,6 +43,7 @@ public class ConfigurableMetadataServiceExporterTest { @BeforeAll public static void init() { ConfigManager configManager = ConfigManager.getInstance(); + configManager.clear(); ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("test"); configManager.setApplication(applicationConfig); @@ -69,7 +69,8 @@ private static RegistryConfig registryConfig() { @Test public void testExportAndUnexport() { - MetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); + ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); + exporter.setApplicationConfig(ConfigManager.getInstance().getApplication().get()); List urls = exporter.export(); assertEquals(1, urls.size());