From f51b3944c36679500ce0da3eee79843e6dd467d9 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 11 Jul 2019 15:13:08 +0800 Subject: [PATCH 01/55] 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/55] =?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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] =?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/55] 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/55] 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/55] @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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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/55] 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()); From 391d0538200ca73c331ba1ffe318c306cd33a440 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 8 Aug 2019 10:54:06 +0800 Subject: [PATCH 31/55] Fix the cases --- .../support/ServiceOrientedRegistryTest.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 ec40682284c..b21f2c69e59 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 @@ -99,7 +99,7 @@ public void testRegister() { SortedSet urls = metadataService.getExportedURLs(); - assertTrue(urls.isEmpty()); + assertFalse(urls.isEmpty()); assertEquals(toSortedSet(), metadataService.getExportedURLs(SERVICE_INTERFACE)); assertEquals(toSortedSet(), metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP)); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP, VERSION), urls); @@ -128,7 +128,9 @@ public void testUnregister() { // register registry.register(newURL); - SortedSet urls = metadataService.getExportedURLs(); + SortedSet urls = new TreeSet<>(metadataService.getExportedURLs()); + + urls.remove(url.toFullString()); assertFalse(urls.isEmpty()); assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION), urls); @@ -139,9 +141,9 @@ public void testUnregister() { urls = metadataService.getExportedURLs(); - assertEquals(toSortedSet(), urls); - assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE), urls); - assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP), urls); + assertEquals(toSortedSet(url.toFullString()), urls); + assertTrue(metadataService.getExportedURLs(SERVICE_INTERFACE).isEmpty()); + assertTrue(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP).isEmpty()); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP, VERSION), urls); assertEquals(metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP, VERSION, DEFAULT_PROTOCOL), urls); } From 83fc425a2167ac143ec3047a4b16b5fa341cd4c3 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 8 Aug 2019 15:01:19 +0800 Subject: [PATCH 32/55] Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native # Conflicts: # dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java # dubbo-metadata/dubbo-metadata-definition-protobuf/pom.xml # dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java # dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java # dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java --- .../file/FileSystemDynamicConfiguration.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 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 80931555a40..59d91138397 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 @@ -170,14 +170,15 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration private final Map> listenersRepository; public FileSystemDynamicConfiguration(URL url) { - this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url)); + this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url), + getThreadPoolKeepAliveTime(url)); } public FileSystemDynamicConfiguration(File rootDirectory, String encoding, String threadPoolPrefixName, - int threadPoolSize - ) { - super(threadPoolPrefixName, threadPoolSize); + int threadPoolSize, + long keepAliveTime) { + super(threadPoolPrefixName, threadPoolSize, keepAliveTime); this.rootDirectory = rootDirectory; this.encoding = encoding; this.processingDirectories = initProcessingDirectories(); From a14782963578e91caaea635e4b97e32c6c6b20eb Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 12 Aug 2019 15:43:46 +0800 Subject: [PATCH 33/55] Refactor ConfigManager --- .../apache/dubbo/config/AbstractConfig.java | 15 +++ .../dubbo/config/context/ConfigManager.java | 113 +++++++++++------- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java index ccac9419b76..c1a7548585d 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -30,9 +30,11 @@ import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.context.ConfigConfigurationAdapter; +import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.rpc.model.ConsumerMethodModel; +import javax.annotation.PostConstruct; import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -646,4 +648,17 @@ public boolean equals(Object obj) { } return true; } + + /** + * Add {@link AbstractConfig current instance} into {@link ConfigManager} + *

    + * Current method will invoked by Spring or Java EE container automatically, or should be triggered manually. + * + * @see ConfigManager#addConfig(AbstractConfig) + * @since 2.7.4 + */ + @PostConstruct + public void addIntoConfigManager() { + ConfigManager.getInstance().addConfig(this); + } } 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 188881906be..4ed89ebf7f2 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 @@ -40,11 +40,11 @@ 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.lang.Boolean.TRUE; +import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableSet; import static java.util.Optional.ofNullable; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; @@ -97,14 +97,7 @@ public class ConfigManager { private volatile ApplicationConfig application; private volatile MonitorConfig monitor; - 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 final Map, Map> configsCache = newMap(); private final StampedLock lock = new StampedLock(); @@ -128,6 +121,34 @@ public Optional getApplication() { return ofNullable(application); } + /** + * Add the dubbo {@link AbstractConfig config} + * + * @param config the dubbo {@link AbstractConfig config} + */ + public void addConfig(AbstractConfig config) { + Class configType = config.getClass(); + write(() -> { + Map configsMap = configsCache.computeIfAbsent(configType, type -> newMap()); + addIfAbsent(config, configsMap); + }); + } + + protected Map getConfigsMap(Class configType) { + return read(() -> (Map) configsCache.getOrDefault(configType, emptyMap())); + } + + protected Collection getConfigs(Class configType) { + return read(() -> getConfigsMap(configType).values()); + } + + protected C getConfig(Class configType, String id) { + return read(() -> { + Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); + return configsMap.get(id); + }); + } + // MonitorConfig correlative methods public void setMonitor(MonitorConfig monitor) { @@ -157,7 +178,7 @@ public Optional getModule() { // ConfigCenterConfig correlative methods public void addConfigCenter(ConfigCenterConfig configCenter) { - addIfAbsent(configCenter, configCenters); + addConfig(configCenter); } public void addConfigCenters(Iterable configCenters) { @@ -165,17 +186,17 @@ public void addConfigCenters(Iterable configCenters) { } public ConfigCenterConfig getConfigCenter(String id) { - return configCenters.get(id); + return getConfig(ConfigCenterConfig.class, id); } public Collection getConfigCenters() { - return configCenters.values(); + return getConfigs(ConfigCenterConfig.class); } // MetadataReportConfig correlative methods public void addMetadataReport(MetadataReportConfig metadataReportConfig) { - addIfAbsent(metadataReportConfig, metadataConfigs); + addConfig(metadataReportConfig); } public void addMetadataReports(Iterable metadataReportConfigs) { @@ -183,17 +204,17 @@ public void addMetadataReports(Iterable metadataReportConf } public Collection getMetadataConfigs() { - return metadataConfigs.values(); + return getConfigs(MetadataReportConfig.class); } // MetadataReportConfig correlative methods public void addProvider(ProviderConfig providerConfig) { - addIfAbsent(providerConfig, providers); + addConfig(providerConfig); } public Optional getProvider(String id) { - return ofNullable(providers.get(id)); + return ofNullable(getConfig(ProviderConfig.class, id)); } public Optional getDefaultProvider() { @@ -201,17 +222,17 @@ public Optional getDefaultProvider() { } public Collection getProviders() { - return providers.values(); + return getConfigs(ProviderConfig.class); } // ConsumerConfig correlative methods public void addConsumer(ConsumerConfig consumerConfig) { - addIfAbsent(consumerConfig, consumers); + addConfig(consumerConfig); } public Optional getConsumer(String id) { - return ofNullable(consumers.get(id)); + return ofNullable(getConfig(ConsumerConfig.class, id)); } public Optional getDefaultConsumer() { @@ -219,13 +240,13 @@ public Optional getDefaultConsumer() { } public Collection getConsumers() { - return consumers.values(); + return getConfigs(ConsumerConfig.class); } // ProtocolConfig correlative methods public void addProtocol(ProtocolConfig protocolConfig) { - addIfAbsent(protocolConfig, protocols); + addConfig(protocolConfig); } public void addProtocols(Iterable protocolConfigs, boolean canBeDefault) { @@ -235,15 +256,15 @@ public void addProtocols(Iterable protocolConfigs, boolean canBe } public Optional getProtocol(String id) { - return ofNullable(protocols.get(id)); + return ofNullable(getConfig(ProtocolConfig.class, id)); } public List getDefaultProtocols() { - return getDefaultConfigs(protocols); + return getDefaultConfigs(getConfigsMap(ProtocolConfig.class)); } public Collection getProtocols() { - return protocols.values(); + return getConfigs(ProtocolConfig.class); } public Set getProtocolIds() { @@ -253,7 +274,7 @@ public Set getProtocolIds() { protocolIds.addAll(getSubProperties(Environment.getInstance() .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX)); - protocolIds.addAll(protocols.keySet()); + protocolIds.addAll(getConfigIds(ProtocolConfig.class)); return unmodifiableSet(protocolIds); } @@ -261,7 +282,7 @@ public Set getProtocolIds() { // RegistryConfig correlative methods public void addRegistry(RegistryConfig registryConfig) { - addIfAbsent(registryConfig, registries); + addConfig(registryConfig); } public void addRegistries(Iterable registryConfigs) { @@ -271,15 +292,15 @@ public void addRegistries(Iterable registryConfigs) { } public Optional getRegistry(String id) { - return ofNullable(registries.get(id)); + return ofNullable(getConfig(RegistryConfig.class, id)); } public List getDefaultRegistries() { - return getDefaultConfigs(registries); + return getDefaultConfigs(getConfigsMap(RegistryConfig.class)); } public Collection getRegistries() { - return registries.values(); + return getConfigs(RegistryConfig.class); } public Set getRegistryIds() { @@ -289,36 +310,36 @@ public Set getRegistryIds() { registryIds.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(), REGISTRIES_SUFFIX)); - registryIds.addAll(registries.keySet()); + registryIds.addAll(getConfigIds(RegistryConfig.class)); return unmodifiableSet(registryIds); } // ServiceConfig correlative methods public void addService(ServiceConfig serviceConfig) { - addIfAbsent(serviceConfig, serviceConfigs); + addConfig(serviceConfig); } - public Collection> getServiceConfigs() { - return serviceConfigs.values(); + public Collection getServiceConfigs() { + return getConfigs(ServiceConfig.class); } public ServiceConfig getServiceConfig(String id) { - return (ServiceConfig) serviceConfigs.get(id); + return getConfig(ServiceConfig.class, id); } // ReferenceConfig correlative methods public void addReference(ReferenceConfig referenceConfig) { - addIfAbsent(referenceConfig, referenceConfigs); + addConfig(referenceConfig); } - public Collection> getReferenceConfigs() { - return referenceConfigs.values(); + public Collection getReferenceConfigs() { + return getConfigs(ReferenceConfig.class); } public ReferenceConfig getReferenceConfig(String id) { - return (ReferenceConfig) referenceConfigs.get(id); + return getConfig(ReferenceConfig.class, id); } protected static Set getSubProperties(Map properties, String prefix) { @@ -350,15 +371,17 @@ 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.configsCache.clear(); }); } + private Collection getConfigIds(Class configType) { + return getConfigs(configType) + .stream() + .map(AbstractConfig::getId) + .collect(Collectors.toSet()); + } + private V write(Callable callable) { V value = null; long stamp = lock.writeLock(); @@ -412,7 +435,7 @@ private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) } } - private static Map, Map> newMap() { + private static Map newMap() { return new HashMap<>(); } From e307e986cb4cc2b18ab216d786976d0c873aaa79 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 12 Aug 2019 17:04:24 +0800 Subject: [PATCH 34/55] Refactor ConfigManager --- .../dubbo/config/context/ConfigManager.java | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) 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 c2963c75129..a7a37968ab2 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 @@ -94,11 +94,6 @@ public class ConfigManager { private static final ConfigManager CONFIG_MANAGER = new ConfigManager(); - private volatile ModuleConfig module; - private volatile ApplicationConfig application; - private volatile MonitorConfig monitor; - private volatile MetricsConfig metrics; - private final Map, Map> configsCache = newMap(); private final StampedLock lock = new StampedLock(); @@ -113,14 +108,11 @@ private ConfigManager() { // ApplicationConfig correlative methods public void setApplication(ApplicationConfig application) { - if (application != null) { - checkDuplicate(this.application, application); - this.application = application; - } + addConfig(application, true); } public Optional getApplication() { - return ofNullable(application); + return ofNullable(getConfig(ApplicationConfig.class)); } /** @@ -129,10 +121,14 @@ public Optional getApplication() { * @param config the dubbo {@link AbstractConfig config} */ public void addConfig(AbstractConfig config) { + addConfig(config, false); + } + + protected void addConfig(AbstractConfig config, boolean unique) { Class configType = config.getClass(); write(() -> { Map configsMap = configsCache.computeIfAbsent(configType, type -> newMap()); - addIfAbsent(config, configsMap); + addIfAbsent(config, configsMap, unique); }); } @@ -151,41 +147,48 @@ protected C getConfig(Class configType, String id) }); } + protected C getConfig(Class configType) throws IllegalStateException { + return read(() -> { + Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); + int size = configsMap.size(); + if (size < 0) { +// throw new IllegalStateException("No such " + configType.getName() + " is found"); + return null; + } else if (size > 1) { + throw new IllegalStateException("The expected single matching " + configType.getName() + " but found " + size + " instances"); + } else { + return configsMap.values().iterator().next(); + } + }); + } + // MonitorConfig correlative methods public void setMonitor(MonitorConfig monitor) { - if (monitor != null) { - checkDuplicate(this.monitor, monitor); - this.monitor = monitor; - } + addConfig(monitor, true); } public Optional getMonitor() { - return ofNullable(monitor); + return ofNullable(getConfig(MonitorConfig.class)); } // ModuleConfig correlative methods public void setModule(ModuleConfig module) { - if (module != null) { - checkDuplicate(this.module, module); - this.module = module; - } + addConfig(module, true); + } public Optional getModule() { - return ofNullable(module); + return ofNullable(getConfig(ModuleConfig.class)); } public void setMetrics(MetricsConfig metrics) { - if (metrics != null) { - checkDuplicate(this.metrics, metrics); - this.metrics = metrics; - } + addConfig(metrics, true); } public Optional getMetrics() { - return ofNullable(metrics); + return ofNullable(getConfig(MetricsConfig.class)); } // ConfigCenterConfig correlative methods @@ -381,9 +384,6 @@ public void refreshAll() { // For test purpose public void clear() { write(() -> { - this.application = null; - this.monitor = null; - this.module = null; this.configsCache.clear(); }); } @@ -441,7 +441,7 @@ private V read(Callable callable) { return value; } - private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) { + private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) throws IllegalStateException { 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."); @@ -452,12 +452,19 @@ private static Map newMap() { return new HashMap<>(); } - private static void addIfAbsent(C config, Map configsMap) { + static void addIfAbsent(C config, Map configsMap, boolean unique) + throws IllegalStateException { if (config == null || configsMap == null) { return; } + if (unique) { // check duplicate + configsMap.values().forEach(c -> { + checkDuplicate(c, config); + }); + } + String key = getId(config); C existedConfig = configsMap.get(key); From ad3e6380af055fb82accf632a8fcc32aab65ef18 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 12 Aug 2019 17:39:27 +0800 Subject: [PATCH 35/55] Resolve the issues on ConfigManager --- .../DubboServiceProviderBootstrap.java | 2 +- .../dubbo/config/context/ConfigManager.java | 30 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) 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 15d162866f6..d094add304c 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 @@ -32,7 +32,7 @@ public static void main(String[] args) { // .registry("zookeeper", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service")) // .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry-type=service").build()) .protocol(builder -> builder.port(-1).name("dubbo")) - .protocol(builder -> builder.port(-1).name("hessian")) +// .protocol(builder -> builder.port(-1).name("hessian")) .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/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java index a7a37968ab2..0e4d610d394 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 @@ -41,7 +41,9 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; -import java.util.concurrent.locks.StampedLock; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; import static java.lang.Boolean.TRUE; @@ -96,7 +98,7 @@ public class ConfigManager { private final Map, Map> configsCache = newMap(); - private final StampedLock lock = new StampedLock(); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); public static ConfigManager getInstance() { return CONFIG_MANAGER; @@ -125,6 +127,9 @@ public void addConfig(AbstractConfig config) { } protected void addConfig(AbstractConfig config, boolean unique) { + if (config == null) { + return; + } Class configType = config.getClass(); write(() -> { Map configsMap = configsCache.computeIfAbsent(configType, type -> newMap()); @@ -151,7 +156,7 @@ protected C getConfig(Class configType) throws Ill return read(() -> { Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); int size = configsMap.size(); - if (size < 0) { + if (size < 1) { // throw new IllegalStateException("No such " + configType.getName() + " is found"); return null; } else if (size > 1) { @@ -397,13 +402,14 @@ private Collection getConfigIds(Class conf private V write(Callable callable) { V value = null; - long stamp = lock.writeLock(); + Lock writeLock = lock.writeLock(); try { + writeLock.lock(); value = callable.call(); } catch (Throwable e) { throw new RuntimeException(e); } finally { - lock.unlockWrite(stamp); + writeLock.unlock(); } return value; } @@ -417,25 +423,17 @@ private void write(Runnable runnable) { private V read(Callable callable) { - long stamp = lock.tryOptimisticRead(); - - boolean readLock = false; + Lock readLock = lock.readLock(); V value = null; try { - readLock = !lock.validate(stamp); - - if (readLock) { - stamp = lock.readLock(); - } + readLock.lock(); value = callable.call(); } catch (Throwable e) { throw new RuntimeException(e); } finally { - if (readLock) { - lock.unlockRead(stamp); - } + readLock.unlock(); } return value; From 07cf7b1a5c26ec65b1b5fb28a5a4dc0ff2208428 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Tue, 13 Aug 2019 10:18:31 +0800 Subject: [PATCH 36/55] Refactor and add test-cases for ConfigManager --- .../dubbo/bootstrap/DubboBootstrap.java | 10 +- .../DubboServiceConsumerBootstrap.java | 2 +- .../apache/dubbo/config/AbstractConfig.java | 3 +- .../dubbo/config/context/ConfigManager.java | 135 +++++++------ .../config/context/ConfigManagerTest.java | 186 +++++++++++++++++- 5 files changed, 263 insertions(+), 73 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 4f1daa16b5e..9de48a63218 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 @@ -51,9 +51,7 @@ import org.apache.dubbo.config.utils.ReferenceConfigCache; import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.event.EventListener; -import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.metadata.report.MetadataReportInstance; -import org.apache.dubbo.metadata.store.RemoteWritableMetadataService; import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory; import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceDiscovery; @@ -517,7 +515,7 @@ public DubboBootstrap start() { exportServices(); // Not only provider register and some services are exported - if (!onlyRegisterProvider && !configManager.getServiceConfigs().isEmpty()) { + if (!onlyRegisterProvider && !configManager.getServices().isEmpty()) { /** * export {@link MetadataService} */ @@ -718,7 +716,7 @@ private List exportMetadataService(ApplicationConfig applicationConfig, } private void exportServices() { - configManager.getServiceConfigs().forEach(this::exportServiceConfig); + configManager.getServices().forEach(this::exportServiceConfig); } public void exportServiceConfig(ServiceConfig serviceConfig) { @@ -729,7 +727,7 @@ private void referServices() { if (cache == null) { cache = ReferenceConfigCache.getCache(); } - configManager.getReferenceConfigs().forEach(cache::get); + configManager.getReferences().forEach(cache::get); } public boolean isOnlyRegisterProvider() { @@ -816,7 +814,7 @@ private void destroyProtocolConfigs() { } private void destroyReferenceConfigs() { - configManager.getReferenceConfigs().forEach(ReferenceConfig::destroy); + configManager.getReferences().forEach(ReferenceConfig::destroy); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s all ReferenceConfigs 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..760fbdcd1fd 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 @@ -41,7 +41,7 @@ public static void main(String[] args) throws Exception { ConfigManager configManager = ConfigManager.getInstance(); - ReferenceConfig referenceConfig = configManager.getReferenceConfig("ref"); + ReferenceConfig referenceConfig = configManager.getReference("ref"); EchoService echoService = referenceConfig.get(); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java index c1a7548585d..d729644992c 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -40,6 +40,7 @@ import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -638,7 +639,7 @@ public boolean equals(Object obj) { Method method2 = obj.getClass().getMethod(method1.getName(), method1.getParameterTypes()); Object value1 = method1.invoke(this, new Object[]{}); Object value2 = method2.invoke(obj, new Object[]{}); - if ((value1 != null && value2 != null) && !value1.equals(value2)) { + if (!Objects.equals(value1, value2)) { return false; } } catch (Exception e) { 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 0e4d610d394..69967409a8f 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 @@ -117,56 +117,6 @@ public Optional getApplication() { return ofNullable(getConfig(ApplicationConfig.class)); } - /** - * Add the dubbo {@link AbstractConfig config} - * - * @param config the dubbo {@link AbstractConfig config} - */ - public void addConfig(AbstractConfig config) { - addConfig(config, false); - } - - protected void addConfig(AbstractConfig config, boolean unique) { - if (config == null) { - return; - } - Class configType = config.getClass(); - write(() -> { - Map configsMap = configsCache.computeIfAbsent(configType, type -> newMap()); - addIfAbsent(config, configsMap, unique); - }); - } - - protected Map getConfigsMap(Class configType) { - return read(() -> (Map) configsCache.getOrDefault(configType, emptyMap())); - } - - protected Collection getConfigs(Class configType) { - return read(() -> getConfigsMap(configType).values()); - } - - protected C getConfig(Class configType, String id) { - return read(() -> { - Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); - return configsMap.get(id); - }); - } - - protected C getConfig(Class configType) throws IllegalStateException { - return read(() -> { - Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); - int size = configsMap.size(); - if (size < 1) { -// throw new IllegalStateException("No such " + configType.getName() + " is found"); - return null; - } else if (size > 1) { - throw new IllegalStateException("The expected single matching " + configType.getName() + " but found " + size + " instances"); - } else { - return configsMap.values().iterator().next(); - } - }); - } - // MonitorConfig correlative methods public void setMonitor(MonitorConfig monitor) { @@ -181,7 +131,6 @@ public Optional getMonitor() { public void setModule(ModuleConfig module) { addConfig(module, true); - } public Optional getModule() { @@ -234,6 +183,10 @@ public void addProvider(ProviderConfig providerConfig) { addConfig(providerConfig); } + public void addProviders(Iterable providerConfigs) { + providerConfigs.forEach(this::addProvider); + } + public Optional getProvider(String id) { return ofNullable(getConfig(ProviderConfig.class, id)); } @@ -252,6 +205,10 @@ public void addConsumer(ConsumerConfig consumerConfig) { addConfig(consumerConfig); } + public void addConsumers(Iterable consumerConfigs) { + consumerConfigs.forEach(this::addConsumer); + } + public Optional getConsumer(String id) { return ofNullable(getConfig(ConsumerConfig.class, id)); } @@ -341,11 +298,15 @@ public void addService(ServiceConfig serviceConfig) { addConfig(serviceConfig); } - public Collection getServiceConfigs() { + public void addServices(Iterable> serviceConfigs) { + serviceConfigs.forEach(this::addService); + } + + public Collection getServices() { return getConfigs(ServiceConfig.class); } - public ServiceConfig getServiceConfig(String id) { + public ServiceConfig getService(String id) { return getConfig(ServiceConfig.class, id); } @@ -355,11 +316,15 @@ public void addReference(ReferenceConfig referenceConfig) { addConfig(referenceConfig); } - public Collection getReferenceConfigs() { + public void addReferences(Iterable> referenceConfigs) { + referenceConfigs.forEach(this::addReference); + } + + public Collection getReferences() { return getConfigs(ReferenceConfig.class); } - public ReferenceConfig getReferenceConfig(String id) { + public ReferenceConfig getReference(String id) { return getConfig(ReferenceConfig.class, id); } @@ -393,7 +358,57 @@ public void clear() { }); } - private Collection getConfigIds(Class configType) { + /** + * Add the dubbo {@link AbstractConfig config} + * + * @param config the dubbo {@link AbstractConfig config} + */ + public void addConfig(AbstractConfig config) { + addConfig(config, false); + } + + protected void addConfig(AbstractConfig config, boolean unique) { + if (config == null) { + return; + } + Class configType = config.getClass(); + write(() -> { + Map configsMap = configsCache.computeIfAbsent(configType, type -> newMap()); + addIfAbsent(config, configsMap, unique); + }); + } + + protected Map getConfigsMap(Class configType) { + return read(() -> (Map) configsCache.getOrDefault(configType, emptyMap())); + } + + protected Collection getConfigs(Class configType) { + return read(() -> getConfigsMap(configType).values()); + } + + protected C getConfig(Class configType, String id) { + return read(() -> { + Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); + return configsMap.get(id); + }); + } + + protected C getConfig(Class configType) throws IllegalStateException { + return read(() -> { + Map configsMap = (Map) configsCache.getOrDefault(configType, emptyMap()); + int size = configsMap.size(); + if (size < 1) { +// throw new IllegalStateException("No such " + configType.getName() + " is found"); + return null; + } else if (size > 1) { + throw new IllegalStateException("The expected single matching " + configType.getName() + " but found " + size + " instances"); + } else { + return configsMap.values().iterator().next(); + } + }); + } + + protected Collection getConfigIds(Class configType) { return getConfigs(configType) .stream() .map(AbstractConfig::getId) @@ -406,8 +421,10 @@ private V write(Callable callable) { try { writeLock.lock(); value = callable.call(); + } catch (RuntimeException e) { + throw e; } catch (Throwable e) { - throw new RuntimeException(e); + throw new RuntimeException(e.getCause()); } finally { writeLock.unlock(); } @@ -421,12 +438,9 @@ private void write(Runnable runnable) { }); } - private V read(Callable callable) { Lock readLock = lock.readLock(); - V value = null; - try { readLock.lock(); value = callable.call(); @@ -435,7 +449,6 @@ private V read(Callable callable) { } finally { readLock.unlock(); } - return value; } 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 index 44e896d517d..41f5f3b83e2 100644 --- 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 @@ -17,15 +17,28 @@ package org.apache.dubbo.config.context; import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ConfigCenterConfig; +import org.apache.dubbo.config.ConsumerConfig; +import org.apache.dubbo.config.MetricsConfig; 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.ReferenceConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.ServiceConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.Collection; + +import static java.util.Arrays.asList; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -40,32 +53,197 @@ public class ConfigManagerTest { @BeforeEach public void init() { configManager.clear(); + } + + @Test + public void testDefaultValues() { + // assert single assertFalse(configManager.getApplication().isPresent()); assertFalse(configManager.getMonitor().isPresent()); - assertFalse(configManager.getMonitor().isPresent()); + assertFalse(configManager.getModule().isPresent()); + assertFalse(configManager.getMetrics().isPresent()); + + // providers and consumers + assertFalse(configManager.getDefaultProvider().isPresent()); + assertFalse(configManager.getDefaultConsumer().isPresent()); + assertTrue(configManager.getProviders().isEmpty()); + assertTrue(configManager.getConsumers().isEmpty()); + + // protocols + assertTrue(configManager.getProtocols().isEmpty()); + assertTrue(configManager.getDefaultProtocols().isEmpty()); + assertTrue(configManager.getProtocolIds().isEmpty()); + + // registries + assertTrue(configManager.getRegistries().isEmpty()); + assertTrue(configManager.getDefaultRegistries().isEmpty()); + assertTrue(configManager.getRegistryIds().isEmpty()); + + // services and references + assertTrue(configManager.getServices().isEmpty()); + assertTrue(configManager.getReferences().isEmpty()); + + // config centers + assertTrue(configManager.getConfigCenters().isEmpty()); + + // metadata + assertTrue(configManager.getMetadataConfigs().isEmpty()); } + // Test ApplicationConfig correlative methods @Test public void testApplicationConfig() { - ApplicationConfig applicationConfig = new ApplicationConfig(); - configManager.setApplication(applicationConfig); + ApplicationConfig config = new ApplicationConfig(); + configManager.setApplication(config); assertTrue(configManager.getApplication().isPresent()); - assertEquals(applicationConfig, configManager.getApplication().get()); + assertEquals(config, configManager.getApplication().get()); + assertThrows(IllegalStateException.class, () -> { + configManager.setApplication(new ApplicationConfig("test")); + }); } + // Test MonitorConfig correlative methods @Test public void testMonitorConfig() { MonitorConfig monitorConfig = new MonitorConfig(); + monitorConfig.setGroup("test"); configManager.setMonitor(monitorConfig); assertTrue(configManager.getMonitor().isPresent()); assertEquals(monitorConfig, configManager.getMonitor().get()); + assertThrows(IllegalStateException.class, () -> { + configManager.setMonitor(new MonitorConfig()); + }); } + // Test MonitorConfig correlative methods @Test public void tesModuleConfig() { ModuleConfig config = new ModuleConfig(); configManager.setModule(config); assertTrue(configManager.getModule().isPresent()); assertEquals(config, configManager.getModule().get()); + assertThrows(IllegalStateException.class, () -> { + configManager.setModule(new ModuleConfig("test")); + }); + } + + // Test MetricsConfig correlative methods + @Test + public void tesMetricsConfig() { + MetricsConfig config = new MetricsConfig(); + configManager.setMetrics(config); + assertTrue(configManager.getMetrics().isPresent()); + assertEquals(config, configManager.getMetrics().get()); + assertThrows(IllegalStateException.class, () -> { + MetricsConfig metricsConfig = new MetricsConfig(); + metricsConfig.setPort("101"); + configManager.setMetrics(metricsConfig); + }); + } + + // Test ProviderConfig correlative methods + @Test + public void testProviderConfig() { + ProviderConfig config = new ProviderConfig(); + configManager.addProviders(asList(config, null)); + Collection configs = configManager.getProviders(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + assertFalse(configManager.getDefaultProvider().isPresent()); + + config.setId(DEFAULT_KEY); + configManager.addProvider(config); + assertTrue(configManager.getDefaultProvider().isPresent()); + configs = configManager.getProviders(); + assertEquals(2, configs.size()); + } + + // Test ConsumerConfig correlative methods + @Test + public void testConsumerConfig() { + ConsumerConfig config = new ConsumerConfig(); + configManager.addConsumers(asList(config, null)); + Collection configs = configManager.getConsumers(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + assertFalse(configManager.getDefaultConsumer().isPresent()); + + config.setId(DEFAULT_KEY); + configManager.addConsumer(config); + assertTrue(configManager.getDefaultConsumer().isPresent()); + configs = configManager.getConsumers(); + assertEquals(2, configs.size()); + } + + // Test ProtocolConfig correlative methods + @Test + public void testProtocolConfig() { + ProtocolConfig config = new ProtocolConfig(); + configManager.addProtocols(asList(config, null)); + Collection configs = configManager.getProtocols(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + assertFalse(configManager.getDefaultProtocols().isEmpty()); + } + + // Test RegistryConfig correlative methods + @Test + public void testRegistryConfig() { + RegistryConfig config = new RegistryConfig(); + configManager.addRegistries(asList(config, null)); + Collection configs = configManager.getRegistries(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + assertFalse(configManager.getDefaultRegistries().isEmpty()); + } + + // Test ServiceConfig correlative methods + @Test + public void testServiceConfig() { + ServiceConfig config = new ServiceConfig(); + config.setId("test"); + configManager.addServices(asList(config, null)); + Collection configs = configManager.getServices(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + assertEquals(config, configManager.getService("test")); + } + + // Test ReferenceConfig correlative methods + @Test + public void testReferenceConfig() { + ReferenceConfig config = new ReferenceConfig(); + config.setId("test"); + configManager.addReferences(asList(config, null)); + Collection configs = configManager.getReferences(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + assertEquals(config, configManager.getReference("test")); + } + + // Test ConfigCenterConfig correlative methods + @Test + public void testConfigCenterConfig() { + ConfigCenterConfig config = new ConfigCenterConfig(); + configManager.addConfigCenters(asList(config, null)); + Collection configs = configManager.getConfigCenters(); + assertEquals(1, configs.size()); + assertEquals(config, configs.iterator().next()); + } + + @Test + public void testAddConfig() { + configManager.addConfig(new ApplicationConfig()); + configManager.addConfig(new ProviderConfig()); + configManager.addConfig(new ProtocolConfig()); + + assertTrue(configManager.getApplication().isPresent()); + assertFalse(configManager.getProviders().isEmpty()); + assertFalse(configManager.getProtocols().isEmpty()); + } + + @Test + public void testRefreshAll() { + configManager.refreshAll(); } } From 51d2be4502efc1abdb31fd71ecdd1629a1d36f85 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Tue, 13 Aug 2019 18:27:40 +0800 Subject: [PATCH 37/55] Polish apache/dubbo#4774 : [Feature] Dubbo Cloud Native - To Support in Spring --- .../dubbo/bootstrap/DubboBootstrap.java | 93 +++++++------- .../org.apache.dubbo.common.context.Lifecycle | 1 + .../CompositeDynamicConfiguration.java | 4 +- .../dubbo/common/context/Lifecycle.java | 78 ++++++++++++ ...ifecycleComponentsApplicationListener.java | 115 ++++++++++++++++++ .../context/annotation/EnableDubbo.java | 1 + .../annotation/EnableDubboLifecycle.java | 42 +++++++ 7 files changed, 282 insertions(+), 52 deletions(-) create mode 100644 dubbo-bootstrap/src/main/resources/META-INF/services/org.apache.dubbo.common.context.Lifecycle create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentsApplicationListener.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboLifecycle.java 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 9de48a63218..695cf8891d5 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 @@ -20,11 +20,11 @@ import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration; +import org.apache.dubbo.common.context.Lifecycle; 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.config.AbstractConfig; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ConfigCenterConfig; import org.apache.dubbo.config.ConsumerConfig; @@ -38,7 +38,6 @@ import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.ServiceConfig; -import org.apache.dubbo.config.builders.AbstractBuilder; import org.apache.dubbo.config.builders.ApplicationBuilder; import org.apache.dubbo.config.builders.ConsumerBuilder; import org.apache.dubbo.config.builders.ProtocolBuilder; @@ -64,7 +63,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; @@ -90,7 +88,7 @@ * * @since 2.7.4 */ -public class DubboBootstrap { +public class DubboBootstrap implements Lifecycle { public static final String DEFAULT_REGISTRY_ID = "REGISTRY#DEFAULT"; @@ -409,25 +407,26 @@ public DubboBootstrap cache(ReferenceConfigCache cache) { /** * Initialize */ - public void init() { + public DubboBootstrap initialize() { + if (!isInitialized()) { - if (isInitialized()) { - return; - } + startConfigCenter(); - startConfigCenter(); + startMetadataReport(); - startMetadataReport(); + loadRemoteConfigs(); - loadRemoteConfigs(); + useRegistryAsConfigCenterIfNecessary(); - useRegistryAsConfigCenterIfNecessary(); + initialized = true; - initialized = true; + if (logger.isInfoEnabled()) { + logger.info(NAME + " has been initialized!"); + } - if (logger.isInfoEnabled()) { - logger.info(NAME + " has been initialized!"); } + + return this; } private void loadRemoteConfigs() { @@ -505,12 +504,12 @@ private Collection getServiceDiscoveries() { /** * Start the bootstrap */ + @Override public DubboBootstrap start() { - + if (!isInitialized()) { + initialize(); + } if (!isStarted()) { - if (!isInitialized()) { - init(); - } exportServices(); @@ -574,32 +573,26 @@ public DubboBootstrap await() { /** * Stop the bootstrap */ - public void stop() { - - if (!isInitialized() || !isStarted()) { - return; + @Override + public DubboBootstrap stop() { + if (isInitialized() && isStarted()) { + unregisterServiceInstance(); + unexportServices(); + started = false; } - - unregisterServiceInstance(); - - destroy(); - - clear(); - - release(); - - shutdown(); + return this; } + @Override public boolean isInitialized() { return initialized; } + @Override public boolean isStarted() { return started; } - /* serve for builder apis, begin */ private ApplicationBuilder createApplicationBuilder(String name) { return new ApplicationBuilder().name(name); @@ -716,11 +709,11 @@ private List exportMetadataService(ApplicationConfig applicationConfig, } private void exportServices() { - configManager.getServices().forEach(this::exportServiceConfig); + configManager.getServices().forEach(ServiceConfig::export); } - public void exportServiceConfig(ServiceConfig serviceConfig) { - serviceConfig.export(); + private void unexportServices() { + configManager.getServices().forEach(ServiceConfig::unexport); } private void referServices() { @@ -798,22 +791,29 @@ private ServiceInstance initServiceInstance(String serviceName, String host, int return this.serviceInstance; } - private void destroy() { + public void destroy() { - destroyProtocolConfigs(); + stop(); - destroyReferenceConfigs(); + destroyProtocols(); + destroyReferences(); + + clear(); + + release(); + + shutdown(); } - private void destroyProtocolConfigs() { + private void destroyProtocols() { configManager.getProtocols().forEach(ProtocolConfig::destroy); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s all ProtocolConfigs have been destroyed."); } } - private void destroyReferenceConfigs() { + private void destroyReferences() { configManager.getReferences().forEach(ReferenceConfig::destroy); if (logger.isDebugEnabled()) { logger.debug(NAME + "'s all ReferenceConfigs have been destroyed."); @@ -857,13 +857,4 @@ private void executeMutually(Runnable runnable) { lock.unlock(); } } - - private static List buildConfigs(Map map) { - List configs = new ArrayList<>(); - map.entrySet().forEach(entry -> { - configs.add((C) entry.getValue().build()); - }); - return configs; - } } diff --git a/dubbo-bootstrap/src/main/resources/META-INF/services/org.apache.dubbo.common.context.Lifecycle b/dubbo-bootstrap/src/main/resources/META-INF/services/org.apache.dubbo.common.context.Lifecycle new file mode 100644 index 00000000000..5c5dcfd5276 --- /dev/null +++ b/dubbo-bootstrap/src/main/resources/META-INF/services/org.apache.dubbo.common.context.Lifecycle @@ -0,0 +1 @@ +org.apache.dubbo.bootstrap.DubboBootstrap \ No newline at end of file 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 16484e7fbc9..8310827a9d9 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 @@ -36,7 +36,9 @@ public class CompositeDynamicConfiguration implements DynamicConfiguration { private Set configurations = new HashSet<>(); public void addConfiguration(DynamicConfiguration configuration) { - this.configurations.add(configuration); + if (configuration != null) { + this.configurations.add(configuration); + } } @Override diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java b/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java new file mode 100644 index 00000000000..672ec2cd22b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java @@ -0,0 +1,78 @@ +/* + * 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.context; + +/** + * The Lifecycle of Dubbo component + * + * @since 2.7.4 + */ +public interface Lifecycle { + + /** + * Initialize the component before {@link #start() start} + * + * @return current {@link Lifecycle} + * @throws IllegalStateException + */ + Lifecycle initialize() throws IllegalStateException; + + /** + * Initialized or not + * + * @return if initialized, return true, or false + */ + boolean isInitialized(); + + /** + * Start the component + * + * @return current {@link Lifecycle} + * @throws IllegalStateException + */ + Lifecycle start() throws IllegalStateException; + + /** + * The component is started or not + * + * @return if started, return true, or false + */ + boolean isStarted(); + + /** + * Stop the component + * + * @return current {@link Lifecycle} + */ + Lifecycle stop() throws IllegalStateException; + + /** + * The component is stopped or not + * + * @return if stopped, return true, or false + */ + default boolean isStopped() { + return !isStarted(); + } + + /** + * Destroy the component + * + * @throws IllegalStateException + */ + void destroy() throws IllegalStateException; +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentsApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentsApplicationListener.java new file mode 100644 index 00000000000..19365d7c572 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentsApplicationListener.java @@ -0,0 +1,115 @@ +/* + * 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; + + +import org.apache.dubbo.common.context.Lifecycle; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ApplicationContextEvent; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.SmartApplicationListener; + +import java.util.LinkedList; +import java.util.List; +import java.util.ServiceLoader; + +import static java.util.Collections.emptyList; +import static java.util.ServiceLoader.load; +import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; + +/** + * A {@link ApplicationListener listener} for the {@link Lifecycle Dubbo Lifecycle} components + * + * @see {@link Lifecycle Dubbo Lifecycle} + * @see SmartApplicationListener + * @since 2.7.4 + */ +public class DubboLifecycleComponentsApplicationListener implements ApplicationListener { + + private List lifecycleComponents = emptyList(); + + @Override + public void onApplicationEvent(ApplicationEvent event) { + + if (!supportsEvent(event)) { + return; + } + + if (event instanceof ContextRefreshedEvent) { + onContextRefreshedEvent((ContextRefreshedEvent) event); + } else if (event instanceof ContextClosedEvent) { + onContextClosedEvent((ContextClosedEvent) event); + } + } + + protected void onContextRefreshedEvent(ContextRefreshedEvent event) { + initLifecycleComponents(event); + startLifecycleComponents(); + } + + protected void onContextClosedEvent(ContextClosedEvent event) { + destroyLifecycleComponents(); + } + + private void initLifecycleComponents(ContextRefreshedEvent event) { + ApplicationContext context = event.getApplicationContext(); + ClassLoader classLoader = context.getClassLoader(); + lifecycleComponents = new LinkedList<>(); + // load the instances of Lifecycle from ServiceLoader + loadLifecycleComponents(lifecycleComponents, classLoader); + // load the Beans of Lifecycle from ApplicationContext + loadLifecycleComponents(lifecycleComponents, context); + } + + private void loadLifecycleComponents(List lifecycleComponents, ClassLoader classLoader) { + ServiceLoader serviceLoader = load(Lifecycle.class, classLoader); + serviceLoader.forEach(lifecycleComponents::add); + } + + private void loadLifecycleComponents(List lifecycleComponents, ApplicationContext context) { + lifecycleComponents.addAll(beansOfTypeIncludingAncestors(context, Lifecycle.class).values()); + } + + private void startLifecycleComponents() { + lifecycleComponents.forEach(Lifecycle::start); + } + + private void destroyLifecycleComponents() { + lifecycleComponents.forEach(Lifecycle::destroy); + } + + /** + * the specified {@link ApplicationEvent event} must be {@link ApplicationContextEvent} and + * its correlative {@link ApplicationContext} must be root + * + * @param event + * @return + */ + private boolean supportsEvent(ApplicationEvent event) { + return event instanceof ApplicationContextEvent && + isRootApplicationContext((ApplicationContextEvent) event); + } + + + private boolean isRootApplicationContext(ApplicationContextEvent event) { + return event.getApplicationContext().getParent() == null; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubbo.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubbo.java index 706e288597e..e07c5351f0a 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubbo.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubbo.java @@ -43,6 +43,7 @@ @Documented @EnableDubboConfig @DubboComponentScan +@EnableDubboLifecycle public @interface EnableDubbo { /** diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboLifecycle.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboLifecycle.java new file mode 100644 index 00000000000..0abd18e405b --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboLifecycle.java @@ -0,0 +1,42 @@ +/* + * 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.annotation; + +import org.apache.dubbo.config.spring.context.DubboLifecycleComponentsApplicationListener; + +import org.springframework.context.Lifecycle; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Enables Dubbo {@link Lifecycle} components + * + * @since 2.7.4 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +@Import(DubboLifecycleComponentsApplicationListener.class) +public @interface EnableDubboLifecycle { +} From c284dad7614b804dbff4fa344b10866ec81a7dd1 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Tue, 13 Aug 2019 20:29:10 +0800 Subject: [PATCH 38/55] Polish apache/dubbo#4808 : [Feature] Add the registered/unregistered event mechanism ShutdownHook --- .../dubbo/config/DubboShutdownHook.java | 17 +++++-- .../DubboShutdownHookRegisteredEvent.java | 46 +++++++++++++++++++ .../DubboShutdownHookUnregisteredEvent.java | 45 ++++++++++++++++++ 3 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookRegisteredEvent.java create mode 100644 dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookUnregisteredEvent.java diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java index 19b97c15fc7..15239bcb12e 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java @@ -20,6 +20,9 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.event.DubboServiceDestroyedEvent; +import org.apache.dubbo.config.event.DubboShutdownHookRegisteredEvent; +import org.apache.dubbo.config.event.DubboShutdownHookUnregisteredEvent; +import org.apache.dubbo.event.Event; import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.registry.support.AbstractRegistryFactory; import org.apache.dubbo.rpc.Protocol; @@ -69,7 +72,9 @@ public void run() { */ public void register() { if (!registered.get() && registered.compareAndSet(false, true)) { - Runtime.getRuntime().addShutdownHook(getDubboShutdownHook()); + DubboShutdownHook dubboShutdownHook = getDubboShutdownHook(); + Runtime.getRuntime().addShutdownHook(dubboShutdownHook); + dispatch(new DubboShutdownHookRegisteredEvent(dubboShutdownHook)); } } @@ -78,7 +83,9 @@ public void register() { */ public void unregister() { if (registered.get() && registered.compareAndSet(true, false)) { - Runtime.getRuntime().removeShutdownHook(getDubboShutdownHook()); + DubboShutdownHook dubboShutdownHook = getDubboShutdownHook(); + Runtime.getRuntime().removeShutdownHook(dubboShutdownHook); + dispatch(new DubboShutdownHookUnregisteredEvent(dubboShutdownHook)); } } @@ -94,7 +101,11 @@ public void doDestroy() { // destroy all the protocols destroyProtocols(); // dispatch the DubboDestroyedEvent @since 2.7.4 - eventDispatcher.dispatch(new DubboServiceDestroyedEvent(this)); + dispatch(new DubboServiceDestroyedEvent(this)); + } + + private void dispatch(Event event) { + eventDispatcher.dispatch(event); } /** diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookRegisteredEvent.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookRegisteredEvent.java new file mode 100644 index 00000000000..6eca86268d8 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookRegisteredEvent.java @@ -0,0 +1,46 @@ +/* + * 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.event; + +import org.apache.dubbo.config.DubboShutdownHook; +import org.apache.dubbo.event.Event; + +/** + * An event raised when the {@link DubboShutdownHook} {@link java.lang.Runtime#addShutdownHook(Thread) registered} on + * {@link ApplicationShutdownHooks JVM ShutdownHooks} + * + * @see DubboShutdownHook + * @see ApplicationShutdownHooks + * @since 2.7.4 + */ +public class DubboShutdownHookRegisteredEvent extends Event { + + /** + * Constructs a prototypical Event. + * + * @param dubboShutdownHook The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + public DubboShutdownHookRegisteredEvent(DubboShutdownHook dubboShutdownHook) { + super(dubboShutdownHook); + } + + public DubboShutdownHook getDubboShutdownHook() { + return (DubboShutdownHook) getSource(); + } + +} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookUnregisteredEvent.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookUnregisteredEvent.java new file mode 100644 index 00000000000..621d7a20314 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/DubboShutdownHookUnregisteredEvent.java @@ -0,0 +1,45 @@ +/* + * 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.event; + +import org.apache.dubbo.config.DubboShutdownHook; +import org.apache.dubbo.event.Event; + +/** + * An event raised when the {@link DubboShutdownHook} {@link Runtime#removeShutdownHook(Thread) unregistered} on + * {@link ApplicationShutdownHooks JVM ShutdownHooks} + * + * @see DubboShutdownHook + * @see ApplicationShutdownHooks + * @since 2.7.4 + */ +public class DubboShutdownHookUnregisteredEvent extends Event { + + /** + * Constructs a prototypical Event. + * + * @param dubboShutdownHook The object on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + public DubboShutdownHookUnregisteredEvent(DubboShutdownHook dubboShutdownHook) { + super(dubboShutdownHook); + } + + public DubboShutdownHook getDubboShutdownHook() { + return (DubboShutdownHook) getSource(); + } +} From 3d84c35dbcd5952dd3524df4fcac5af70e1e024f Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 14 Aug 2019 01:46:39 +0800 Subject: [PATCH 39/55] Polish apache/dubbo#4807 : [Feature] Add the callback mechanism ShutdownHook #4807 --- .../apache/dubbo/common/lang/Prioritized.java | 52 ++++++++++++++++ .../common/lang/ShutdownHookCallback.java | 32 ++++++++++ .../dubbo/config/DubboShutdownHook.java | 49 +++++++++++++++ .../dubbo/config/DubboShutdownHookTest.java | 62 +++++++++++++++++++ ...che.dubbo.common.lang.ShutdownHookCallback | 1 + 5 files changed, 196 insertions(+) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java create mode 100644 dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboShutdownHookTest.java create mode 100644 dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.common.lang.ShutdownHookCallback diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java new file mode 100644 index 00000000000..d8a110a7ad3 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java @@ -0,0 +1,52 @@ +/* + * 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.lang; + +import static java.lang.Integer.compare; + +/** + * {@code Prioritized} interface can be implemented by objects that + * should be sorted, for example the tasks in executable queue. + * + * @since 2.7.4 + */ +public interface Prioritized extends Comparable { + + /** + * The maximum priority + */ + int MAX_PRIORITY = Integer.MIN_VALUE; + + /** + * The minimum priority + */ + int MIN_PRIORITY = Integer.MAX_VALUE; + + /** + * Get the priority + * + * @return the default is {@link #MIN_PRIORITY minimum one} + */ + default int getPriority() { + return MIN_PRIORITY; + } + + @Override + default int compareTo(Prioritized that) { + return compare(this.getPriority(), that.getPriority()); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java new file mode 100644 index 00000000000..5bac3a06634 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common.lang; + +/** + * Dubbo ShutdownHook callback interface + * + * @since 2.7.4 + */ +public interface ShutdownHookCallback extends Prioritized { + + /** + * Callback execution + * + * @throws Throwable if met with some errors + */ + void callback() throws Throwable; +} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java index 15239bcb12e..321649d7b0d 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java @@ -17,6 +17,7 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.lang.ShutdownHookCallback; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.event.DubboServiceDestroyedEvent; @@ -27,8 +28,14 @@ import org.apache.dubbo.registry.support.AbstractRegistryFactory; import org.apache.dubbo.rpc.Protocol; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import static java.util.Collections.sort; +import static java.util.ServiceLoader.load; + /** * The shutdown hook thread to do the clean up stuff. * This is a singleton in order to ensure there is only one shutdown hook registered. @@ -40,10 +47,12 @@ public class DubboShutdownHook extends Thread { private static final Logger logger = LoggerFactory.getLogger(DubboShutdownHook.class); private static final DubboShutdownHook DUBBO_SHUTDOWN_HOOK = new DubboShutdownHook("DubboShutdownHook"); + /** * Has it already been registered or not? */ private final AtomicBoolean registered = new AtomicBoolean(false); + /** * Has it already been destroyed or not? */ @@ -51,8 +60,16 @@ public class DubboShutdownHook extends Thread { private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + private final List callbacks = new LinkedList<>(); + private DubboShutdownHook(String name) { super(name); + loadCallbacks(); + } + + public DubboShutdownHook addCallback(ShutdownHookCallback callback) { + this.callbacks.add(callback); + return this; } public static DubboShutdownHook getDubboShutdownHook() { @@ -64,9 +81,41 @@ public void run() { if (logger.isInfoEnabled()) { logger.info("Run shutdown hook now."); } + callback(); doDestroy(); } + /** + * For testing purpose + */ + Collection getCallbacks() { + sort(callbacks); + return callbacks; + } + + /** + * For testing purpose + */ + void clear() { + callbacks.clear(); + } + + private void loadCallbacks() { + load(ShutdownHookCallback.class).forEach(callbacks::add); + } + + private void callback() { + getCallbacks().forEach(callback -> { + try { + callback.callback(); + } catch (Throwable e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } + }); + } + /** * Register the ShutdownHook */ diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboShutdownHookTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboShutdownHookTest.java new file mode 100644 index 00000000000..6142ce8177d --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboShutdownHookTest.java @@ -0,0 +1,62 @@ +/* + * 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; + +import org.apache.dubbo.common.lang.ShutdownHookCallback; +import org.apache.dubbo.event.EventDispatcher; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link DubboShutdownHook} Test + * + * @since 2.7.4 + */ +public class DubboShutdownHookTest implements ShutdownHookCallback { + + private final DubboShutdownHook dubboShutdownHook = DubboShutdownHook.getDubboShutdownHook(); + + private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + + + @BeforeEach + public void before() { + + } + + @AfterEach + public void after() { + eventDispatcher.removeAllEventListeners(); + dubboShutdownHook.clear(); + } + + @Test + public void testCallback() { + assertEquals(this.getClass(), dubboShutdownHook.getCallbacks().iterator().next().getClass()); + dubboShutdownHook.addCallback(this); + assertEquals(2, dubboShutdownHook.getCallbacks().size()); + } + + @Override + public void callback() throws Throwable { + + } +} diff --git a/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.common.lang.ShutdownHookCallback b/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.common.lang.ShutdownHookCallback new file mode 100644 index 00000000000..8cad7581a4a --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.common.lang.ShutdownHookCallback @@ -0,0 +1 @@ +org.apache.dubbo.config.DubboShutdownHookTest \ No newline at end of file From 21bcfaa2611b6a5ede273f988e24d283265caaec Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 14 Aug 2019 01:58:49 +0800 Subject: [PATCH 40/55] Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer --- .../org/apache/dubbo/event/EventListener.java | 17 +++++------------ .../apache/dubbo/event/EchoEventListener2.java | 3 +-- .../client/ServiceInstanceCustomizer.java | 3 ++- .../CustomizableServiceInstanceListener.java | 15 +++++++-------- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/dubbo-event/src/main/java/org/apache/dubbo/event/EventListener.java b/dubbo-event/src/main/java/org/apache/dubbo/event/EventListener.java index edc0475fb73..2d6d4d301c0 100644 --- a/dubbo-event/src/main/java/org/apache/dubbo/event/EventListener.java +++ b/dubbo-event/src/main/java/org/apache/dubbo/event/EventListener.java @@ -16,11 +16,12 @@ */ package org.apache.dubbo.event; +import org.apache.dubbo.common.lang.Prioritized; + import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Objects; -import static java.lang.Integer.compare; import static org.apache.dubbo.common.utils.ReflectUtils.findParameterizedTypes; /** @@ -36,7 +37,7 @@ * @since 2.7.4 */ @FunctionalInterface -public interface EventListener extends java.util.EventListener, Comparable> { +public interface EventListener extends java.util.EventListener, Prioritized { /** * Handle a {@link Event Dubbo Event} when it's be published @@ -50,18 +51,10 @@ public interface EventListener extends java.util.EventListener, * * @return the value is more greater, the priority is more lower. * {@link Integer#MIN_VALUE} indicates the highest priority. The default value is {@link Integer#MAX_VALUE}. - * The comparison rule , refer to {@link #compareTo(EventListener)}. - * @see #compareTo(EventListener) - * @see Integer#MAX_VALUE - * @see Integer#MIN_VALUE + * The comparison rule , refer to {@link #compareTo}. */ default int getPriority() { - return Integer.MAX_VALUE; - } - - @Override - default int compareTo(EventListener another) { - return compare(this.getPriority(), another.getPriority()); + return MIN_PRIORITY; } /** diff --git a/dubbo-event/src/test/java/org/apache/dubbo/event/EchoEventListener2.java b/dubbo-event/src/test/java/org/apache/dubbo/event/EchoEventListener2.java index a6da23c57c5..f9b291e0d9d 100644 --- a/dubbo-event/src/test/java/org/apache/dubbo/event/EchoEventListener2.java +++ b/dubbo-event/src/test/java/org/apache/dubbo/event/EchoEventListener2.java @@ -25,8 +25,7 @@ * * @since 2.7.4 */ -public class EchoEventListener2 extends Vector> implements Serializable, Comparable>, - EventListener { +public class EchoEventListener2 extends Vector> implements Serializable, EventListener { private AbstractEventListener delegate = new AbstractEventListener() { @Override diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java index f198b0662b1..eefbc42e03d 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.registry.client; +import org.apache.dubbo.common.lang.Prioritized; import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; import org.apache.dubbo.registry.client.event.listener.CustomizableServiceInstanceListener; @@ -27,7 +28,7 @@ * @see ServiceInstance#getMetadata() * @since 2.7.4 */ -public interface ServiceInstanceCustomizer { +public interface ServiceInstanceCustomizer extends Prioritized { /** * Customizes {@link ServiceInstance the service instance} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java index ab22f9ac06b..1a823b867c8 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java @@ -21,10 +21,10 @@ import org.apache.dubbo.registry.client.ServiceInstanceCustomizer; import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; -import java.util.Iterator; import java.util.ServiceLoader; import static java.util.ServiceLoader.load; +import static java.util.stream.StreamSupport.stream; /** @@ -43,12 +43,11 @@ public void onEvent(ServiceInstancePreRegisteredEvent event) { ServiceLoader customizers = load(ServiceInstanceCustomizer.class); - Iterator iterator = customizers.iterator(); - - while (iterator.hasNext()) { - ServiceInstanceCustomizer customizer = iterator.next(); - // customizes - customizer.customize(event.getServiceInstance()); - } + stream(customizers.spliterator(), false) + .sorted() + .forEach(customizer -> { + // customizes + customizer.customize(event.getServiceInstance()); + }); } } From 63a315c0bd223f05e6e0b22b577f8dbeb90921dd Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 14 Aug 2019 10:35:13 +0800 Subject: [PATCH 41/55] Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components --- .../apache/dubbo/common/lang/Prioritized.java | 7 ++ .../common/utils/DubboServiceLoader.java | 101 ++++++++++++++++++ .../dubbo/event/AbstractEventDispatcher.java | 31 +++--- .../CustomizableServiceInstanceListener.java | 16 +-- 4 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java index d8a110a7ad3..a196d740ba1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java @@ -16,6 +16,8 @@ */ package org.apache.dubbo.common.lang; +import java.util.Comparator; + import static java.lang.Integer.compare; /** @@ -26,6 +28,11 @@ */ public interface Prioritized extends Comparable { + /** + * The {@link Comparator} of {@link Prioritized} + */ + Comparator COMPARATOR = (a, b) -> a.compareTo(b); + /** * The maximum priority */ diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java new file mode 100644 index 00000000000..2f48491478c --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java @@ -0,0 +1,101 @@ +/* + * 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.utils; + +import org.apache.dubbo.common.lang.Prioritized; + +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.StreamSupport.stream; +import static org.apache.dubbo.common.extension.support.ActivateComparator.COMPARATOR; + +/** + * An extension class of {@link ServiceLoader} to help the ease for use of Dubbo services/components + * + * @see ServiceLoader + * @see Prioritized + * @since 2.7.4 + */ +public class DubboServiceLoader { + + /** + * Load a {@link Stream stream} of services by the specified {@link Class type} and {@link ClassLoader} + * + * @param serviceClass {@link Class Service class} + * @param classLoader {@link ClassLoader} + * @param {@link Class Service type} + * @return the {@link Stream} of services that has been sorted by {@link Prioritized#COMPARATOR} + * @throws NullPointerException if serviceClass is null + */ + public static Stream load(Class serviceClass, ClassLoader classLoader) throws NullPointerException { + if (serviceClass == null) { + throw new NullPointerException("The serviceClass must not be null"); + } + + ClassLoader actualClassLoader = classLoader; + if (actualClassLoader == null) { + actualClassLoader = DubboServiceLoader.class.getClassLoader(); + } + + ServiceLoader serviceLoader = ServiceLoader.load(serviceClass, actualClassLoader); + + return stream(serviceLoader.spliterator(), false).sorted(COMPARATOR); + } + + /** + * Load a {@link Stream stream} of services by the specified {@link Class type} under + * {@link Thread#getContextClassLoader() the current thread context ClassLoader} + * + * @param serviceClass {@link Class Service class} + * @param {@link Class Service type} + * @return the {@link Stream} of services that has been sorted by {@link Prioritized#COMPARATOR} + * @throws NullPointerException if serviceClass is null + */ + public static Stream load(Class serviceClass) throws NullPointerException { + return load(serviceClass, Thread.currentThread().getContextClassLoader()); + } + + /** + * Load a {@link List list} of services by the specified {@link Class type} and {@link ClassLoader} + * + * @param serviceClass {@link Class Service class} + * @param classLoader {@link ClassLoader} + * @param {@link Class Service type} + * @return the {@link List list} of services that has been sorted by {@link Prioritized#COMPARATOR} + * @throws NullPointerException + */ + public static List loadServices(Class serviceClass, ClassLoader classLoader) throws NullPointerException { + return Collections.unmodifiableList(load(serviceClass, classLoader).collect(toList())); + } + + /** + * Load a {@link List list} of services by the specified {@link Class type} under + * {@link Thread#getContextClassLoader() the current thread context ClassLoader} + * + * @param serviceClass {@link Class Service class} + * @param {@link Class Service type} + * @return the {@link List list} of services that has been sorted by {@link Prioritized#COMPARATOR} + * @throws NullPointerException + */ + public static List loadServices(Class serviceClass) throws NullPointerException { + return loadServices(serviceClass, Thread.currentThread().getContextClassLoader()); + } +} diff --git a/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java b/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java index add8f61cd98..a2182ebe3c6 100644 --- a/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java +++ b/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java @@ -25,6 +25,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; import static java.util.Collections.sort; import static java.util.Collections.unmodifiableList; @@ -81,18 +83,25 @@ public void removeEventListener(EventListener listener) throws NullPointerExc public List> getAllEventListeners() { List> listeners = new LinkedList<>(); - listenersCache + sortedListeners().forEach(listener -> { + addIfAbsent(listeners, listener); + }); + + return unmodifiableList(listeners); + } + + protected Stream sortedListeners() { + return sortedListeners(e -> true); + } + + protected Stream sortedListeners(Predicate, List>> predicate) { + return listenersCache .entrySet() .stream() + .filter(predicate) .map(Map.Entry::getValue) .flatMap(Collection::stream) - .forEach(listener -> { - addIfAbsent(listeners, listener); - }); - - sort((List) listeners); - - return unmodifiableList(listeners); + .sorted(); } private void addIfAbsent(Collection collection, E element) { @@ -108,11 +117,7 @@ public void dispatch(Event event) { // execute in sequential or parallel execution model executor.execute(() -> { - listenersCache.entrySet() - .stream() - .filter(entry -> entry.getKey().isAssignableFrom(event.getClass())) - .map(Map.Entry::getValue) - .flatMap(Collection::stream) + sortedListeners(entry -> entry.getKey().isAssignableFrom(event.getClass())) .forEach(listener -> { listener.onEvent(event); }); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java index 1a823b867c8..60bc23c117a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java @@ -23,8 +23,7 @@ import java.util.ServiceLoader; -import static java.util.ServiceLoader.load; -import static java.util.stream.StreamSupport.stream; +import static org.apache.dubbo.common.utils.DubboServiceLoader.load; /** @@ -40,14 +39,9 @@ public class CustomizableServiceInstanceListener implements EventListener customizers = load(ServiceInstanceCustomizer.class); - - stream(customizers.spliterator(), false) - .sorted() - .forEach(customizer -> { - // customizes - customizer.customize(event.getServiceInstance()); - }); + load(ServiceInstanceCustomizer.class).forEach(customizer -> { + // customizes + customizer.customize(event.getServiceInstance()); + }); } } From 741321c2eaadb6ea04453ff579588b878f4bbdb6 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Wed, 14 Aug 2019 11:26:22 +0800 Subject: [PATCH 42/55] Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components --- .../apache/dubbo/common/lang/Prioritized.java | 14 +- .../common/utils/DubboServiceLoader.java | 3 +- .../dubbo/common/lang/PrioritizedTest.java | 125 ++++++++++++++++++ 3 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 dubbo-common/src/test/java/org/apache/dubbo/common/lang/PrioritizedTest.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java index a196d740ba1..b25ff48e62a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java @@ -31,7 +31,19 @@ public interface Prioritized extends Comparable { /** * The {@link Comparator} of {@link Prioritized} */ - Comparator COMPARATOR = (a, b) -> a.compareTo(b); + Comparator COMPARATOR = (one, two) -> { + boolean b1 = one instanceof Prioritized; + boolean b2 = two instanceof Prioritized; + if (b1 && !b2) { // one is Prioritized, two is not + return -1; + } else if (b2 && !b1) { // two is Prioritized, one is not + return 1; + } else if (b1 && b2) { // one and two both Prioritized + return ((Prioritized) one).compareTo((Prioritized) two); + } else { // no different + return 0; + } + }; /** * The maximum priority diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java index 2f48491478c..a153494b282 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java @@ -25,7 +25,6 @@ import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; -import static org.apache.dubbo.common.extension.support.ActivateComparator.COMPARATOR; /** * An extension class of {@link ServiceLoader} to help the ease for use of Dubbo services/components @@ -57,7 +56,7 @@ public static Stream load(Class serviceClass, ClassLoader classLoader) ServiceLoader serviceLoader = ServiceLoader.load(serviceClass, actualClassLoader); - return stream(serviceLoader.spliterator(), false).sorted(COMPARATOR); + return stream(serviceLoader.spliterator(), false).sorted(Prioritized.COMPARATOR); } /** diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/lang/PrioritizedTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/lang/PrioritizedTest.java new file mode 100644 index 00000000000..3ee027f25bb --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/lang/PrioritizedTest.java @@ -0,0 +1,125 @@ +/* + * 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.lang; + +import org.junit.jupiter.api.Test; + +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +import static java.util.Arrays.asList; +import static java.util.Collections.sort; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link Prioritized} Test + * + * @since 2.7.4 + */ +public class PrioritizedTest { + + @Test + public void testConstants() { + assertEquals(Integer.MAX_VALUE, Prioritized.MIN_PRIORITY); + assertEquals(Integer.MIN_VALUE, Prioritized.MAX_PRIORITY); + } + + @Test + public void testGetPriority() { + assertEquals(Prioritized.MIN_PRIORITY, new Prioritized() { + }.getPriority()); + } + + @Test + public void testComparator() { + + List list = new LinkedList<>(); + + // All Prioritized + list.add(of(1)); + list.add(of(2)); + list.add(of(3)); + + List copy = new LinkedList<>(list); + + sort(list, Prioritized.COMPARATOR); + + assertEquals(copy, list); + + // MIX non-Prioritized and Prioritized + list.clear(); + + list.add(1); + list.add(of(2)); + list.add(of(1)); + + sort(list, Prioritized.COMPARATOR); + + copy = asList(of(1), of(2), 1); + + assertEquals(copy, list); + + // All non-Prioritized + list.clear(); + list.add(1); + list.add(2); + list.add(3); + + sort(list, Prioritized.COMPARATOR); + + copy = asList(1, 2, 3); + + assertEquals(copy, list); + + } + + public static PrioritizedValue of(int value) { + return new PrioritizedValue(value); + } + + static class PrioritizedValue implements Prioritized { + + private final int value; + + private PrioritizedValue(int value) { + this.value = value; + } + + public int getPriority() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof PrioritizedValue)) return false; + PrioritizedValue that = (PrioritizedValue) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + } +} From f67d7695158b99b6d011f1c1f6d3150be9df90ba Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 15 Aug 2019 11:22:35 +0800 Subject: [PATCH 43/55] Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer --- .../main/java/org/apache/dubbo/common/lang/Prioritized.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java index 98bf3f8c5b9..f416ae0a1bb 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java @@ -38,7 +38,7 @@ public interface Prioritized extends Comparable { return -1; } else if (b2 && !b1) { // two is Prioritized, one is not return 1; - } else if (b1 && b2) { // one and two both Prioritized + } else if (b1 && b2) { // one and two both are Prioritized return ((Prioritized) one).compareTo((Prioritized) two); } else { // no different return 0; @@ -54,6 +54,7 @@ public interface Prioritized extends Comparable { * The minimum priority */ int MIN_PRIORITY = Integer.MAX_VALUE; + /** * Normal Priority */ From b286e1d65fbbcbef30dd39221ea54f1dd3382d46 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 15 Aug 2019 11:34:28 +0800 Subject: [PATCH 44/55] Polish apache/dubbo#4807 : Add sort implementation --- .../main/java/org/apache/dubbo/config/DubboShutdownHook.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java index 321649d7b0d..8172e140914 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import static java.util.Collections.sort; -import static java.util.ServiceLoader.load; +import static org.apache.dubbo.common.utils.DubboServiceLoader.load; /** * The shutdown hook thread to do the clean up stuff. From 0bfda8322c02aafef750004d4aa6cac1b0b1e5ba Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 02:13:05 +0800 Subject: [PATCH 45/55] Refactor --- .../dubbo/bootstrap/DubboBootstrap.java | 29 ++-- .../file/FileSystemDynamicConfiguration.java | 4 + .../common/constants/RegistryConstants.java | 2 +- .../dubbo/common/context/Lifecycle.java | 2 +- .../common/extension/ExtensionLoader.java | 14 ++ .../common/function/ThrowableAction.java | 33 +++-- .../dubbo/config/DubboProviderBootstrap.java | 13 +- .../metadata/WritableMetadataService.java | 6 +- .../AbstractServiceDiscoveryFactory.java | 16 +-- .../DefaultServiceDiscoveryFactory.java | 54 ++++++++ .../EventPublishingServiceDiscovery.java | 125 ++++++++++-------- .../client/FileSystemServiceDiscovery.java | 22 +-- .../registry/client/ServiceDiscovery.java | 19 ++- .../client/ServiceDiscoveryFactory.java | 29 ++-- .../ServiceDiscoveryRegistry.java} | 84 ++++++------ .../ServiceDiscoveryRegistryFactory.java} | 6 +- .../ServiceDiscoveryRegistryProtocol.java} | 4 +- ...va => ServiceDiscoveryDestroyedEvent.java} | 17 +-- ...a => ServiceDiscoveryDestroyingEvent.java} | 17 +-- .../client/event/ServiceDiscoveryEvent.java | 49 +++++++ .../event/ServiceDiscoveryExceptionEvent.java | 54 ++++++++ ... => ServiceDiscoveryInitializedEvent.java} | 19 +-- ...=> ServiceDiscoveryInitializingEvent.java} | 19 +-- .../event/listener/LoggingEventListener.java | 20 +-- ...tedServicesRevisionMetadataCustomizer.java | 11 +- ...ataServiceURLParamsMetadataCustomizer.java | 9 +- .../RefreshServiceMetadataCustomizer.java | 7 +- .../ServiceInstanceMetadataUtils.java | 55 ++++++-- .../SpringCloudMetadataServiceURLBuilder.java | 4 +- ...bedServicesRevisionMetadataCustomizer.java | 11 +- .../org.apache.dubbo.registry.RegistryFactory | 2 +- ...che.dubbo.registry.client.ServiceDiscovery | 1 + ...bo.registry.client.ServiceDiscoveryFactory | 1 + .../internal/org.apache.dubbo.rpc.Protocol | 2 +- .../EventPublishingServiceDiscoveryTest.java | 44 +++--- .../client/InMemoryServiceDiscovery.java | 5 +- .../InMemoryServiceDiscoveryFactory.java | 33 ----- .../registry/client/ServiceDiscoveryTest.java | 8 +- .../listener/LoggingEventListenerTest.java | 23 ++-- .../support/ServiceOrientedRegistryTest.java | 10 +- ...he.dubbo.registry.client.ServiceDiscovery} | 2 +- .../consul/ConsulServiceDiscovery.java | 23 ++-- .../consul/ConsulServiceDiscoveryFactory.java | 31 ----- ...che.dubbo.registry.client.ServiceDiscovery | 1 + ...bo.registry.client.ServiceDiscoveryFactory | 1 - .../registry/etcd/EtcdServiceDiscovery.java | 36 ++--- .../etcd/EtcdServiceDiscoveryFactory.java | 39 ------ ...che.dubbo.registry.client.ServiceDiscovery | 1 + ...bo.registry.client.ServiceDiscoveryFactory | 1 - .../registry/nacos/NacosServiceDiscovery.java | 16 +-- .../nacos/NacosServiceDiscoveryFactory.java | 36 ----- ...che.dubbo.registry.client.ServiceDiscovery | 1 + ...bo.registry.client.ServiceDiscoveryFactory | 1 - .../zookeeper/ZookeeperServiceDiscovery.java | 34 ++--- .../zookeeper/util/CuratorFrameworkUtils.java | 5 - ...he.dubbo.registry.client.ServiceDiscovery} | 2 +- ...bo.registry.client.ServiceDiscoveryFactory | 1 - .../ZookeeperServiceDiscoveryTest.java | 10 +- 58 files changed, 592 insertions(+), 532 deletions(-) rename dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java => dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java (59%) create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/{service/ServiceOrientedRegistry.java => client/ServiceDiscoveryRegistry.java} (87%) rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/{service/ServiceOrientedRegistryFactory.java => client/ServiceDiscoveryRegistryFactory.java} (89%) rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/{service/ServiceOrientedRegistryProtocol.java => client/ServiceDiscoveryRegistryProtocol.java} (93%) rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/{ServiceDiscoveryStoppedEvent.java => ServiceDiscoveryDestroyedEvent.java} (72%) rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/{ServiceDiscoveryStartingEvent.java => ServiceDiscoveryDestroyingEvent.java} (72%) create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/{ServiceDiscoveryStartedEvent.java => ServiceDiscoveryInitializedEvent.java} (72%) rename dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/{ServiceDiscoveryStoppingEvent.java => ServiceDiscoveryInitializingEvent.java} (72%) create mode 100644 dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery create mode 100644 dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory delete mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java rename dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/{org.apache.dubbo.registry.client.ServiceDiscoveryFactory => org.apache.dubbo.registry.client.ServiceDiscovery} (86%) delete mode 100644 dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java create mode 100644 dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery delete mode 100644 dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory delete mode 100644 dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java create mode 100644 dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery delete mode 100644 dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory delete mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery delete mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory rename dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/{org.apache.dubbo.registry.client.ServiceDiscoveryFactory => org.apache.dubbo.registry.client.ServiceDiscovery} (82%) delete mode 100644 dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory 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 db5963a37b9..6432dc8d3f9 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 @@ -76,12 +76,10 @@ 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.GROUP_CHAR_SEPERATOR; -import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT; -import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE; import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.context.ConfigManager.getInstance; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType; import static org.apache.dubbo.remoting.Constants.CLIENT_KEY; /** @@ -130,7 +128,9 @@ public class DubboBootstrap implements Lifecycle { */ private volatile boolean onlyRegisterProvider = false; - private ServiceInstance serviceInstance; + private volatile boolean defaultMetadataStorageType = true; + + private volatile ServiceInstance serviceInstance; public DubboBootstrap() { DubboShutdownHook.getDubboShutdownHook().register(); @@ -147,6 +147,15 @@ public DubboBootstrap onlyRegisterProvider(boolean onlyRegisterProvider) { return this; } + public boolean isDefaultMetadataStorageType() { + return defaultMetadataStorageType; + } + + public DubboBootstrap setDefaultMetadataStorageType(boolean defaultMetadataStorageType) { + this.defaultMetadataStorageType = defaultMetadataStorageType; + return this; + } + public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) { configManager.addMetadataReport(metadataReportConfig); return this; @@ -161,7 +170,6 @@ public DubboBootstrap metadataReports(List metadataReportC return this; } - // {@link ApplicationConfig} correlative methods /** @@ -746,12 +754,7 @@ private void registerServiceInstance(ApplicationConfig applicationConfig) { String host = address[0]; int port = Integer.parseInt(address[1]); - ServiceInstance serviceInstance = initServiceInstance( - serviceName, - host, - port, - applicationConfig.getMetadata() == null ? METADATA_DEFAULT : applicationConfig.getMetadata() - ); + ServiceInstance serviceInstance = initServiceInstance(serviceName, host, port); getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance)); } @@ -791,9 +794,9 @@ private void unregisterServiceInstance() { } - private ServiceInstance initServiceInstance(String serviceName, String host, int port, String metadataType) { + private ServiceInstance initServiceInstance(String serviceName, String host, int port) { this.serviceInstance = new DefaultServiceInstance(serviceName, host, port); - this.serviceInstance.getMetadata().put(MEATADATA_STORED_TYPE_KEY, metadataType); + setMetadataStorageType(serviceInstance, isDefaultMetadataStorageType()); return this.serviceInstance; } 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 3070c1f632a..45c2b6bb95b 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 @@ -169,6 +169,10 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration private final Map> listenersRepository; + public FileSystemDynamicConfiguration() { + this(URL.valueOf("file:///default")); + } + public FileSystemDynamicConfiguration(URL url) { this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url), getThreadPoolKeepAliveTime(url)); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java index b0d89b9b462..e7e604c7d1f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java @@ -67,7 +67,7 @@ public interface RegistryConstants { */ String SERVICE_REGISTRY_TYPE = "service"; - String SERVICE_REGISTRY_PROTOCOL = "service-oriented-registry"; + String SERVICE_REGISTRY_PROTOCOL = "service-discovery-registry"; /** * The parameter key of the subscribed service names for Service-Oriented Registry diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java b/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java index 672ec2cd22b..67d7b132b6a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java @@ -21,7 +21,7 @@ * * @since 2.7.4 */ -public interface Lifecycle { +public interface Lifecycle { /** * Initialize the component before {@link #start() start} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java index 1cace235039..4575dbba22a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java @@ -353,6 +353,16 @@ public T getExtension(String name) { return (T) instance; } + /** + * Get the extension by specified name if found, or {@link #getDefaultExtension() returns the default one} + * + * @param name the name of extension + * @return non-null + */ + public T getOrDefaultExtension(String name) { + return containsExtension(name) ? getExtension(name) : getDefaultExtension(); + } + /** * Return default extension, return null if it's not configured. */ @@ -543,6 +553,10 @@ private T createExtension(String name) { } } + private boolean containsExtension(String name) { + return getExtensionClasses().containsKey(name); + } + private T injectExtension(T instance) { try { if (objectFactory != null) { diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java similarity index 59% rename from dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java index 4bf354dcb9b..17c96d84648 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java @@ -14,25 +14,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.registry.zookeeper; +package org.apache.dubbo.common.function; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory; -import org.apache.dubbo.registry.client.ServiceDiscovery; -import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; +import java.util.function.Function; /** - * The zookeeper {@link ServiceDiscoveryFactory} implementation + * A function interface for action with {@link Throwable} * - * @see ServiceDiscoveryFactory + * @see Function + * @see Throwable * @since 2.7.4 */ -public class ZookeeperServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory { +@FunctionalInterface +public interface ThrowableAction { - @Override - public ServiceDiscovery createDiscovery(URL connectionURL) { + /** + * Executes the action + * + * @throws Exception if met with error + */ + void execute() throws Exception; + + /** + * Executes {@link ThrowableAction} + * + * @param action {@link ThrowableAction} + * @throws RuntimeException wrap {@link Exception} to {@link RuntimeException} + */ + static void execute(ThrowableAction action) throws RuntimeException { try { - return new ZookeeperServiceDiscovery(connectionURL); + action.execute(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java index ef8cca858dd..22530f85097 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java @@ -17,7 +17,6 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.api.DemoService; import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter; @@ -27,14 +26,12 @@ import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; -import java.io.IOException; - /** * Dubbo Provider Bootstrap */ public class DubboProviderBootstrap { - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws Exception { ApplicationConfig application = new ApplicationConfig(); application.setName("dubbo-provider-demo"); @@ -68,11 +65,11 @@ public static void main(String[] args) throws IOException { // 暴露 MetadataService 服务 exporter.export(); - ServiceDiscoveryFactory factory = ExtensionLoader.getExtensionLoader(ServiceDiscoveryFactory.class).getAdaptiveExtension(); + ServiceDiscoveryFactory factory = ServiceDiscoveryFactory.getExtension(connectionURL); - ServiceDiscovery serviceDiscovery = factory.getDiscovery(connectionURL); + ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(connectionURL); - serviceDiscovery.start(); + serviceDiscovery.initialize(connectionURL); DefaultServiceInstance serviceInstance = new DefaultServiceInstance(application.getName(), "127.0.0.1", protocol.getPort()); @@ -80,6 +77,6 @@ public static void main(String[] args) throws IOException { System.in.read(); - serviceDiscovery.stop(); + serviceDiscovery.destroy(); } } 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 7a8fd27e11e..b5fca8640d0 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 @@ -64,7 +64,7 @@ default String serviceName() { * * @return If success , return true */ - default boolean refreshMetadata(String exportedRevision, String subscribedRevision){ + default boolean refreshMetadata(String exportedRevision, String subscribedRevision) { return true; } @@ -97,8 +97,6 @@ static WritableMetadataService getDefaultExtension() { } static WritableMetadataService getExtension(String name) { - return getExtensionLoader(WritableMetadataService.class).getExtension(name); + return getExtensionLoader(WritableMetadataService.class).getOrDefaultExtension(name); } - - } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java index c9c6ec03cd2..b8d941b6483 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java @@ -40,12 +40,12 @@ public static Collection getDiscoveries() { */ public static void destroyAll() { if (logger.isInfoEnabled()) { - logger.info("Closing all ServiceDicovery instances: " + getDiscoveries()); + logger.info("Closing all ServiceDiscovery instances: " + getDiscoveries()); } for (ServiceDiscovery discovery : getDiscoveries()) { try { - discovery.stop(); + discovery.destroy(); } catch (Throwable e) { logger.error("Error trying to close ServiceDiscovery instance.", e); } @@ -54,17 +54,13 @@ public static void destroyAll() { } /** - * @param url "zookeeper://ip:port/RegistryService?xxx" + * @param registryURL "zookeeper://ip:port/RegistryService?xxx" * @return */ @Override - public ServiceDiscovery getDiscovery(URL url) { - String key = url.toServiceStringWithoutResolving(); - - return discoveries.computeIfAbsent(key, k -> { - ServiceDiscovery discovery = createDiscovery(url); - return new EventPublishingServiceDiscovery(discovery); - }); + public ServiceDiscovery getServiceDiscovery(URL registryURL) { + String key = registryURL.toServiceStringWithoutResolving(); + return discoveries.computeIfAbsent(key, k -> createDiscovery(registryURL)); } protected abstract ServiceDiscovery createDiscovery(URL url); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java new file mode 100644 index 00000000000..0d38acec504 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.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; + +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 default {@link SPI} implementation of {@link ServiceDiscoveryFactory} to {@link #getServiceDiscovery(URL) get the + * instance of ServiceDiscovery} via the {@link URL#getProtocol() protocol} from the {@link URL} that will connect + * the infrastructure of Service registration and discovery. The {@link URL#getProtocol() protocol} will be used as the + * extension name by which the {@link ServiceDiscovery} instance is loaded. + * + * @see AbstractServiceDiscoveryFactory + * @see EventPublishingServiceDiscovery + * @since 2.7.4 + */ +public class DefaultServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory { + + @Override + protected ServiceDiscovery createDiscovery(URL connectionURL) { + ServiceDiscovery serviceDiscovery = load(connectionURL); + return new EventPublishingServiceDiscovery(serviceDiscovery); + } + + /** + * Load the {@link ServiceDiscovery} by {@link URL#getProtocol() the protocol} from {@link URL connection URL} + * + * @param connectionURL the {@link URL url} to connect + * @return non-null + */ + private ServiceDiscovery load(URL connectionURL) { + String protocol = connectionURL.getProtocol(); + ExtensionLoader loader = getExtensionLoader(ServiceDiscovery.class); + return loader.getOrDefaultExtension(protocol); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java index b8e6b3d167f..f85138f2283 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java @@ -16,15 +16,18 @@ */ package org.apache.dubbo.registry.client; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.function.ThrowableAction; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.event.Event; import org.apache.dubbo.event.EventDispatcher; -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.ServiceDiscoveryDestroyedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryExceptionEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent; @@ -55,14 +58,14 @@ * * * - * {@link #START_ACTION start} - * {@link ServiceDiscoveryStartingEvent} - * {@link ServiceDiscoveryStartedEvent} + * {@link #INITIALIZE_ACTION start} + * {@link ServiceDiscoveryInitializingEvent} + * {@link ServiceDiscoveryInitializedEvent} * * - * {@link #STOP_ACTION stop} - * {@link ServiceDiscoveryStoppingEvent} - * {@link ServiceDiscoveryStoppedEvent} + * {@link #DESTROY_ACTION stop} + * {@link ServiceDiscoveryDestroyingEvent} + * {@link ServiceDiscoveryDestroyedEvent} * * * @@ -96,15 +99,15 @@ * * * @see ServiceDiscovery - * @see ServiceDiscoveryStartingEvent - * @see ServiceDiscoveryStartedEvent + * @see ServiceDiscoveryInitializingEvent + * @see ServiceDiscoveryInitializedEvent * @see ServiceInstancePreRegisteredEvent * @see ServiceInstanceRegisteredEvent - * @see ServiceDiscoveryStoppingEvent - * @see ServiceDiscoveryStoppedEvent + * @see ServiceDiscoveryDestroyingEvent + * @see ServiceDiscoveryDestroyedEvent * @since 2.7.4 */ -class EventPublishingServiceDiscovery implements ServiceDiscovery { +final class EventPublishingServiceDiscovery implements ServiceDiscovery { /** * @see ServiceInstancePreRegisteredEvent @@ -117,22 +120,22 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery { protected static final String UNREGISTER_ACTION = "unregister"; /** - * @see ServiceDiscoveryStartingEvent - * @see ServiceDiscoveryStartedEvent + * @see ServiceDiscoveryInitializingEvent + * @see ServiceDiscoveryInitializedEvent */ - protected static final String START_ACTION = "start"; + protected static final String INITIALIZE_ACTION = "initialize"; /** - * @see ServiceDiscoveryStoppingEvent - * @see ServiceDiscoveryStoppedEvent + * @see ServiceDiscoveryDestroyingEvent + * @see ServiceDiscoveryDestroyedEvent */ - protected static final String STOP_ACTION = "stop"; + protected static final String DESTROY_ACTION = "destroy"; protected final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); - protected final AtomicBoolean started = new AtomicBoolean(false); + protected final AtomicBoolean initialized = new AtomicBoolean(false); - protected final AtomicBoolean stopped = new AtomicBoolean(false); + protected final AtomicBoolean destroyed = new AtomicBoolean(false); protected final Logger logger = LoggerFactory.getLogger(getClass()); @@ -148,8 +151,8 @@ protected EventPublishingServiceDiscovery(ServiceDiscovery serviceDiscovery) { @Override public final void register(ServiceInstance serviceInstance) throws RuntimeException { - requireStarted(REGISTER_ACTION); - requireNotStopped(REGISTER_ACTION); + assertDestroyed(REGISTER_ACTION); + assertInitialized(REGISTER_ACTION); executeWithEvents( of(new ServiceInstancePreRegisteredEvent(serviceDiscovery, serviceInstance)), @@ -161,8 +164,8 @@ public final void register(ServiceInstance serviceInstance) throws RuntimeExcept @Override public final void update(ServiceInstance serviceInstance) throws RuntimeException { - requireStarted(UPDATE_ACTION); - requireNotStopped(UPDATE_ACTION); + assertDestroyed(UPDATE_ACTION); + assertInitialized(UPDATE_ACTION); executeWithEvents( empty(), @@ -174,8 +177,8 @@ public final void update(ServiceInstance serviceInstance) throws RuntimeExceptio @Override public final void unregister(ServiceInstance serviceInstance) throws RuntimeException { - requireStarted(UNREGISTER_ACTION); - requireNotStopped(UNREGISTER_ACTION); + assertDestroyed(UNREGISTER_ACTION); + assertInitialized(UNREGISTER_ACTION); executeWithEvents( of(new ServiceInstancePreUnregisteredEvent(this, serviceInstance)), @@ -220,11 +223,11 @@ public void addServiceInstancesChangedListener(String serviceName, ServiceInstan } @Override - public final void start() { + public void initialize(URL registryURL) { - requireNotStopped(START_ACTION); + assertInitialized(INITIALIZE_ACTION); - if (isStarted()) { + if (isInitialized()) { if (logger.isWarnEnabled()) { logger.warn("It's ignored to start current ServiceDiscovery, because it has been started."); } @@ -232,21 +235,21 @@ public final void start() { } executeWithEvents( - of(new ServiceDiscoveryStartingEvent(serviceDiscovery)), - serviceDiscovery::start, - of(new ServiceDiscoveryStartedEvent(serviceDiscovery)) + of(new ServiceDiscoveryInitializingEvent(serviceDiscovery)), + () -> serviceDiscovery.initialize(registryURL), + of(new ServiceDiscoveryInitializedEvent(serviceDiscovery)) ); // doesn't start -> started - started.compareAndSet(false, true); + initialized.compareAndSet(false, true); } @Override - public final void stop() { + public void destroy() { - requireStarted(STOP_ACTION); + assertDestroyed(DESTROY_ACTION); - if (isStopped()) { + if (isDestroyed()) { if (logger.isWarnEnabled()) { logger.warn("It's ignored to stop current ServiceDiscovery, because it has been stopped."); } @@ -254,40 +257,48 @@ public final void stop() { } executeWithEvents( - of(new ServiceDiscoveryStoppingEvent(serviceDiscovery)), - serviceDiscovery::stop, - of(new ServiceDiscoveryStoppedEvent(serviceDiscovery)) + of(new ServiceDiscoveryDestroyingEvent(serviceDiscovery)), + serviceDiscovery::destroy, + of(new ServiceDiscoveryDestroyedEvent(serviceDiscovery)) ); // doesn't stop -> stopped - stopped.compareAndSet(false, true); + destroyed.compareAndSet(false, true); } protected final void executeWithEvents(Optional beforeEvent, - Runnable action, + ThrowableAction action, Optional afterEvent) { - beforeEvent.ifPresent(eventDispatcher::dispatch); - action.run(); - afterEvent.ifPresent(eventDispatcher::dispatch); + beforeEvent.ifPresent(this::dispatchEvent); + try { + action.execute(); + } catch (Exception e) { + dispatchEvent(new ServiceDiscoveryExceptionEvent(serviceDiscovery, e)); + } + afterEvent.ifPresent(this::dispatchEvent); + } + + private void dispatchEvent(Event event) { + eventDispatcher.dispatch(event); } - public final boolean isStarted() { - return started.get(); + public final boolean isInitialized() { + return initialized.get(); } - public final boolean isStopped() { - return stopped.get(); + public final boolean isDestroyed() { + return destroyed.get(); } - protected void requireStarted(String action) throws IllegalStateException { - if (!isStarted()) { - throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is not started yet."); + protected void assertDestroyed(String action) throws IllegalStateException { + if (!isInitialized()) { + throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is not initialized yet."); } } - protected void requireNotStopped(String action) throws IllegalStateException { - if (isStopped()) { - throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is stopped already."); + protected void assertInitialized(String action) throws IllegalStateException { + if (isDestroyed()) { + throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is destroyed already."); } } } 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 index 1dbf90d6121..e49d392436b 100644 --- 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 @@ -36,35 +36,21 @@ */ 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); - } + public void initialize(URL registryURL) throws Exception { + dynamicConfiguration = createDynamicConfiguration(registryURL); } @Override - public void stop() { - try { - if (dynamicConfiguration != null) { - dynamicConfiguration.close(); - } - } catch (Exception e) { - throw new RuntimeException(e); - } + public void destroy() throws Exception { + dynamicConfiguration.close(); } private String getConfigKey(ServiceInstance serviceInstance) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java index 914ec958a9a..3381d5a562a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java @@ -16,6 +16,9 @@ */ package org.apache.dubbo.registry.client; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.common.lang.Prioritized; import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; @@ -33,19 +36,25 @@ * * @since 2.7.4 */ -public interface ServiceDiscovery { +@SPI("file") +public interface ServiceDiscovery extends Prioritized { // ==================================== Lifecycle ==================================== // /** - * Starts the ServiceRegistry. This is a lifecycle method. + * Initializes the {@link ServiceDiscovery} + * + * @param registryURL the {@link URL url} to connect service registry + * @throws Exception If met with error */ - void start(); + void initialize(URL registryURL) throws Exception; /** - * Stops the ServiceRegistry. This is a lifecycle method. + * Destroy the {@link ServiceDiscovery} + * + * @throws Exception If met with error */ - void stop(); + void destroy() throws Exception; // ==================================================================================== // diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java index 20257f4a642..b9b8bb5ef7b 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java @@ -17,24 +17,37 @@ package org.apache.dubbo.registry.client; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; +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 an instance of {@link ServiceDiscovery} + * The factory to create {@link ServiceDiscovery} * * @see ServiceDiscovery * @since 2.7.4 */ -@SPI("zookeeper") +@SPI("default") public interface ServiceDiscoveryFactory { /** - * Creates an instance of {@link ServiceDiscovery}. + * Get the instance of {@link ServiceDiscovery} + * + * @param registryURL the {@link URL} to connect the registry + * @return non-null + */ + ServiceDiscovery getServiceDiscovery(URL registryURL); + + /** + * Get the extension instance of {@link ServiceDiscoveryFactory} by {@link URL#getProtocol() the protocol} * - * @param connectionURL the {@link URL connection url} - * @return an instance of {@link ServiceDiscovery} + * @param registryURL the {@link URL} to connect the registry + * @return non-null */ - @Adaptive({"protocol"}) - ServiceDiscovery getDiscovery(URL connectionURL); + static ServiceDiscoveryFactory getExtension(URL registryURL) { + String protocol = registryURL.getProtocol(); + ExtensionLoader loader = getExtensionLoader(ServiceDiscoveryFactory.class); + return loader.getOrDefaultExtension(protocol); + } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java similarity index 87% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index 5fdc35f39d9..40d0a099b8a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -14,21 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.registry.service; +package org.apache.dubbo.registry.client; import org.apache.dubbo.common.URL; -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.StringUtils; import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.ServiceNameMapping; import org.apache.dubbo.metadata.WritableMetadataService; +import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService; +import org.apache.dubbo.metadata.store.RemoteWritableMetadataService; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.client.ServiceDiscovery; -import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; -import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory; import org.apache.dubbo.registry.client.selector.ServiceInstanceSelector; import org.apache.dubbo.registry.support.FailbackRegistry; @@ -54,7 +52,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; @@ -63,29 +60,36 @@ import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE; import static org.apache.dubbo.common.constants.RegistryConstants.SUBSCRIBED_SERVICE_NAMES_KEY; import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; +import static org.apache.dubbo.common.function.ThrowableAction.execute; import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty; import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty; import static org.apache.dubbo.common.utils.StringUtils.isBlank; import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_EXTENSION; -import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY; +import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStoredType; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort; /** - * Service-Oriented {@link Registry} that is dislike the traditional {@link Registry} will not communicate to - * registry immediately instead of persisting into the metadata's repository when the Dubbo service exports. - * The metadata repository will be used as the data source of Dubbo Metadata service that is about to export and be - * subscribed by the consumers. + * {@link ServiceDiscoveryRegistry} is the service-oriented {@link Registry} and dislike the traditional one that + * {@link #register(URL) registers} to and {@link #subscribe(URL, NotifyListener) discoveries} + * the Dubbo's {@link URL urls} from the external registry. In the {@link #register(URL) registration} + * phase, The {@link URL urls} of Dubbo services will be {@link WritableMetadataService#exportURL(URL) exported} into + * {@link WritableMetadataService} that is either {@link InMemoryWritableMetadataService in-memory} or + * {@link RemoteWritableMetadataService remote}, + *

    + * it's decided by metadata + * subscribes from the remote proxy of {@link MetadataService} + * *

    * * @see ServiceDiscovery * @see FailbackRegistry * @since 2.7.4 */ -public class ServiceOrientedRegistry extends FailbackRegistry { +public class ServiceDiscoveryRegistry extends FailbackRegistry { protected final Logger logger = LoggerFactory.getLogger(getClass()); @@ -97,20 +101,17 @@ public class ServiceOrientedRegistry extends FailbackRegistry { private final WritableMetadataService writableMetadataService; - - public ServiceOrientedRegistry(URL registryURL) { + public ServiceDiscoveryRegistry(URL registryURL) { super(registryURL); - this.serviceDiscovery = buildServiceDiscovery(registryURL); - this.subscribedServices = buildSubscribedServices(registryURL); + this.serviceDiscovery = getServiceDiscovery(registryURL); + this.subscribedServices = getSubscribedServices(registryURL); this.serviceNameMapping = ServiceNameMapping.getDefaultExtension(); - - String metadata = registryURL.getParameter(METADATA_REPORT_KEY, METADATA_DEFAULT); - // FIXME - this.writableMetadataService = WritableMetadataService.getExtension(metadata); + String metadataStorageType = getMetadataStorageType(registryURL); + this.writableMetadataService = WritableMetadataService.getExtension(metadataStorageType); } - private Set buildSubscribedServices(URL url) { - String subscribedServiceNames = url.getParameter(SUBSCRIBED_SERVICE_NAMES_KEY); + protected Set getSubscribedServices(URL registryURL) { + String subscribedServiceNames = registryURL.getParameter(SUBSCRIBED_SERVICE_NAMES_KEY); return isBlank(subscribedServiceNames) ? emptySet() : unmodifiableSet(of(subscribedServiceNames.split(",")) .map(String::trim) @@ -118,17 +119,24 @@ private Set buildSubscribedServices(URL url) { .collect(toSet())); } - private ServiceDiscovery buildServiceDiscovery(URL url) { - ServiceDiscoveryFactory factory = ExtensionLoader.getExtensionLoader(ServiceDiscoveryFactory.class).getAdaptiveExtension(); - ServiceDiscovery serviceDiscovery = factory.getDiscovery(url - .addParameter(INTERFACE_KEY, ServiceDiscovery.class.getName()) - .removeParameter(REGISTRY_TYPE_KEY) - ); - serviceDiscovery.start(); + /** + * Get the {@link ServiceDiscovery} from the connection {@link URL} + * + * @param registryURL the {@link URL} to connect the registry + * @return non-null + */ + protected ServiceDiscovery getServiceDiscovery(URL registryURL) { + ServiceDiscoveryFactory factory = getExtension(registryURL); + ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(registryURL); + execute(() -> { + serviceDiscovery.initialize(registryURL.addParameter(INTERFACE_KEY, ServiceDiscovery.class.getName()) + .removeParameter(REGISTRY_TYPE_KEY)); + }); return serviceDiscovery; } protected boolean shouldRegister(URL providerURL) { + String side = providerURL.getParameter(SIDE_KEY); boolean should = PROVIDER_SIDE.equals(side); // Only register the Provider. @@ -222,8 +230,10 @@ public boolean isAvailable() { @Override public void destroy() { super.destroy(); - // stop ServiceDiscovery - serviceDiscovery.stop(); + execute(() -> { + // stop ServiceDiscovery + serviceDiscovery.destroy(); + }); } protected void subscribeURLs(URL url, NotifyListener listener) { @@ -429,11 +439,11 @@ protected List getProviderExportedURLs(URL subscribedURL, ServiceInstance p String version = subscribedURL.getParameter(VERSION_KEY); // The subscribed protocol may be null String protocol = subscribedURL.getParameter(PROTOCOL_KEY); - String metadataServiceType = getMetadataStoredType(providerInstance); + String metadataStorageType = getMetadataStorageType(providerInstance); try { MetadataService metadataService = MetadataServiceProxyFactory - .getExtension(metadataServiceType == null ? DEFAULT_EXTENSION : metadataServiceType) + .getExtension(metadataStorageType == null ? DEFAULT_EXTENSION : metadataStorageType) .getProxy(providerInstance); SortedSet urls = metadataService.getExportedURLs(serviceInterface, group, version, protocol); exportedURLs = urls.stream().map(URL::valueOf).collect(Collectors.toList()); @@ -478,13 +488,13 @@ protected Set findMappedServices(URL subscribedURL) { } /** - * Create an instance of {@link ServiceOrientedRegistry} if supported + * Create an instance of {@link ServiceDiscoveryRegistry} if supported * * @param registryURL the {@link URL url} of registry * @return null if not supported */ - public static ServiceOrientedRegistry create(URL registryURL) { - return supports(registryURL) ? new ServiceOrientedRegistry(registryURL) : null; + public static ServiceDiscoveryRegistry create(URL registryURL) { + return supports(registryURL) ? new ServiceDiscoveryRegistry(registryURL) : null; } /** diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java similarity index 89% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryFactory.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java index ea7027c5482..ebf3c5a7a3f 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.registry.service; +package org.apache.dubbo.registry.client; import org.apache.dubbo.common.URL; import org.apache.dubbo.registry.Registry; @@ -24,7 +24,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL; import static org.apache.dubbo.registry.Constants.DEFAULT_REGISTRY; -public class ServiceOrientedRegistryFactory extends AbstractRegistryFactory { +public class ServiceDiscoveryRegistryFactory extends AbstractRegistryFactory { @Override protected Registry createRegistry(URL url) { @@ -32,7 +32,7 @@ protected Registry createRegistry(URL url) { String protocol = url.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY); url = url.setProtocol(protocol).removeParameter(REGISTRY_KEY); } - return new ServiceOrientedRegistry(url); + return new ServiceDiscoveryRegistry(url); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryProtocol.java similarity index 93% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryProtocol.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryProtocol.java index 733e8b89616..c89c6c97da5 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryProtocol.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.registry.service; +package org.apache.dubbo.registry.client; import org.apache.dubbo.common.URL; import org.apache.dubbo.registry.integration.RegistryProtocol; @@ -25,7 +25,7 @@ /** * TODO, replace RegistryProtocol completely in the future. */ -public class ServiceOrientedRegistryProtocol extends RegistryProtocol { +public class ServiceDiscoveryRegistryProtocol extends RegistryProtocol { @Override protected URL getRegistryUrl(Invoker originInvoker) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java similarity index 72% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java index 406a5662d8d..2303335708c 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java @@ -16,16 +16,15 @@ */ package org.apache.dubbo.registry.client.event; -import org.apache.dubbo.event.Event; import org.apache.dubbo.registry.client.ServiceDiscovery; /** - * An event raised after the {@link ServiceDiscovery Service Discovery} stopped. + * An event raised after the {@link ServiceDiscovery Service Discovery} destroyed. * - * @see ServiceDiscovery#stop() + * @see ServiceDiscovery#destroy() * @since 2.7.4 */ -public class ServiceDiscoveryStoppedEvent extends Event { +public class ServiceDiscoveryDestroyedEvent extends ServiceDiscoveryEvent { /** * Constructs a prototypical Event. @@ -33,16 +32,8 @@ public class ServiceDiscoveryStoppedEvent extends Event { * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source * @throws IllegalArgumentException if source is null. */ - public ServiceDiscoveryStoppedEvent(ServiceDiscovery serviceDiscovery) { + public ServiceDiscoveryDestroyedEvent(ServiceDiscovery serviceDiscovery) { super(serviceDiscovery); } - /** - * Get the instance of {@link ServiceDiscovery} as source - * - * @return the instance of {@link ServiceDiscovery} as source - */ - public ServiceDiscovery getServiceDiscovery() { - return (ServiceDiscovery) getSource(); - } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java similarity index 72% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartingEvent.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java index 9f30d673fa4..60500eefddb 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartingEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java @@ -16,16 +16,15 @@ */ package org.apache.dubbo.registry.client.event; -import org.apache.dubbo.event.Event; import org.apache.dubbo.registry.client.ServiceDiscovery; /** - * An event raised when the {@link ServiceDiscovery Service Discovery} is starting. + * An event raised when the {@link ServiceDiscovery Service Discovery} is destroying. * - * @see ServiceDiscovery#start + * @see ServiceDiscovery#destroy() * @since 2.7.4 */ -public class ServiceDiscoveryStartingEvent extends Event { +public class ServiceDiscoveryDestroyingEvent extends ServiceDiscoveryEvent { /** * Constructs a prototypical Event. @@ -33,16 +32,8 @@ public class ServiceDiscoveryStartingEvent extends Event { * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source * @throws IllegalArgumentException if source is null. */ - public ServiceDiscoveryStartingEvent(ServiceDiscovery serviceDiscovery) { + public ServiceDiscoveryDestroyingEvent(ServiceDiscovery serviceDiscovery) { super(serviceDiscovery); } - /** - * Get the instance of {@link ServiceDiscovery} as source - * - * @return the instance of {@link ServiceDiscovery} as source - */ - public ServiceDiscovery getServiceDiscovery() { - return (ServiceDiscovery) getSource(); - } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java new file mode 100644 index 00000000000..a319fd51fdf --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.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.event; + +import org.apache.dubbo.event.Event; +import org.apache.dubbo.registry.client.ServiceDiscovery; + +/** + * An abstract {@link Event} class for {@link ServiceDiscovery} + * + * @see Event + * @see ServiceDiscovery + * @since 2.7.4 + */ +public abstract class ServiceDiscoveryEvent extends Event { + + /** + * Constructs a prototypical Event. + * + * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred. + * @throws IllegalArgumentException if source is null. + */ + public ServiceDiscoveryEvent(ServiceDiscovery serviceDiscovery) { + super(serviceDiscovery); + } + + /** + * Get the {@link ServiceDiscovery} on which the Event initially occurred. + * + * @return {@link ServiceDiscovery} instance + */ + public final ServiceDiscovery getServiceDiscovery() { + return (ServiceDiscovery) getSource(); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java new file mode 100644 index 00000000000..49582aba472 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.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; + +import org.apache.dubbo.registry.client.ServiceDiscovery; + +/** + * An event raised when the {@link ServiceDiscovery Service Discovery} met with some exception + * + * @see ServiceDiscovery + * @see org.apache.dubbo.event.Event + * @since 2.7.4 + */ +public class ServiceDiscoveryExceptionEvent extends ServiceDiscoveryEvent { + + private final Exception cause; + + /** + * Constructs a prototypical Event. + * + * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred. + * @throws IllegalArgumentException if any argument is null. + */ + public ServiceDiscoveryExceptionEvent(ServiceDiscovery serviceDiscovery, Exception cause) { + super(serviceDiscovery); + if (cause == null) { + throw new NullPointerException("The cause of Exception must not null"); + } + this.cause = cause; + } + + /** + * The cause of {@link Exception} + * + * @return non-nul + */ + public Exception getCause() { + return cause; + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java similarity index 72% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartedEvent.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java index 08af0a698f4..31bcc79d8e4 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartedEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java @@ -16,16 +16,16 @@ */ package org.apache.dubbo.registry.client.event; -import org.apache.dubbo.event.Event; +import org.apache.dubbo.common.URL; import org.apache.dubbo.registry.client.ServiceDiscovery; /** - * An event raised after the {@link ServiceDiscovery Service Discovery} started + * An event raised after the {@link ServiceDiscovery Service Discovery} initialized * - * @see ServiceDiscovery#start() + * @see ServiceDiscovery#initialize(URL) * @since 2.7.4 */ -public class ServiceDiscoveryStartedEvent extends Event { +public class ServiceDiscoveryInitializedEvent extends ServiceDiscoveryEvent { /** * Constructs a prototypical Event. @@ -33,17 +33,8 @@ public class ServiceDiscoveryStartedEvent extends Event { * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source * @throws IllegalArgumentException if source is null. */ - public ServiceDiscoveryStartedEvent(ServiceDiscovery serviceDiscovery) { + public ServiceDiscoveryInitializedEvent(ServiceDiscovery serviceDiscovery) { super(serviceDiscovery); } - /** - * Get the instance of {@link ServiceDiscovery} as source - * - * @return the instance of {@link ServiceDiscovery} as source - */ - public ServiceDiscovery getServiceDiscovery() { - return (ServiceDiscovery) getSource(); - } - } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java similarity index 72% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java index 26ea1fbf598..92ef4d1e90f 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java @@ -16,16 +16,16 @@ */ package org.apache.dubbo.registry.client.event; -import org.apache.dubbo.event.Event; +import org.apache.dubbo.common.URL; import org.apache.dubbo.registry.client.ServiceDiscovery; /** - * An event raised when the {@link ServiceDiscovery Service Discovery} is stopping. + * An event raised when the {@link ServiceDiscovery Service Discovery} is initializing. * - * @see ServiceDiscovery#stop() + * @see ServiceDiscovery#initialize(URL) * @since 2.7.4 */ -public class ServiceDiscoveryStoppingEvent extends Event { +public class ServiceDiscoveryInitializingEvent extends ServiceDiscoveryEvent { /** * Constructs a prototypical Event. @@ -33,16 +33,7 @@ public class ServiceDiscoveryStoppingEvent extends Event { * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source * @throws IllegalArgumentException if source is null. */ - public ServiceDiscoveryStoppingEvent(ServiceDiscovery serviceDiscovery) { + public ServiceDiscoveryInitializingEvent(ServiceDiscovery serviceDiscovery) { super(serviceDiscovery); } - - /** - * Get the instance of {@link ServiceDiscovery} as source - * - * @return the instance of {@link ServiceDiscovery} as source - */ - public ServiceDiscovery getServiceDiscovery() { - return (ServiceDiscovery) getSource(); - } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java index ef99d6fa865..f2205bb23d1 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java @@ -20,10 +20,10 @@ import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.event.Event; import org.apache.dubbo.event.GenericEventListener; -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.ServiceDiscoveryDestroyedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent; @@ -41,12 +41,12 @@ public class LoggingEventListener extends GenericEventListener { private final Logger logger = LoggerFactory.getLogger(getClass()); - public void onEvent(ServiceDiscoveryStartingEvent event) { - info("%s is starting...", event.getServiceDiscovery()); + public void onEvent(ServiceDiscoveryInitializingEvent event) { + info("%s is initializing...", event.getServiceDiscovery()); } - public void onEvent(ServiceDiscoveryStartedEvent event) { - info("%s is started.", event.getServiceDiscovery()); + public void onEvent(ServiceDiscoveryInitializedEvent event) { + info("%s is initialized.", event.getServiceDiscovery()); } public void onEvent(ServiceInstancePreRegisteredEvent event) { @@ -69,11 +69,11 @@ public void onEvent(ServiceInstanceUnregisteredEvent event) { info("%s has been unregistered from %s.", event.getServiceInstance(), event.getSource()); } - public void onEvent(ServiceDiscoveryStoppingEvent event) { + public void onEvent(ServiceDiscoveryDestroyingEvent event) { info("%s is stopping...", event.getServiceDiscovery()); } - public void onEvent(ServiceDiscoveryStoppedEvent event) { + public void onEvent(ServiceDiscoveryDestroyedEvent event) { info("%s is stopped.", event.getServiceDiscovery()); } 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 31dac6bef6a..1045aaa8818 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 @@ -29,8 +29,9 @@ import static java.lang.String.valueOf; import static java.util.Objects.hash; +import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType; /** * The customizer to a add the metadata that the reversion of Dubbo exported services calculates. @@ -48,9 +49,11 @@ protected String buildMetadataKey(ServiceInstance serviceInstance) { @Override protected String buildMetadataValue(ServiceInstance serviceInstance) { - WritableMetadataService writableMetadataService = WritableMetadataService.getExtension( - serviceInstance.getMetadata().get(MEATADATA_STORED_TYPE_KEY) - ); + + String metadataStorageType = getMetadataStorageType(serviceInstance); + + WritableMetadataService writableMetadataService = getExtension(metadataStorageType); + SortedSet exportedURLs = writableMetadataService.getExportedURLs(); Object[] data = exportedURLs.stream() .map(URL::valueOf) // String to URL 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 b1baa6536d2..8ea5a9807d5 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 @@ -25,9 +25,10 @@ import java.util.SortedSet; import static org.apache.dubbo.metadata.MetadataService.toURLs; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY; +import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_KEY; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceParameter; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType; /** * An {@link ServiceInstanceMetadataCustomizer} to customize the {@link URL urls} of {@link MetadataService} @@ -46,9 +47,9 @@ public String buildMetadataKey(ServiceInstance serviceInstance) { @Override public String buildMetadataValue(ServiceInstance serviceInstance) { - WritableMetadataService writableMetadataService = WritableMetadataService.getExtension( - serviceInstance.getMetadata().get(MEATADATA_STORED_TYPE_KEY) - ); + String metadataStorageType = getMetadataStorageType(serviceInstance); + + WritableMetadataService writableMetadataService = getExtension(metadataStorageType); String serviceInterface = MetadataService.class.getName(); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java index 5fd089ee3e6..32657097318 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java @@ -4,12 +4,9 @@ import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.ServiceInstanceCustomizer; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY; import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_EXTENSION; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStoredType; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getSubscribedServicesRevision; /** @@ -26,7 +23,7 @@ public int getPriority() { @Override public void customize(ServiceInstance serviceInstance) { // FIXME to define the constant - String metadataStoredType = getMetadataStoredType(serviceInstance); + String metadataStoredType = getMetadataStorageType(serviceInstance); WritableMetadataService remoteWritableMetadataService = WritableMetadataService.getExtension(metadataStoredType == null ? DEFAULT_EXTENSION : metadataStoredType); 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 329dea8c678..3a541a388f0 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 @@ -18,6 +18,9 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.metadata.WritableMetadataService; +import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService; +import org.apache.dubbo.metadata.store.RemoteWritableMetadataService; import org.apache.dubbo.registry.client.ServiceInstance; import com.alibaba.fastjson.JSON; @@ -45,19 +48,19 @@ public class ServiceInstanceMetadataUtils { /** * The prefix of {@link MetadataService} : "dubbo.metadata-service." */ - public static final String DUBBO_METADATA_SERVICE_PREFIX = "dubbo.metadata-service."; + public static final String 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_PREFIX + "url-params"; + public static String METADATA_SERVICE_URL_PARAMS_KEY = 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"; + public static final String METADATA_SERVICE_URLS_PROPERTY_NAME = METADATA_SERVICE_PREFIX + "urls"; /** * The key of The revision for all exported Dubbo services. @@ -70,9 +73,19 @@ public class ServiceInstanceMetadataUtils { public static String SUBSCRIBER_SERVICES_REVISION_KEY = "dubbo.subscribed-services.revision"; /** - * The key of metadata store type. + * The key of metadata storage type. */ - public static String MEATADATA_STORED_TYPE_KEY = "dubbo.metadata.stored-type"; + public static String METADATA_STORAGE_TYPE_KEY = "dubbo.metadata.storage-type"; + + /** + * The storage type value for {@link InMemoryWritableMetadataService} + */ + public static String DEFAULT_METADATA_STORAGE_TYPE = "default"; + + /** + * The storage type value for {@link RemoteWritableMetadataService} + */ + public static String REMOTE_METADATA_STORAGE_TYPE = "remote"; /** * The {@link URL url's} parameter name of Dubbo Provider host @@ -181,14 +194,38 @@ public static String getSubscribedServicesRevision(ServiceInstance serviceInstan } /** - * The metadata is stored in the type used to which {@link org.apache.dubbo.metadata.WritableMetadataService} instance. + * Get metadata's storage type + * + * @param registryURL the {@link URL} to connect the registry + * @return if not found in {@link URL#getParameters() parameters} of {@link URL registry URL}, return + * {@link #DEFAULT_METADATA_STORAGE_TYPE "default"} + */ + public static String getMetadataStorageType(URL registryURL) { + return registryURL.getParameter(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE); + } + + /** + * The metadata's storage type is used to which {@link WritableMetadataService} instance. * * @param serviceInstance the specified {@link ServiceInstance} - * @return null if not exits + * @return if not found in {@link ServiceInstance#getMetadata() metadata} of {@link ServiceInstance}, return + * {@link #DEFAULT_METADATA_STORAGE_TYPE "default"} + */ + public static String getMetadataStorageType(ServiceInstance serviceInstance) { + Map metadata = serviceInstance.getMetadata(); + return metadata.getOrDefault(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE); + } + + /** + * Set the metadata storage type in specified {@link ServiceInstance service instance} + * + * @param serviceInstance {@link ServiceInstance service instance} + * @param isDefaultType is default storage type or not */ - public static String getMetadataStoredType(ServiceInstance serviceInstance) { + public static void setMetadataStorageType(ServiceInstance serviceInstance, boolean isDefaultType) { Map metadata = serviceInstance.getMetadata(); - return metadata.get(MEATADATA_STORED_TYPE_KEY); + metadata.put(METADATA_STORAGE_TYPE_KEY, isDefaultType ? + DEFAULT_METADATA_STORAGE_TYPE : REMOTE_METADATA_STORAGE_TYPE); } private static void setProviderHostParam(Map params, URL providerURL) { 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 index 7eb3664d1cf..efc3253a10b 100644 --- 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 @@ -27,7 +27,7 @@ import java.util.Map; import java.util.stream.Collectors; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME; /** * The {@link MetadataServiceURLBuilder} implementation for The standard Dubbo scenario @@ -39,7 +39,7 @@ public class SpringCloudMetadataServiceURLBuilder implements MetadataServiceURLB @Override public List build(ServiceInstance serviceInstance) { Map metadata = serviceInstance.getMetadata(); - String dubboURLsJSON = metadata.get(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME); + String dubboURLsJSON = metadata.get(METADATA_SERVICE_URLS_PROPERTY_NAME); if (StringUtils.isBlank(dubboURLsJSON)) { return Collections.emptyList(); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java index ca89b266dc2..c0e2c4ab493 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java @@ -29,8 +29,9 @@ import static java.lang.String.valueOf; import static java.util.Objects.hash; -import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY; +import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.SUBSCRIBER_SERVICES_REVISION_KEY; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType; /** * The customizer to a add the metadata that the reversion of Dubbo subscribed services calculates. @@ -48,9 +49,11 @@ protected String buildMetadataKey(ServiceInstance serviceInstance) { @Override protected String buildMetadataValue(ServiceInstance serviceInstance) { - WritableMetadataService writableMetadataService = WritableMetadataService.getExtension( - serviceInstance.getMetadata().get(MEATADATA_STORED_TYPE_KEY) - ); + + String metadataStorageType = getMetadataStorageType(serviceInstance); + + WritableMetadataService writableMetadataService = getExtension(metadataStorageType); + SortedSet subscribedURLs = writableMetadataService.getSubscribedURLs(); Object[] data = subscribedURLs.stream() .map(URL::valueOf) // String to URL diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory index d533e06240b..0dc70024c68 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory @@ -1 +1 @@ -service-oriented-registry=org.apache.dubbo.registry.service.ServiceOrientedRegistryFactory \ No newline at end of file +service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryFactory \ 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.ServiceDiscovery b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery new file mode 100644 index 00000000000..d64d12ca25b --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery @@ -0,0 +1 @@ +file=org.apache.dubbo.registry.client.FileSystemServiceDiscovery \ 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.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory new file mode 100644 index 00000000000..d30ea0c1866 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory @@ -0,0 +1 @@ +default=org.apache.dubbo.registry.client.DefaultServiceDiscoveryFactory \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol index ed2df317faf..c8903b0abf0 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol @@ -1,2 +1,2 @@ registry=org.apache.dubbo.registry.integration.RegistryProtocol -service-oriented-registry=org.apache.dubbo.registry.service.ServiceOrientedRegistryProtocol \ No newline at end of file +service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryProtocol \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java index 5bc272972c5..97ccf8eaf31 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java @@ -19,10 +19,10 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.event.EventListener; -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.ServiceDiscoveryDestroyedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent; @@ -53,7 +53,7 @@ public class EventPublishingServiceDiscoveryTest { private ServiceDiscoveryTest serviceDiscoveryTest; @BeforeEach - public void init() { + public void init() throws Exception { // remove all EventListeners eventDispatcher.removeAllEventListeners(); @@ -67,17 +67,17 @@ public void init() { serviceDiscoveryTest.setServiceDiscovery(serviceDiscovery); // ServiceDiscoveryStartingEvent - eventDispatcher.addEventListener(new EventListener() { + eventDispatcher.addEventListener(new EventListener() { @Override - public void onEvent(ServiceDiscoveryStartingEvent event) { + public void onEvent(ServiceDiscoveryInitializingEvent event) { assertEquals(delegate, event.getServiceDiscovery()); } }); // ServiceDiscoveryStartedEvent - eventDispatcher.addEventListener(new EventListener() { + eventDispatcher.addEventListener(new EventListener() { @Override - public void onEvent(ServiceDiscoveryStartedEvent event) { + public void onEvent(ServiceDiscoveryInitializedEvent event) { assertEquals(delegate, event.getServiceDiscovery()); } }); @@ -98,43 +98,43 @@ public void onEvent(ServiceInstanceRegisteredEvent event) { } }); - assertFalse(serviceDiscovery.isStarted()); - assertFalse(serviceDiscovery.isStopped()); + assertFalse(serviceDiscovery.isInitialized()); + assertFalse(serviceDiscovery.isDestroyed()); // test start() serviceDiscoveryTest.init(); - assertTrue(serviceDiscovery.isStarted()); - assertFalse(serviceDiscovery.isStopped()); + assertTrue(serviceDiscovery.isInitialized()); + assertFalse(serviceDiscovery.isDestroyed()); } @AfterEach - public void destroy() { + public void destroy() throws Exception { // ServiceDiscoveryStoppingEvent - eventDispatcher.addEventListener(new EventListener() { + eventDispatcher.addEventListener(new EventListener() { @Override - public void onEvent(ServiceDiscoveryStoppingEvent event) { + public void onEvent(ServiceDiscoveryDestroyingEvent event) { assertEquals(delegate, event.getServiceDiscovery()); } }); // ServiceDiscoveryStoppedEvent - eventDispatcher.addEventListener(new EventListener() { + eventDispatcher.addEventListener(new EventListener() { @Override - public void onEvent(ServiceDiscoveryStoppedEvent event) { + public void onEvent(ServiceDiscoveryDestroyedEvent event) { assertEquals(delegate, event.getServiceDiscovery()); } }); - assertTrue(serviceDiscovery.isStarted()); - assertFalse(serviceDiscovery.isStopped()); + assertTrue(serviceDiscovery.isInitialized()); + assertFalse(serviceDiscovery.isDestroyed()); // test stop() serviceDiscoveryTest.destroy(); - assertTrue(serviceDiscovery.isStarted()); - assertTrue(serviceDiscovery.isStopped()); + assertTrue(serviceDiscovery.isInitialized()); + assertTrue(serviceDiscovery.isDestroyed()); } @Test diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java index a8954c550e7..6f7c3ea4330 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.registry.client; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.DefaultPage; import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.event.EventDispatcher; @@ -95,12 +96,12 @@ public void unregister(ServiceInstance serviceInstance) throws RuntimeException } @Override - public void start() { + public void initialize(URL registryURL) throws Exception { } @Override - public void stop() { + public void destroy() { } @Override diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java deleted file mode 100644 index 6264611d7c2..00000000000 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java +++ /dev/null @@ -1,33 +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.registry.client; - -import org.apache.dubbo.common.URL; - -/** - * {@link InMemoryServiceDiscovery} Factory - * - * @see InMemoryServiceDiscovery - * @since 2.7.4 - */ -public class InMemoryServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory { - - @Override - public ServiceDiscovery createDiscovery(URL connectionURL) { - return new InMemoryServiceDiscovery(); - } -} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java index aa607418c77..1d0e0d3fa88 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java @@ -41,18 +41,18 @@ public class ServiceDiscoveryTest { private ServiceDiscovery serviceDiscovery; @BeforeEach - public void init() { + public void init() throws Exception { if (serviceDiscovery == null) { setServiceDiscovery(new InMemoryServiceDiscovery()); } // test start() - serviceDiscovery.start(); + serviceDiscovery.initialize(null); } @AfterEach - public void destroy() { + public void destroy() throws Exception { // test stop() - serviceDiscovery.stop(); + serviceDiscovery.destroy(); } @Test 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 index ddd3aecd08e..f594a43c3fb 100644 --- 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 @@ -19,10 +19,10 @@ 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.ServiceDiscoveryDestroyedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent; import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent; @@ -50,16 +50,19 @@ public void init() { } @Test - public void testOnEvent() { + public void testOnEvent() throws Exception { URL connectionURL = URL.valueOf("file:///Users/Home"); - ServiceDiscovery serviceDiscovery = new FileSystemServiceDiscovery(connectionURL); + + ServiceDiscovery serviceDiscovery = new FileSystemServiceDiscovery(); + + serviceDiscovery.initialize(connectionURL); // ServiceDiscoveryStartingEvent - listener.onEvent(new ServiceDiscoveryStartingEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryInitializingEvent(serviceDiscovery)); // ServiceDiscoveryStartedEvent - listener.onEvent(new ServiceDiscoveryStartedEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryInitializedEvent(serviceDiscovery)); // ServiceInstancePreRegisteredEvent listener.onEvent(new ServiceInstancePreRegisteredEvent(serviceDiscovery, createInstance())); @@ -77,9 +80,9 @@ public void testOnEvent() { listener.onEvent(new ServiceInstanceUnregisteredEvent(serviceDiscovery, createInstance())); // ServiceDiscoveryStoppingEvent - listener.onEvent(new ServiceDiscoveryStoppingEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryDestroyingEvent(serviceDiscovery)); // ServiceDiscoveryStoppedEvent - listener.onEvent(new ServiceDiscoveryStoppedEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryDestroyedEvent(serviceDiscovery)); } } 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 5d9157d624a..f884b9d167d 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 @@ -19,7 +19,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.service.ServiceOrientedRegistry; +import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -43,7 +43,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; /** - * {@link ServiceOrientedRegistry} Test + * {@link ServiceDiscoveryRegistry} Test * * @since 2.7.4 */ @@ -72,20 +72,20 @@ public class ServiceOrientedRegistryTest { private WritableMetadataService metadataService; - private ServiceOrientedRegistry registry; + private ServiceDiscoveryRegistry registry; private NotifyListener notifyListener; @BeforeEach public void init() { - registry = ServiceOrientedRegistry.create(registryURL); + registry = ServiceDiscoveryRegistry.create(registryURL); metadataService = WritableMetadataService.getDefaultExtension(); notifyListener = new MyNotifyListener(); } @Test public void testSupports() { - assertTrue(ServiceOrientedRegistry.supports(registryURL)); + assertTrue(ServiceDiscoveryRegistry.supports(registryURL)); } @Test diff --git a/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery similarity index 86% rename from dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory rename to dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery index 2a280741612..53725cbe6ae 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory +++ b/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery @@ -1 +1 @@ -in-memory=org.apache.dubbo.registry.client.InMemoryServiceDiscoveryFactory \ No newline at end of file +in-memory=org.apache.dubbo.registry.client.InMemoryServiceDiscovery \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java index 503823a1bf6..22e44a149c8 100644 --- a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java @@ -63,6 +63,7 @@ * 2019-07-31 */ public class ConsulServiceDiscovery implements ServiceDiscovery, EventListener { + private static final Logger logger = LoggerFactory.getLogger(ConsulServiceDiscovery.class); private ConsulClient client; @@ -72,28 +73,24 @@ public class ConsulServiceDiscovery implements ServiceDiscovery, EventListener childListenerMap = new ConcurrentHashMap<>(); private final ConcurrentMap> etcdListeners = new ConcurrentHashMap<>(); - private final EtcdClient etcdClient; - private final EventDispatcher dispatcher; + + private EtcdClient etcdClient; + private EventDispatcher dispatcher; private ServiceInstance serviceInstance; - public EtcdServiceDiscovery(URL url, EtcdTransporter etcdTransporter) { - if (url.isAnyHost()) { - throw new IllegalStateException("Service discovery address is invalid, actual: '" + url.getHost() + "'"); + @Override + public void onEvent(ServiceInstancesChangedEvent event) { + registerServiceWatcher(event.getServiceName()); + } + + @Override + public void initialize(URL registryURL) throws Exception { + + EtcdTransporter etcdTransporter = ExtensionLoader.getExtensionLoader(EtcdTransporter.class).getAdaptiveExtension(); + + if (registryURL.isAnyHost()) { + throw new IllegalStateException("Service discovery address is invalid, actual: '" + registryURL.getHost() + "'"); } - etcdClient = etcdTransporter.connect(url); + + etcdClient = etcdTransporter.connect(registryURL); etcdClient.addStateListener(state -> { if (state == StateListener.CONNECTED) { @@ -82,17 +94,7 @@ public EtcdServiceDiscovery(URL url, EtcdTransporter etcdTransporter) { } @Override - public void onEvent(ServiceInstancesChangedEvent event) { - registerServiceWatcher(event.getServiceName()); - } - - @Override - public void start() { - - } - - @Override - public void stop() { + public void destroy() { } diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java deleted file mode 100644 index fb7500669d3..00000000000 --- a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java +++ /dev/null @@ -1,39 +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.registry.etcd; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory; -import org.apache.dubbo.registry.client.ServiceDiscovery; -import org.apache.dubbo.remoting.etcd.EtcdTransporter; - -/** - * 2019-07-08 - */ -public class EtcdServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory { - - private EtcdTransporter etcdTransporter; - - public void setEtcdTransporter(EtcdTransporter etcdTransporter) { - this.etcdTransporter = etcdTransporter; - } - - @Override - public ServiceDiscovery createDiscovery(URL connectionURL) { - return new EtcdServiceDiscovery(connectionURL, etcdTransporter); - } -} diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery new file mode 100644 index 00000000000..60f47ac9e4f --- /dev/null +++ b/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery @@ -0,0 +1 @@ +etcd=org.apache.dubbo.registry.etcd.EtcdServiceDiscovery \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory deleted file mode 100644 index ad5937af662..00000000000 --- a/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory +++ /dev/null @@ -1 +0,0 @@ -etcd3=org.apache.dubbo.registry.etcd.EtcdServiceDiscoveryFactory diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java index 0db74301b9f..8863e8915c4 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java @@ -51,24 +51,18 @@ public class NacosServiceDiscovery implements ServiceDiscovery { private final Logger logger = LoggerFactory.getLogger(getClass()); - private final URL connectionURL; - - private final String group; + private String group; private NamingService namingService; - public NacosServiceDiscovery(URL connectionURL) { - this.connectionURL = connectionURL; - this.group = getGroup(connectionURL); - } - @Override - public void start() { - this.namingService = createNamingService(connectionURL); + public void initialize(URL registryURL) throws Exception { + this.namingService = createNamingService(registryURL); + this.group = getGroup(registryURL); } @Override - public void stop() { + public void destroy() { this.namingService = null; } diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java deleted file mode 100644 index e2ac08bb14d..00000000000 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.apache.dubbo.registry.nacos;/* - * 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. - */ - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory; -import org.apache.dubbo.registry.client.ServiceDiscovery; -import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; - -/** - * Nacos {@link ServiceDiscoveryFactory} - * - * @see ServiceDiscoveryFactory - * @see ServiceDiscovery - * @since 2.7.4 - */ -public class NacosServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory { - - @Override - public ServiceDiscovery createDiscovery(URL connectionURL) { - return new NacosServiceDiscovery(connectionURL); - } -} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery new file mode 100644 index 00000000000..e3819e092ab --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery @@ -0,0 +1 @@ +nacos=org.apache.dubbo.registry.nacos.NacosServiceDiscovery \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory deleted file mode 100644 index 4fc3f4a4dd2..00000000000 --- a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory +++ /dev/null @@ -1 +0,0 @@ -nacos=org.apache.dubbo.registry.nacos.NacosServiceDiscoveryFactory \ No newline at end of file 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 9ee5dde7cf8..feac09358f1 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 @@ -56,25 +56,31 @@ public class ZookeeperServiceDiscovery implements ServiceDiscovery, EventListene private final Logger logger = LoggerFactory.getLogger(getClass()); - private final CuratorFramework curatorFramework; + private EventDispatcher dispatcher; - private final String rootPath; + private CuratorFramework curatorFramework; - private final org.apache.curator.x.discovery.ServiceDiscovery serviceDiscovery; + private String rootPath; - private final EventDispatcher dispatcher; + private org.apache.curator.x.discovery.ServiceDiscovery serviceDiscovery; /** * The Key is watched Zookeeper path, the value is an instance of {@link CuratorWatcher} */ private final Map watcherCaches = new ConcurrentHashMap<>(); - public ZookeeperServiceDiscovery(URL connectionURL) throws Exception { - this.curatorFramework = buildCuratorFramework(connectionURL); - this.rootPath = ROOT_PATH.getParameterValue(connectionURL); - this.serviceDiscovery = buildServiceDiscovery(curatorFramework, rootPath); + @Override + public void initialize(URL registryURL) throws Exception { this.dispatcher = EventDispatcher.getDefaultExtension(); this.dispatcher.addEventListener(this); + this.curatorFramework = buildCuratorFramework(registryURL); + this.rootPath = ROOT_PATH.getParameterValue(registryURL); + this.serviceDiscovery = buildServiceDiscovery(curatorFramework, rootPath); + this.serviceDiscovery.start(); + } + + public void destroy() throws Exception { + serviceDiscovery.close(); } public void register(ServiceInstance serviceInstance) throws RuntimeException { @@ -95,18 +101,6 @@ public void unregister(ServiceInstance serviceInstance) throws RuntimeException }); } - public void start() { - doInServiceRegistry(serviceDiscovery -> { - serviceDiscovery.start(); - }); - } - - public void stop() { - doInServiceRegistry(serviceDiscovery -> { - serviceDiscovery.close(); - }); - } - @Override public Set getServices() { return doInServiceDiscovery(s -> new LinkedHashSet<>(s.queryForNames())); diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java index 901acfcbb50..e72b87dd68b 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java @@ -20,7 +20,6 @@ import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.zookeeper.ZookeeperInstance; -import org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery; import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; @@ -49,10 +48,6 @@ */ public abstract class CuratorFrameworkUtils { - public static ZookeeperServiceDiscovery buildZookeeperServiceDiscovery(URL connectionURL) throws Exception { - return new ZookeeperServiceDiscovery(connectionURL); - } - public static ServiceDiscovery buildServiceDiscovery(CuratorFramework curatorFramework, String basePath) { return ServiceDiscoveryBuilder.builder(ZookeeperInstance.class) diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery similarity index 82% rename from dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory rename to dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery index 12262adad29..5532b31946d 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery @@ -1 +1 @@ -zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscoveryFactory \ No newline at end of file +zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory deleted file mode 100644 index 9e2e9ec9c91..00000000000 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory +++ /dev/null @@ -1 +0,0 @@ -org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscoveryFactory \ No newline at end of file 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 5f14ec5849e..12c1a1981c7 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 @@ -27,7 +27,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.IOException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -36,7 +35,6 @@ import static java.util.Arrays.asList; import static org.apache.dubbo.common.utils.NetUtils.getAvailablePort; -import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkUtils.buildZookeeperServiceDiscovery; import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkUtils.generateId; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -67,13 +65,13 @@ public void init() throws Exception { zkServer.start(); this.registryUrl = URL.valueOf("zookeeper://127.0.0.1:" + zkServerPort); - this.discovery = buildZookeeperServiceDiscovery(registryUrl); - this.discovery.start(); + this.discovery = new ZookeeperServiceDiscovery(); + this.discovery.initialize(registryUrl); } @AfterEach - public void close() throws IOException { - discovery.stop(); + public void close() throws Exception { + discovery.destroy(); zkServer.stop(); } From b5da5da064aacaef1042f3e341a2ffdd73581028 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 10:59:11 +0800 Subject: [PATCH 46/55] Refactor --- .../dubbo/bootstrap/DubboBootstrap.java | 138 ++++++++++++------ .../DubboServiceConsumerBootstrap.java | 9 +- .../DubboServiceProvider2Bootstrap.java | 9 +- .../ConfigurableMetadataServiceExporter.java | 59 ++++---- ...nfigurableMetadataServiceExporterTest.java | 2 +- .../dubbo/metadata/MetadataService.java | 2 +- .../metadata/MetadataServiceExporter.java | 23 ++- .../metadata/WritableMetadataService.java | 24 +++ .../ServiceInstanceMetadataUtils.java | 28 +--- 9 files changed, 183 insertions(+), 111 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 6432dc8d3f9..4ad55126639 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 @@ -21,7 +21,6 @@ import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration; import org.apache.dubbo.common.context.Lifecycle; -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; @@ -50,13 +49,14 @@ import org.apache.dubbo.config.utils.ReferenceConfigCache; import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.event.EventListener; +import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.metadata.MetadataServiceExporter; +import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.metadata.report.MetadataReportInstance; import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory; import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.client.ServiceInstance; -import org.apache.dubbo.rpc.Protocol; -import org.apache.dubbo.rpc.ProtocolServer; import java.io.IOException; import java.util.ArrayList; @@ -64,6 +64,7 @@ import java.util.HashMap; import java.util.List; import java.util.Set; +import java.util.SortedSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; @@ -75,10 +76,10 @@ 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.GROUP_CHAR_SEPERATOR; import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE; import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.context.ConfigManager.getInstance; +import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType; import static org.apache.dubbo.remoting.Constants.CLIENT_KEY; @@ -132,6 +133,10 @@ public class DubboBootstrap implements Lifecycle { private volatile ServiceInstance serviceInstance; + private volatile MetadataService metadataService; + + private volatile MetadataServiceExporter metadataServiceExporter; + public DubboBootstrap() { DubboShutdownHook.getDubboShutdownHook().register(); } @@ -147,11 +152,15 @@ public DubboBootstrap onlyRegisterProvider(boolean onlyRegisterProvider) { return this; } + public boolean isOnlyRegisterProvider() { + return onlyRegisterProvider; + } + public boolean isDefaultMetadataStorageType() { return defaultMetadataStorageType; } - public DubboBootstrap setDefaultMetadataStorageType(boolean defaultMetadataStorageType) { + public DubboBootstrap defaultMetadataStorageType(boolean defaultMetadataStorageType) { this.defaultMetadataStorageType = defaultMetadataStorageType; return this; } @@ -427,6 +436,10 @@ public DubboBootstrap initialize() { useRegistryAsConfigCenterIfNecessary(); + initMetadataService(); + + initMetadataServiceExporter(); + initialized = true; if (logger.isInfoEnabled()) { @@ -438,6 +451,24 @@ public DubboBootstrap initialize() { return this; } + /** + * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension + */ + private void initMetadataService() { + this.metadataService = getExtension(isDefaultMetadataStorageType()); + } + + /** + * Initialize {@link MetadataServiceExporter} + */ + private void initMetadataServiceExporter() { + this.metadataServiceExporter = new ConfigurableMetadataServiceExporter() + .setApplicationConfig(getApplication()) + .setRegistries(configManager.getRegistries()) + .setProtocols(configManager.getProtocols()) + .metadataService(metadataService); + } + private void loadRemoteConfigs() { // registry ids to registry configs List tmpRegistries = new ArrayList<>(); @@ -520,26 +551,16 @@ public DubboBootstrap start() { } if (!isStarted()) { + // 1. export Dubbo Services exportServices(); - // Not only provider register and some services are exported - if (!onlyRegisterProvider && !configManager.getServices().isEmpty()) { - /** - * export {@link MetadataService} - */ - // TODO, only export to default registry? - ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")); - if (!METADATA_REMOTE.equals(applicationConfig.getMetadata())) { - exportMetadataService( - applicationConfig, - configManager.getRegistries(), - configManager.getProtocols() - ); - } - /** - * Register the local {@link ServiceInstance} - */ - registerServiceInstance(applicationConfig); + // 2. export MetadataService + exportMetadataService(); + + // Not only provider register + if (!isOnlyRegisterProvider() || hasExportedServices()) { + //3. Register the local ServiceInstance if required + registerServiceInstance(); } referServices(); @@ -553,6 +574,14 @@ public DubboBootstrap start() { return this; } + private boolean hasExportedServices() { + return !metadataService.getExportedURLs().isEmpty(); + } + + private ApplicationConfig getApplication() { + return configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")); + } + /** * Block current thread to be await. * @@ -586,6 +615,7 @@ public DubboBootstrap await() { public DubboBootstrap stop() { if (isInitialized() && isStarted()) { unregisterServiceInstance(); + unexportMetadataService(); unexportServices(); started = false; } @@ -707,14 +737,17 @@ public DubboBootstrap addEventListener(EventListener listener) { return this; } - private List exportMetadataService(ApplicationConfig applicationConfig, - Collection globalRegistryConfigs, - Collection globalProtocolConfigs) { - ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); - exporter.setApplicationConfig(applicationConfig); - exporter.setRegistries(globalRegistryConfigs); - exporter.setProtocols(globalProtocolConfigs); - return exporter.export(); + /** + * export {@link MetadataService} and get the exported {@link URL URLs} + * + * @return {@link MetadataServiceExporter#getExportedURLs()} + */ + private List exportMetadataService() { + return metadataServiceExporter.export().getExportedURLs(); + } + + private void unexportMetadataService() { + metadataServiceExporter.unexport(); } private void exportServices() { @@ -732,33 +765,42 @@ private void referServices() { configManager.getReferences().forEach(cache::get); } - public boolean isOnlyRegisterProvider() { - return onlyRegisterProvider; - } + private void registerServiceInstance() { - private void registerServiceInstance(ApplicationConfig applicationConfig) { - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Protocol.class); - Set protocols = loader.getLoadedExtensions(); - if (CollectionUtils.isEmpty(protocols)) { - throw new IllegalStateException("There should has at least one Protocol specified."); - } + ApplicationConfig application = getApplication(); - String protocol = findOneProtocolForServiceInstance(protocols); + String serviceName = application.getName(); - Protocol protocolInstance = loader.getExtension(protocol); + URL exportedURL = selectMetadataServiceExportedURL(); - String serviceName = applicationConfig.getName(); - // TODO, only support exporting one server - ProtocolServer server = protocolInstance.getServers().get(0); - String[] address = server.getAddress().split(GROUP_CHAR_SEPERATOR); - String host = address[0]; - int port = Integer.parseInt(address[1]); + String host = exportedURL.getHost(); + + int port = exportedURL.getPort(); ServiceInstance serviceInstance = initServiceInstance(serviceName, host, port); getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance)); } + private URL selectMetadataServiceExportedURL() { + + URL selectedURL = null; + + SortedSet urlValues = metadataService.getExportedURLs(); + + for (String urlValue : urlValues) { + URL url = URL.valueOf(urlValue); + if ("rest".equals(url.getProtocol())) { // REST first + selectedURL = url; + break; + } else { + selectedURL = url; // If not found, take any one + } + } + + return selectedURL; + } + /** * Use rest protocol if there's one, otherwise, choose the first one available. * 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 cc0e16b19d4..bf1fe0ae5f8 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 @@ -17,16 +17,9 @@ package org.apache.dubbo.bootstrap; import org.apache.dubbo.bootstrap.rest.UserService; -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.MetadataReportConfig; import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.context.ConfigManager; -import java.util.HashMap; -import java.util.Map; - -import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY; - /** * Dubbo Provider Bootstrap * @@ -40,7 +33,7 @@ public static void main(String[] args) throws Exception { .application("dubbo-consumer-demo") // Zookeeper .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry.type=service&subscribed.services=dubbo-provider-demo")) - .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181")) +// .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181")) // Nacos // .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1")) .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo")) diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java index ad87adbbce9..83ea7a12ffd 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java @@ -16,6 +16,9 @@ */ package org.apache.dubbo.bootstrap; +import org.apache.dubbo.bootstrap.rest.UserService; +import org.apache.dubbo.bootstrap.rest.UserServiceImpl; + /** * Dubbo Provider Bootstrap * @@ -31,8 +34,10 @@ public static void main(String[] args) { // Nacos // .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service")) // .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry.type=service").build()) - .protocol(builder -> builder.port(20885).name("dubbo")) - .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl())) + .protocol("dubbo", builder -> builder.port(20885).name("dubbo")) + .protocol("rest", builder -> builder.port(9090).name("rest")) + .service(builder -> builder.id("echo").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo")) + .service(builder -> builder.id("user").interfaceClass(UserService.class).ref(new UserServiceImpl()).protocolIds("rest")) .start() .await(); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java index 1e8c1f694b3..b5ca2183c12 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java @@ -21,20 +21,18 @@ import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.AbstractConfig; import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.MetadataReportConfig; import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.ServiceConfig; import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.MetadataServiceExporter; -import org.apache.dubbo.metadata.WritableMetadataService; import java.util.Collection; import java.util.LinkedList; import java.util.List; -import static java.util.Collections.unmodifiableList; +import static java.util.Collections.emptyList; /** * {@link MetadataServiceExporter} implementation based on {@link AbstractConfig Dubbo configurations}, the clients @@ -43,6 +41,8 @@ *

    * Typically, do not worry about their ready status, because they are initialized before * any {@link ServiceConfig} exports, or The Dubbo export will be failed. + *

    + * Being aware of it's not a thread-safe implementation. * * @see MetadataServiceExporter * @see ServiceConfig @@ -53,44 +53,52 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor private final Logger logger = LoggerFactory.getLogger(getClass()); - private volatile ServiceConfig serviceConfig; - private ApplicationConfig applicationConfig; - private MetadataReportConfig metadataReportConfig; private List registries = new LinkedList<>(); private List protocols = new LinkedList<>(); - public void setApplicationConfig(ApplicationConfig applicationConfig) { + private MetadataService metadataService; + + private ServiceConfig serviceConfig; + + public ConfigurableMetadataServiceExporter setApplicationConfig(ApplicationConfig applicationConfig) { this.applicationConfig = applicationConfig; + return this; } - public void setRegistries(Collection registries) { + public ConfigurableMetadataServiceExporter setRegistries(Collection registries) { this.registries.clear(); this.registries.addAll(registries); + return this; } - public void setProtocols(Collection protocols) { + public ConfigurableMetadataServiceExporter setProtocols(Collection protocols) { this.protocols.clear(); - this.protocols.addAll(protocols); + // TODO only support "dubbo" protocol, add more in the future + protocols.stream().filter(protocolConfig -> "dubbo".equals(protocolConfig.getName())) + .forEach(this.protocols::add); + return this; + } + + public ConfigurableMetadataServiceExporter metadataService(MetadataService metadataService) { + this.metadataService = metadataService; + return this; } @Override - public List export() { + public ConfigurableMetadataServiceExporter export() { if (!isExported()) { - // FIXME, if uses remote metadata center, does not need to export MetadataService locally. - WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(); - ServiceConfig serviceConfig = new ServiceConfig<>(); serviceConfig.setApplication(applicationConfig); serviceConfig.setRegistries(registries); serviceConfig.setProtocols(protocols); serviceConfig.setInterface(MetadataService.class); serviceConfig.setRef(metadataService); - serviceConfig.setGroup(getApplicationConfig().getName()); + serviceConfig.setGroup(applicationConfig.getName()); serviceConfig.setVersion(metadataService.version()); // export @@ -107,29 +115,24 @@ public List export() { logger.warn("The MetadataService has been exported : " + serviceConfig.getExportedUrls()); } } - return serviceConfig.getExportedUrls(); + + return this; } @Override - public void unexport() { + public ConfigurableMetadataServiceExporter unexport() { if (isExported()) { serviceConfig.unexport(); } + return this; } - private List getProtocols() { - return unmodifiableList(protocols); - } - - private List getRegistries() { - return unmodifiableList(registries); - } - - private ApplicationConfig getApplicationConfig() { - return applicationConfig; + @Override + public List getExportedURLs() { + return serviceConfig != null ? serviceConfig.getExportedUrls() : emptyList(); } - private boolean isExported() { + public boolean isExported() { return serviceConfig != null && serviceConfig.isExported(); } } 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 c53eb7df27c..1528b74cc0c 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 @@ -71,7 +71,7 @@ private static RegistryConfig registryConfig() { public void testExportAndUnexport() { ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); exporter.setApplicationConfig(ConfigManager.getInstance().getApplication().get()); - List urls = exporter.export(); + List urls = exporter.export().getExportedURLs(); assertEquals(1, urls.size()); 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 c4cf2505b20..6beeba7accf 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 @@ -31,7 +31,7 @@ /** * A framework interface of Dubbo Metadata Service defines the contract of Dubbo Services registartion and subscription - * between Dubbo service providers and its consumers. The implementationwill be exported as a normal Dubbo service that + * between Dubbo service providers and its consumers. The implementation will be exported as a normal Dubbo service that * the clients would subscribe, whose version comes from the {@link #version()} method and group gets from * {@link #serviceName()}, that means, The different Dubbo service(application) will export the different * {@link MetadataService} that persists all the exported and subscribed metadata, they are present by diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java index 6ba99dee8b9..108b3a7a1b2 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java @@ -33,12 +33,29 @@ public interface MetadataServiceExporter { /** * Exports the {@link MetadataService} as a Dubbo service * - * @return the exported {@link URL URLs} + * @return {@link MetadataServiceExporter itself} */ - List export(); + MetadataServiceExporter export(); /** * Unexports the {@link MetadataService} + * + * @return {@link MetadataServiceExporter itself} + */ + MetadataServiceExporter unexport(); + + /** + * Get the {@link URL URLs} that were exported + * + * @return non-null */ - void unexport(); + List getExportedURLs(); + + /** + * {@link MetadataService} is export or not + * + * @return if {@link #export()} was executed, return true, or false + */ + boolean isExported(); } + 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 b5fca8640d0..e51fa2a060a 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 @@ -33,6 +33,16 @@ @SPI("default") public interface WritableMetadataService extends MetadataService { + /** + * The default storage type value as the extension name + */ + public static String DEFAULT_METADATA_STORAGE_TYPE = "default"; + + /** + * The remote storage type value as the extension name + */ + public static String REMOTE_METADATA_STORAGE_TYPE = "remote"; + /** * Gets the current Dubbo Service name * @@ -96,6 +106,20 @@ static WritableMetadataService getDefaultExtension() { return getExtensionLoader(WritableMetadataService.class).getDefaultExtension(); } + /** + * Get the metadata's storage type + * + * @param isDefaultStorageType is default storage type or not + * @return non-null, {@link #DEFAULT_METADATA_STORAGE_TYPE "default"} or {@link #REMOTE_METADATA_STORAGE_TYPE "remote"} + */ + public static String getMetadataStorageType(boolean isDefaultStorageType) { + return isDefaultStorageType ? DEFAULT_METADATA_STORAGE_TYPE : REMOTE_METADATA_STORAGE_TYPE; + } + + static WritableMetadataService getExtension(boolean isDefaultStorageType) { + return getExtension(getMetadataStorageType(isDefaultStorageType)); + } + static WritableMetadataService getExtension(String name) { return getExtensionLoader(WritableMetadataService.class).getOrDefaultExtension(name); } 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 3a541a388f0..78402633e56 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 @@ -19,8 +19,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.WritableMetadataService; -import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService; -import org.apache.dubbo.metadata.store.RemoteWritableMetadataService; import org.apache.dubbo.registry.client.ServiceInstance; import com.alibaba.fastjson.JSON; @@ -33,6 +31,7 @@ import static java.lang.String.valueOf; import static java.util.Collections.emptyMap; import static org.apache.dubbo.common.utils.StringUtils.isBlank; +import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_METADATA_STORAGE_TYPE; import static org.apache.dubbo.registry.integration.RegistryProtocol.DEFAULT_REGISTER_PROVIDER_KEYS; /** @@ -77,16 +76,6 @@ public class ServiceInstanceMetadataUtils { */ public static String METADATA_STORAGE_TYPE_KEY = "dubbo.metadata.storage-type"; - /** - * The storage type value for {@link InMemoryWritableMetadataService} - */ - public static String DEFAULT_METADATA_STORAGE_TYPE = "default"; - - /** - * The storage type value for {@link RemoteWritableMetadataService} - */ - public static String REMOTE_METADATA_STORAGE_TYPE = "remote"; - /** * The {@link URL url's} parameter name of Dubbo Provider host */ @@ -198,18 +187,18 @@ public static String getSubscribedServicesRevision(ServiceInstance serviceInstan * * @param registryURL the {@link URL} to connect the registry * @return if not found in {@link URL#getParameters() parameters} of {@link URL registry URL}, return - * {@link #DEFAULT_METADATA_STORAGE_TYPE "default"} + * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"} */ public static String getMetadataStorageType(URL registryURL) { return registryURL.getParameter(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE); } /** - * The metadata's storage type is used to which {@link WritableMetadataService} instance. + * Get the metadata's storage type is used to which {@link WritableMetadataService} instance. * * @param serviceInstance the specified {@link ServiceInstance} * @return if not found in {@link ServiceInstance#getMetadata() metadata} of {@link ServiceInstance}, return - * {@link #DEFAULT_METADATA_STORAGE_TYPE "default"} + * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"} */ public static String getMetadataStorageType(ServiceInstance serviceInstance) { Map metadata = serviceInstance.getMetadata(); @@ -219,13 +208,12 @@ public static String getMetadataStorageType(ServiceInstance serviceInstance) { /** * Set the metadata storage type in specified {@link ServiceInstance service instance} * - * @param serviceInstance {@link ServiceInstance service instance} - * @param isDefaultType is default storage type or not + * @param serviceInstance {@link ServiceInstance service instance} + * @param isDefaultStorageType is default storage type or not */ - public static void setMetadataStorageType(ServiceInstance serviceInstance, boolean isDefaultType) { + public static void setMetadataStorageType(ServiceInstance serviceInstance, boolean isDefaultStorageType) { Map metadata = serviceInstance.getMetadata(); - metadata.put(METADATA_STORAGE_TYPE_KEY, isDefaultType ? - DEFAULT_METADATA_STORAGE_TYPE : REMOTE_METADATA_STORAGE_TYPE); + metadata.put(METADATA_STORAGE_TYPE_KEY, WritableMetadataService.getMetadataStorageType(isDefaultStorageType)); } private static void setProviderHostParam(Map params, URL providerURL) { From 8a7f52b05789799a6214ac9ab14a52a815f7f661 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 11:39:04 +0800 Subject: [PATCH 47/55] Polish apache/dubbo#4845 : [Feature] Enhance the Event-Publishing feature to original ServiceDiscovery --- .../DefaultServiceDiscoveryFactory.java | 17 ++++------ .../client/ServiceDiscoveryRegistry.java | 34 +++++++++++++++---- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java index 0d38acec504..68e9d86f596 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java @@ -34,20 +34,15 @@ */ public class DefaultServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory { - @Override - protected ServiceDiscovery createDiscovery(URL connectionURL) { - ServiceDiscovery serviceDiscovery = load(connectionURL); - return new EventPublishingServiceDiscovery(serviceDiscovery); - } - /** - * Load the {@link ServiceDiscovery} by {@link URL#getProtocol() the protocol} from {@link URL connection URL} + * Create the {@link ServiceDiscovery} by {@link URL#getProtocol() the protocol} from {@link URL connection URL} * - * @param connectionURL the {@link URL url} to connect - * @return non-null + * @param registryURL + * @return */ - private ServiceDiscovery load(URL connectionURL) { - String protocol = connectionURL.getProtocol(); + @Override + protected ServiceDiscovery createDiscovery(URL registryURL) { + String protocol = registryURL.getProtocol(); ExtensionLoader loader = getExtensionLoader(ServiceDiscovery.class); return loader.getOrDefaultExtension(protocol); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index 40d0a099b8a..5075acbff90 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -103,7 +103,7 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry { public ServiceDiscoveryRegistry(URL registryURL) { super(registryURL); - this.serviceDiscovery = getServiceDiscovery(registryURL); + this.serviceDiscovery = createServiceDiscovery(registryURL); this.subscribedServices = getSubscribedServices(registryURL); this.serviceNameMapping = ServiceNameMapping.getDefaultExtension(); String metadataStorageType = getMetadataStorageType(registryURL); @@ -120,14 +120,14 @@ protected Set getSubscribedServices(URL registryURL) { } /** - * Get the {@link ServiceDiscovery} from the connection {@link URL} + * Create the {@link ServiceDiscovery} from the registry {@link URL} * * @param registryURL the {@link URL} to connect the registry * @return non-null */ - protected ServiceDiscovery getServiceDiscovery(URL registryURL) { - ServiceDiscoveryFactory factory = getExtension(registryURL); - ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(registryURL); + protected ServiceDiscovery createServiceDiscovery(URL registryURL) { + ServiceDiscovery originalServiceDiscovery = getServiceDiscovery(registryURL); + ServiceDiscovery serviceDiscovery = enhanceEventPublishing(originalServiceDiscovery); execute(() -> { serviceDiscovery.initialize(registryURL.addParameter(INTERFACE_KEY, ServiceDiscovery.class.getName()) .removeParameter(REGISTRY_TYPE_KEY)); @@ -135,6 +135,28 @@ protected ServiceDiscovery getServiceDiscovery(URL registryURL) { return serviceDiscovery; } + /** + * Get the instance {@link ServiceDiscovery} from the registry {@link URL} using + * {@link ServiceDiscoveryFactory} SPI + * + * @param registryURL the {@link URL} to connect the registry + * @return + */ + private ServiceDiscovery getServiceDiscovery(URL registryURL) { + ServiceDiscoveryFactory factory = getExtension(registryURL); + return factory.getServiceDiscovery(registryURL); + } + + /** + * Enhance the original {@link ServiceDiscovery} with event publishing feature + * + * @param original the original {@link ServiceDiscovery} + * @return {@link EventPublishingServiceDiscovery} instance + */ + private ServiceDiscovery enhanceEventPublishing(ServiceDiscovery original) { + return new EventPublishingServiceDiscovery(original); + } + protected boolean shouldRegister(URL providerURL) { String side = providerURL.getParameter(SIDE_KEY); @@ -512,7 +534,7 @@ public static boolean supports(URL registryURL) { * * @return non-null */ - public ServiceDiscovery getServiceDiscovery() { + public ServiceDiscovery createServiceDiscovery() { return serviceDiscovery; } } From 176d56b2d80436f75ced40a64ef7f5a2440f951d Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 14:30:36 +0800 Subject: [PATCH 48/55] Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native # Conflicts: # dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java # dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java --- .../dubbo/bootstrap/DubboBootstrap.java | 238 ++++++++++-------- .../AbstractServiceDiscoveryFactory.java | 43 +--- .../EventPublishingServiceDiscovery.java | 10 +- .../event/ServiceDiscoveryDestroyedEvent.java | 10 +- .../ServiceDiscoveryDestroyingEvent.java | 10 +- .../client/event/ServiceDiscoveryEvent.java | 26 +- .../event/ServiceDiscoveryExceptionEvent.java | 10 +- .../ServiceDiscoveryInitializedEvent.java | 11 +- .../ServiceDiscoveryInitializingEvent.java | 10 +- .../listener/LoggingEventListenerTest.java | 8 +- 10 files changed, 179 insertions(+), 197 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 4ad55126639..b7df466335e 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 @@ -49,14 +49,15 @@ import org.apache.dubbo.config.utils.ReferenceConfigCache; import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.event.EventListener; +import org.apache.dubbo.event.GenericEventListener; import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.MetadataServiceExporter; import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.metadata.report.MetadataReportInstance; -import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory; import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.client.ServiceInstance; +import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent; import java.io.IOException; import java.util.ArrayList; @@ -65,6 +66,7 @@ import java.util.List; import java.util.Set; import java.util.SortedSet; +import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; @@ -77,6 +79,7 @@ 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.METADATA_REMOTE; +import static org.apache.dubbo.common.function.ThrowableAction.execute; import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.context.ConfigManager.getInstance; import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; @@ -88,7 +91,7 @@ * * @since 2.7.4 */ -public class DubboBootstrap implements Lifecycle { +public class DubboBootstrap extends GenericEventListener implements Lifecycle { public static final String DEFAULT_REGISTRY_ID = "REGISTRY#DEFAULT"; @@ -137,10 +140,22 @@ public class DubboBootstrap implements Lifecycle { private volatile MetadataServiceExporter metadataServiceExporter; + private SortedSet serviceDiscoveries = new ConcurrentSkipListSet<>(); + public DubboBootstrap() { DubboShutdownHook.getDubboShutdownHook().register(); } + /** + * Store the {@link ServiceDiscovery} instances into {@link ServiceDiscoveryInitializingEvent} + * + * @param event {@link ServiceDiscoveryInitializingEvent} + * @see {@linkplan org.apache.dubbo.registry.client.EventPublishingServiceDiscovery} + */ + public void onServiceDiscoveryInitializing(ServiceDiscoveryInitializingEvent event) { + serviceDiscoveries.add(event.getSource()); + } + /** * Set only register provider or not * @@ -440,6 +455,8 @@ public DubboBootstrap initialize() { initMetadataServiceExporter(); + initEventListener(); + initialized = true; if (logger.isInfoEnabled()) { @@ -451,22 +468,74 @@ public DubboBootstrap initialize() { return this; } - /** - * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension - */ - private void initMetadataService() { - this.metadataService = getExtension(isDefaultMetadataStorageType()); + private void startConfigCenter() { + Collection configCenters = configManager.getConfigCenters(); + + if (CollectionUtils.isNotEmpty(configCenters)) { + CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration(); + for (ConfigCenterConfig configCenter : configCenters) { + configCenter.refresh(); + compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter)); + } + Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration); + } + configManager.refreshAll(); + } + + private void startMetadataReport() { + ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow( + () -> new IllegalStateException("There's no ApplicationConfig specified.") + ); + + String metadataType = applicationConfig.getMetadata(); + // FIXME, multiple metadata config support. + Collection metadataReportConfigs = configManager.getMetadataConfigs(); + if (CollectionUtils.isEmpty(metadataReportConfigs)) { + if (METADATA_REMOTE.equals(metadataType)) { + throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'."); + } + return; + } + MetadataReportConfig metadataReportConfig = metadataReportConfigs.iterator().next(); + if (!metadataReportConfig.isValid()) { + return; + } + + MetadataReportInstance.init(metadataReportConfig.toUrl()); } /** - * Initialize {@link MetadataServiceExporter} + * For compatibility purpose, use registry as the default config center when the registry protocol is zookeeper and + * there's no config center specified explicitly. */ - private void initMetadataServiceExporter() { - this.metadataServiceExporter = new ConfigurableMetadataServiceExporter() - .setApplicationConfig(getApplication()) - .setRegistries(configManager.getRegistries()) - .setProtocols(configManager.getProtocols()) - .metadataService(metadataService); + private void useRegistryAsConfigCenterIfNecessary() { + // 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.getDefaultRegistries().stream() + .filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter()) + .forEach(registryConfig -> { + String protocol = registryConfig.getProtocol(); + String id = "config-center-" + protocol + "-" + registryConfig.getPort(); + ConfigCenterConfig cc = new ConfigCenterConfig(); + cc.setId(id); + cc.setParameters(registryConfig.getParameters() == null ? + new HashMap<>() : + new HashMap<>(registryConfig.getParameters())); + cc.getParameters().put(CLIENT_KEY, registryConfig.getClient()); + cc.setProtocol(registryConfig.getProtocol()); + cc.setAddress(registryConfig.getAddress()); + cc.setNamespace(registryConfig.getGroup()); + cc.setHighestPriority(false); + configManager.addConfigCenter(cc); + }); + startConfigCenter(); } private void loadRemoteConfigs() { @@ -503,42 +572,35 @@ private void loadRemoteConfigs() { configManager.addProtocols(tmpProtocols); } + /** - * For compatibility purpose, use registry as the default config center when the registry protocol is zookeeper and - * there's no config center specified explicitly. + * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension */ - private void useRegistryAsConfigCenterIfNecessary() { - // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. - if (Environment.getInstance().getDynamicConfiguration().isPresent()) { - return; - } + private void initMetadataService() { + this.metadataService = getExtension(isDefaultMetadataStorageType()); + } - if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) { - return; - } + /** + * Initialize {@link MetadataServiceExporter} + */ + private void initMetadataServiceExporter() { + this.metadataServiceExporter = new ConfigurableMetadataServiceExporter() + .setApplicationConfig(getApplication()) + .setRegistries(configManager.getRegistries()) + .setProtocols(configManager.getProtocols()) + .metadataService(metadataService); + } - configManager.getDefaultRegistries().stream() - .filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter()) - .forEach(registryConfig -> { - String protocol = registryConfig.getProtocol(); - String id = "config-center-" + protocol + "-" + registryConfig.getPort(); - ConfigCenterConfig cc = new ConfigCenterConfig(); - cc.setId(id); - cc.setParameters(registryConfig.getParameters() == null ? - new HashMap<>() : - new HashMap<>(registryConfig.getParameters())); - cc.getParameters().put(CLIENT_KEY, registryConfig.getClient()); - cc.setProtocol(registryConfig.getProtocol()); - cc.setAddress(registryConfig.getAddress()); - cc.setNamespace(registryConfig.getGroup()); - cc.setHighestPriority(false); - configManager.addConfigCenter(cc); - }); - startConfigCenter(); + /** + * Initialize {@link EventListener} + */ + private void initEventListener() { + // Add current instance into listeners + addEventListener(this); } private Collection getServiceDiscoveries() { - return AbstractServiceDiscoveryFactory.getDiscoveries(); + return serviceDiscoveries; } /** @@ -631,8 +693,8 @@ public boolean isInitialized() { public boolean isStarted() { return started; } - /* serve for builder apis, begin */ + private ApplicationBuilder createApplicationBuilder(String name) { return new ApplicationBuilder().name(name); } @@ -660,43 +722,7 @@ private ProviderBuilder createProviderBuilder(String id) { private ConsumerBuilder createConsumerBuilder(String id) { return new ConsumerBuilder().id(id); } - /* serve for builder apis, end */ - private void startMetadataReport() { - ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow( - () -> new IllegalStateException("There's no ApplicationConfig specified.") - ); - - String metadataType = applicationConfig.getMetadata(); - // FIXME, multiple metadata config support. - Collection metadataReportConfigs = configManager.getMetadataConfigs(); - if (CollectionUtils.isEmpty(metadataReportConfigs)) { - if (METADATA_REMOTE.equals(metadataType)) { - throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'."); - } - return; - } - MetadataReportConfig metadataReportConfig = metadataReportConfigs.iterator().next(); - if (!metadataReportConfig.isValid()) { - return; - } - - MetadataReportInstance.init(metadataReportConfig.toUrl()); - } - - private void startConfigCenter() { - Collection configCenters = configManager.getConfigCenters(); - - if (CollectionUtils.isNotEmpty(configCenters)) { - CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration(); - for (ConfigCenterConfig configCenter : configCenters) { - configCenter.refresh(); - compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter)); - } - Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration); - } - configManager.refreshAll(); - } private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) { if (configCenter.isValid()) { @@ -777,7 +803,7 @@ private void registerServiceInstance() { int port = exportedURL.getPort(); - ServiceInstance serviceInstance = initServiceInstance(serviceName, host, port); + ServiceInstance serviceInstance = createServiceInstance(serviceName, host, port); getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance)); } @@ -801,42 +827,15 @@ private URL selectMetadataServiceExportedURL() { return selectedURL; } - /** - * Use rest protocol if there's one, otherwise, choose the first one available. - * - * @return - */ - private String findOneProtocolForServiceInstance(Set protocols) { - String result = null; - for (String protocol : protocols) { - if ("rest".equalsIgnoreCase(protocol)) { - result = protocol; - break; - } - } - - if (result == null) { - for (String protocol : protocols) { - if (!"injvm".equalsIgnoreCase(protocol) && "registry".equalsIgnoreCase(protocol)) { - result = protocol; - break; - } - } - } - return result; - } - private void unregisterServiceInstance() { - if (serviceInstance != null) { getServiceDiscoveries().forEach(serviceDiscovery -> { serviceDiscovery.unregister(serviceInstance); }); } - } - private ServiceInstance initServiceInstance(String serviceName, String host, int port) { + private ServiceInstance createServiceInstance(String serviceName, String host, int port) { this.serviceInstance = new DefaultServiceInstance(serviceName, host, port); setMetadataStorageType(serviceInstance, isDefaultMetadataStorageType()); return this.serviceInstance; @@ -850,6 +849,8 @@ public void destroy() { destroyReferences(); + destroyServiceDiscoveries(); + clear(); release(); @@ -871,8 +872,20 @@ private void destroyReferences() { } } + private void destroyServiceDiscoveries() { + getServiceDiscoveries().forEach(serviceDiscovery -> { + execute(() -> { + serviceDiscovery.destroy(); + }); + }); + if (logger.isDebugEnabled()) { + logger.debug(NAME + "'s all ServiceDiscoveries have been destroyed."); + } + } + private void clear() { clearConfigs(); + clearServiceDiscoveries(); } private void clearConfigs() { @@ -882,6 +895,13 @@ private void clearConfigs() { } } + private void clearServiceDiscoveries() { + serviceDiscoveries.clear(); + if (logger.isDebugEnabled()) { + logger.debug(NAME + "'s serviceDiscoveries have been clear."); + } + } + private void release() { executeMutually(() -> { while (awaited.compareAndSet(false, true)) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java index b8d941b6483..f5fc29161cb 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java @@ -17,51 +17,26 @@ package org.apache.dubbo.registry.client; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import java.util.Collection; -import java.util.Collections; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +/** + * Abstract {@link ServiceDiscoveryFactory} implementation with cache, the subclass + * should implement {@link #createDiscovery(URL)} method to create an instance of {@link ServiceDiscovery} + * + * @see ServiceDiscoveryFactory + * @since 2.7.4 + */ public abstract class AbstractServiceDiscoveryFactory implements ServiceDiscoveryFactory { - private static final Logger logger = LoggerFactory.getLogger(AbstractServiceDiscoveryFactory.class); - - private static ConcurrentMap discoveries = new ConcurrentHashMap<>(); - - public static Collection getDiscoveries() { - return Collections.unmodifiableCollection(discoveries.values()); - } - - /** - * Close all created registries - */ - public static void destroyAll() { - if (logger.isInfoEnabled()) { - logger.info("Closing all ServiceDiscovery instances: " + getDiscoveries()); - } - - for (ServiceDiscovery discovery : getDiscoveries()) { - try { - discovery.destroy(); - } catch (Throwable e) { - logger.error("Error trying to close ServiceDiscovery instance.", e); - } - } - discoveries.clear(); - } + private final ConcurrentMap discoveries = new ConcurrentHashMap<>(); - /** - * @param registryURL "zookeeper://ip:port/RegistryService?xxx" - * @return - */ @Override public ServiceDiscovery getServiceDiscovery(URL registryURL) { String key = registryURL.toServiceStringWithoutResolving(); return discoveries.computeIfAbsent(key, k -> createDiscovery(registryURL)); } - protected abstract ServiceDiscovery createDiscovery(URL url); + protected abstract ServiceDiscovery createDiscovery(URL registryURL); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java index f85138f2283..dc20a0ffa39 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java @@ -235,9 +235,9 @@ public void initialize(URL registryURL) { } executeWithEvents( - of(new ServiceDiscoveryInitializingEvent(serviceDiscovery)), + of(new ServiceDiscoveryInitializingEvent(this, serviceDiscovery)), () -> serviceDiscovery.initialize(registryURL), - of(new ServiceDiscoveryInitializedEvent(serviceDiscovery)) + of(new ServiceDiscoveryInitializedEvent(this, serviceDiscovery)) ); // doesn't start -> started @@ -257,9 +257,9 @@ public void destroy() { } executeWithEvents( - of(new ServiceDiscoveryDestroyingEvent(serviceDiscovery)), + of(new ServiceDiscoveryDestroyingEvent(this, serviceDiscovery)), serviceDiscovery::destroy, - of(new ServiceDiscoveryDestroyedEvent(serviceDiscovery)) + of(new ServiceDiscoveryDestroyedEvent(this, serviceDiscovery)) ); // doesn't stop -> stopped @@ -273,7 +273,7 @@ protected final void executeWithEvents(Optional beforeEvent, try { action.execute(); } catch (Exception e) { - dispatchEvent(new ServiceDiscoveryExceptionEvent(serviceDiscovery, e)); + dispatchEvent(new ServiceDiscoveryExceptionEvent(this, serviceDiscovery, e)); } afterEvent.ifPresent(this::dispatchEvent); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java index 2303335708c..7a99fdcdfe2 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java @@ -26,14 +26,8 @@ */ public class ServiceDiscoveryDestroyedEvent extends ServiceDiscoveryEvent { - /** - * Constructs a prototypical Event. - * - * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source - * @throws IllegalArgumentException if source is null. - */ - public ServiceDiscoveryDestroyedEvent(ServiceDiscovery serviceDiscovery) { - super(serviceDiscovery); + public ServiceDiscoveryDestroyedEvent(ServiceDiscovery source, ServiceDiscovery original) { + super(source, original); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java index 60500eefddb..d6ebfd61e66 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java @@ -26,14 +26,8 @@ */ public class ServiceDiscoveryDestroyingEvent extends ServiceDiscoveryEvent { - /** - * Constructs a prototypical Event. - * - * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source - * @throws IllegalArgumentException if source is null. - */ - public ServiceDiscoveryDestroyingEvent(ServiceDiscovery serviceDiscovery) { - super(serviceDiscovery); + public ServiceDiscoveryDestroyingEvent(ServiceDiscovery source, ServiceDiscovery original) { + super(source, original); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java index a319fd51fdf..afe613da476 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java @@ -28,14 +28,23 @@ */ public abstract class ServiceDiscoveryEvent extends Event { + private final ServiceDiscovery original; + /** * Constructs a prototypical Event. * - * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred. + * @param source The object on which the Event initially occurred. + * @param original The original {@link ServiceDiscovery} * @throws IllegalArgumentException if source is null. */ - public ServiceDiscoveryEvent(ServiceDiscovery serviceDiscovery) { - super(serviceDiscovery); + public ServiceDiscoveryEvent(ServiceDiscovery source, ServiceDiscovery original) { + super(source); + this.original = original; + } + + @Override + public ServiceDiscovery getSource() { + return (ServiceDiscovery) super.getSource(); } /** @@ -44,6 +53,15 @@ public ServiceDiscoveryEvent(ServiceDiscovery serviceDiscovery) { * @return {@link ServiceDiscovery} instance */ public final ServiceDiscovery getServiceDiscovery() { - return (ServiceDiscovery) getSource(); + return getSource(); + } + + /** + * Get the original {@link ServiceDiscovery} + * + * @return the original {@link ServiceDiscovery} + */ + public final ServiceDiscovery getOriginal() { + return original; } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java index 49582aba472..328be1e13f2 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java @@ -29,14 +29,8 @@ public class ServiceDiscoveryExceptionEvent extends ServiceDiscoveryEvent { private final Exception cause; - /** - * Constructs a prototypical Event. - * - * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred. - * @throws IllegalArgumentException if any argument is null. - */ - public ServiceDiscoveryExceptionEvent(ServiceDiscovery serviceDiscovery, Exception cause) { - super(serviceDiscovery); + public ServiceDiscoveryExceptionEvent(ServiceDiscovery source, ServiceDiscovery original, Exception cause) { + super(source, original); if (cause == null) { throw new NullPointerException("The cause of Exception must not null"); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java index 31bcc79d8e4..a688847a93a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java @@ -27,14 +27,7 @@ */ public class ServiceDiscoveryInitializedEvent extends ServiceDiscoveryEvent { - /** - * Constructs a prototypical Event. - * - * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source - * @throws IllegalArgumentException if source is null. - */ - public ServiceDiscoveryInitializedEvent(ServiceDiscovery serviceDiscovery) { - super(serviceDiscovery); + public ServiceDiscoveryInitializedEvent(ServiceDiscovery source, ServiceDiscovery original) { + super(source, original); } - } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java index 92ef4d1e90f..da92466d517 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java @@ -27,13 +27,7 @@ */ public class ServiceDiscoveryInitializingEvent extends ServiceDiscoveryEvent { - /** - * Constructs a prototypical Event. - * - * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source - * @throws IllegalArgumentException if source is null. - */ - public ServiceDiscoveryInitializingEvent(ServiceDiscovery serviceDiscovery) { - super(serviceDiscovery); + public ServiceDiscoveryInitializingEvent(ServiceDiscovery source, ServiceDiscovery original) { + super(source, original); } } 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 index f594a43c3fb..e1eeecf7c62 100644 --- 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 @@ -59,10 +59,10 @@ public void testOnEvent() throws Exception { serviceDiscovery.initialize(connectionURL); // ServiceDiscoveryStartingEvent - listener.onEvent(new ServiceDiscoveryInitializingEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryInitializingEvent(serviceDiscovery, serviceDiscovery)); // ServiceDiscoveryStartedEvent - listener.onEvent(new ServiceDiscoveryInitializedEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryInitializedEvent(serviceDiscovery, serviceDiscovery)); // ServiceInstancePreRegisteredEvent listener.onEvent(new ServiceInstancePreRegisteredEvent(serviceDiscovery, createInstance())); @@ -80,9 +80,9 @@ public void testOnEvent() throws Exception { listener.onEvent(new ServiceInstanceUnregisteredEvent(serviceDiscovery, createInstance())); // ServiceDiscoveryStoppingEvent - listener.onEvent(new ServiceDiscoveryDestroyingEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryDestroyingEvent(serviceDiscovery, serviceDiscovery)); // ServiceDiscoveryStoppedEvent - listener.onEvent(new ServiceDiscoveryDestroyedEvent(serviceDiscovery)); + listener.onEvent(new ServiceDiscoveryDestroyedEvent(serviceDiscovery, serviceDiscovery)); } } From 147c4773c804826234ed4d805de8fed314deadbb Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 15:05:38 +0800 Subject: [PATCH 49/55] Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native # Conflicts: # dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java # dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java --- .../org/apache/dubbo/bootstrap/DubboBootstrap.java | 10 +++++++--- .../dubbo/bootstrap/DubboServiceConsumerBootstrap.java | 1 + .../bootstrap/DubboServiceProvider2Bootstrap.java | 2 +- 3 files changed, 9 insertions(+), 4 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 b7df466335e..437024d9990 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 @@ -63,10 +63,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.SortedSet; -import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; @@ -75,6 +75,7 @@ import java.util.function.Consumer; import static java.util.Arrays.asList; +import static java.util.Collections.sort; 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; @@ -140,7 +141,7 @@ public class DubboBootstrap extends GenericEventListener implements Lifecycle { private volatile MetadataServiceExporter metadataServiceExporter; - private SortedSet serviceDiscoveries = new ConcurrentSkipListSet<>(); + private volatile List serviceDiscoveries = new LinkedList<>(); public DubboBootstrap() { DubboShutdownHook.getDubboShutdownHook().register(); @@ -153,7 +154,10 @@ public DubboBootstrap() { * @see {@linkplan org.apache.dubbo.registry.client.EventPublishingServiceDiscovery} */ public void onServiceDiscoveryInitializing(ServiceDiscoveryInitializingEvent event) { - serviceDiscoveries.add(event.getSource()); + executeMutually(() -> { + serviceDiscoveries.add(event.getSource()); + sort(serviceDiscoveries); + }); } /** 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 bf1fe0ae5f8..96a865f3f61 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 @@ -35,6 +35,7 @@ public static void main(String[] args) throws Exception { .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry.type=service&subscribed.services=dubbo-provider-demo")) // .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181")) // Nacos + .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-provider-demo")) // .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1")) .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo")) .reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest")) diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java index 83ea7a12ffd..15bb814c2ba 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java @@ -32,7 +32,7 @@ public static void main(String[] args) { // Zookeeper in service registry type .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")) // .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry.type=service").build()) .protocol("dubbo", builder -> builder.port(20885).name("dubbo")) .protocol("rest", builder -> builder.port(9090).name("rest")) From 39fca058ef5a7d531c7793d942c4d7d88629979a Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 15:49:19 +0800 Subject: [PATCH 50/55] Polish apache/dubbo#4854 : [Feature] MetadataService supports the Dubbo protocol under auto-increased port --- .../dubbo/bootstrap/DubboBootstrap.java | 14 ++-- .../ConfigurableMetadataServiceExporter.java | 67 +++++++++---------- .../dubbo/config/DubboProviderBootstrap.java | 4 +- ...nfigurableMetadataServiceExporterTest.java | 4 +- 4 files changed, 41 insertions(+), 48 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 437024d9990..7ab996875d8 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 @@ -588,11 +588,7 @@ private void initMetadataService() { * Initialize {@link MetadataServiceExporter} */ private void initMetadataServiceExporter() { - this.metadataServiceExporter = new ConfigurableMetadataServiceExporter() - .setApplicationConfig(getApplication()) - .setRegistries(configManager.getRegistries()) - .setProtocols(configManager.getProtocols()) - .metadataService(metadataService); + this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService); } /** @@ -768,12 +764,10 @@ public DubboBootstrap addEventListener(EventListener listener) { } /** - * export {@link MetadataService} and get the exported {@link URL URLs} - * - * @return {@link MetadataServiceExporter#getExportedURLs()} + * export {@link MetadataService} */ - private List exportMetadataService() { - return metadataServiceExporter.export().getExportedURLs(); + private void exportMetadataService() { + metadataServiceExporter.export(); } private void unexportMetadataService() { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java index b5ca2183c12..c59726a51aa 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java @@ -19,7 +19,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.config.AbstractConfig; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.RegistryConfig; @@ -28,14 +27,15 @@ import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.MetadataServiceExporter; -import java.util.Collection; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; +import static java.util.Arrays.asList; import static java.util.Collections.emptyList; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO; /** - * {@link MetadataServiceExporter} implementation based on {@link AbstractConfig Dubbo configurations}, the clients + * {@link MetadataServiceExporter} implementation based on {@link ConfigManager Dubbo configurations}, the clients * should make sure the {@link ApplicationConfig}, {@link RegistryConfig} and {@link ProtocolConfig} are ready before * {@link #export()}. *

    @@ -53,38 +53,15 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor private final Logger logger = LoggerFactory.getLogger(getClass()); - private ApplicationConfig applicationConfig; + private final ConfigManager configManager; - private List registries = new LinkedList<>(); - - private List protocols = new LinkedList<>(); - - private MetadataService metadataService; + private final MetadataService metadataService; private ServiceConfig serviceConfig; - public ConfigurableMetadataServiceExporter setApplicationConfig(ApplicationConfig applicationConfig) { - this.applicationConfig = applicationConfig; - return this; - } - - public ConfigurableMetadataServiceExporter setRegistries(Collection registries) { - this.registries.clear(); - this.registries.addAll(registries); - return this; - } - - public ConfigurableMetadataServiceExporter setProtocols(Collection protocols) { - this.protocols.clear(); - // TODO only support "dubbo" protocol, add more in the future - protocols.stream().filter(protocolConfig -> "dubbo".equals(protocolConfig.getName())) - .forEach(this.protocols::add); - return this; - } - - public ConfigurableMetadataServiceExporter metadataService(MetadataService metadataService) { + public ConfigurableMetadataServiceExporter(MetadataService metadataService) { + this.configManager = ConfigManager.getInstance(); this.metadataService = metadataService; - return this; } @Override @@ -93,12 +70,12 @@ public ConfigurableMetadataServiceExporter export() { if (!isExported()) { ServiceConfig serviceConfig = new ServiceConfig<>(); - serviceConfig.setApplication(applicationConfig); - serviceConfig.setRegistries(registries); - serviceConfig.setProtocols(protocols); + serviceConfig.setApplication(getApplicationConfig()); + serviceConfig.setRegistries(getRegistries()); + serviceConfig.setProtocols(getProtocols()); serviceConfig.setInterface(MetadataService.class); serviceConfig.setRef(metadataService); - serviceConfig.setGroup(applicationConfig.getName()); + serviceConfig.setGroup(getApplicationConfig().getName()); serviceConfig.setVersion(metadataService.version()); // export @@ -135,4 +112,24 @@ public List getExportedURLs() { public boolean isExported() { return serviceConfig != null && serviceConfig.isExported(); } + + private ApplicationConfig getApplicationConfig() { + return configManager.getApplication().get(); + } + + private List getRegistries() { + return new ArrayList<>(configManager.getRegistries()); + } + + private List getProtocols() { + return asList(getDefaultProtocol()); + } + + private ProtocolConfig getDefaultProtocol() { + ProtocolConfig defaultProtocol = new ProtocolConfig(); + defaultProtocol.setName(DUBBO); + // auto-increment port + defaultProtocol.setPort(-1); + return defaultProtocol; + } } diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java index 22530f85097..468bc977bd9 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java @@ -26,6 +26,8 @@ import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; +import static org.apache.dubbo.metadata.WritableMetadataService.getDefaultExtension; + /** * Dubbo Provider Bootstrap */ @@ -60,7 +62,7 @@ public static void main(String[] args) throws Exception { // 暴露及注册服务 service.export(); - MetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); + MetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(getDefaultExtension()); // 暴露 MetadataService 服务 exporter.export(); 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 1528b74cc0c..6cf5aba277e 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,6 +22,7 @@ import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -69,8 +70,7 @@ private static RegistryConfig registryConfig() { @Test public void testExportAndUnexport() { - ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(); - exporter.setApplicationConfig(ConfigManager.getInstance().getApplication().get()); + ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(new InMemoryWritableMetadataService()); List urls = exporter.export().getExportedURLs(); assertEquals(1, urls.size()); From 4ef7e30afdea4a5eca1b8964b4f0142646e8ed1d Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 16 Aug 2019 17:20:29 +0800 Subject: [PATCH 51/55] Polish apache/dubbo#4857 : [Enhancement] Sync the Metadata storage type into ApplicationConfig --- dubbo-all/pom.xml | 4 ++++ .../dubbo/bootstrap/DubboBootstrap.java | 10 ++++++++- .../DubboServiceProvider2Bootstrap.java | 5 ++++- .../DubboServiceProviderBootstrap.java | 6 +---- .../dubbo/config/ApplicationConfig.java | 11 +++++----- .../config/builders/ApplicationBuilder.java | 2 +- dubbo-registry/dubbo-registry-api/pom.xml | 8 +++++++ .../client/ServiceDiscoveryRegistry.java | 2 +- .../RefreshServiceMetadataCustomizer.java | 10 ++++----- .../ServiceInstanceMetadataUtils.java | 22 +++++++++++++++---- 10 files changed, 57 insertions(+), 23 deletions(-) diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml index dd687875505..35790a47d18 100644 --- a/dubbo-all/pom.xml +++ b/dubbo-all/pom.xml @@ -791,6 +791,10 @@ META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory + + META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery + + META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder 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 7ab996875d8..0c864c4188d 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 @@ -84,6 +84,7 @@ import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.context.ConfigManager.getInstance; import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; +import static org.apache.dubbo.metadata.WritableMetadataService.getMetadataStorageType; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType; import static org.apache.dubbo.remoting.Constants.CLIENT_KEY; @@ -455,6 +456,8 @@ public DubboBootstrap initialize() { useRegistryAsConfigCenterIfNecessary(); + initApplicationMetadata(); + initMetadataService(); initMetadataServiceExporter(); @@ -472,6 +475,11 @@ public DubboBootstrap initialize() { return this; } + private void initApplicationMetadata() { + String metadataStorageType = getMetadataStorageType(isDefaultMetadataStorageType()); + getApplication().setMetadataStorageType(metadataStorageType); + } + private void startConfigCenter() { Collection configCenters = configManager.getConfigCenters(); @@ -491,7 +499,7 @@ private void startMetadataReport() { () -> new IllegalStateException("There's no ApplicationConfig specified.") ); - String metadataType = applicationConfig.getMetadata(); + String metadataType = applicationConfig.getMetadataStorageType(); // FIXME, multiple metadata config support. Collection metadataReportConfigs = configManager.getMetadataConfigs(); if (CollectionUtils.isEmpty(metadataReportConfigs)) { diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java index 15bb814c2ba..03b9e1d8259 100644 --- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java @@ -18,6 +18,7 @@ import org.apache.dubbo.bootstrap.rest.UserService; import org.apache.dubbo.bootstrap.rest.UserServiceImpl; +import org.apache.dubbo.config.MetadataReportConfig; /** * Dubbo Provider Bootstrap @@ -28,12 +29,14 @@ public class DubboServiceProvider2Bootstrap { public static void main(String[] args) { new DubboBootstrap() + .defaultMetadataStorageType(false) .application("dubbo-provider-demo") // Zookeeper in service registry type .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")) // .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry.type=service").build()) + .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181")) .protocol("dubbo", builder -> builder.port(20885).name("dubbo")) .protocol("rest", builder -> builder.port(9090).name("rest")) .service(builder -> builder.id("echo").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo")) 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 d0b7e4a2464..8dabb16f261 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 @@ -25,10 +25,6 @@ import org.apache.dubbo.config.ServiceConfig; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY; /** * Dubbo Provider Bootstrap @@ -67,7 +63,7 @@ private static void multipleRegistries() { // userService.setRegistries(Arrays.asList(interfaceRegistry, serviceRegistry)); ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-provider-demo"); - applicationConfig.setMetadata("remote"); + applicationConfig.setMetadataStorageType("remote"); new DubboBootstrap() .application(applicationConfig) // Zookeeper in service registry type 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 535a1829102..9880c23b400 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 @@ -150,7 +150,7 @@ public class ApplicationConfig extends AbstractConfig { /** * Metadata type, local or remote, if choose remote, you need to further specify metadata center. */ - private String metadata; + private String metadataStorageType; public ApplicationConfig() { } @@ -334,6 +334,7 @@ public void setQosAcceptForeignIp(Boolean qosAcceptForeignIp) { /** * The format is the same as the springboot, including: getQosEnableCompatible(), getQosPortCompatible(), getQosAcceptForeignIpCompatible(). + * * @return */ @Parameter(key = QOS_ENABLE_COMPATIBLE, excluded = true) @@ -387,12 +388,12 @@ public boolean isValid() { return !StringUtils.isEmpty(name); } - public String getMetadata() { - return metadata; + public String getMetadataStorageType() { + return metadataStorageType; } - public void setMetadata(String metadata) { - this.metadata = metadata; + public void setMetadataStorageType(String metadataStorageType) { + this.metadataStorageType = metadataStorageType; } @Override diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java index f4a804745c1..5f6f99992d8 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java @@ -177,7 +177,7 @@ public ApplicationConfig build() { super.build(config); config.setName(name); - config.setMetadata(metadata); + config.setMetadataStorageType(metadata); config.setVersion(this.version); config.setOwner(this.owner); config.setOrganization(this.organization); diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml index 9d47281f8e7..d66a2440778 100644 --- a/dubbo-registry/dubbo-registry-api/pom.xml +++ b/dubbo-registry/dubbo-registry-api/pom.xml @@ -31,11 +31,19 @@ false + org.apache.dubbo dubbo-common ${project.parent.version} + + + org.apache.dubbo + dubbo-config-api + ${project.parent.version} + + org.apache.dubbo dubbo-cluster diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index 725963af5da..fd86ab62375 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -156,7 +156,7 @@ private ServiceDiscovery getServiceDiscovery(URL registryURL) { private ServiceDiscovery enhanceEventPublishing(ServiceDiscovery original) { return new EventPublishingServiceDiscovery(original); } - + protected boolean shouldRegister(URL providerURL) { String side = providerURL.getParameter(SIDE_KEY); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java index 32657097318..62b5a99f393 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java @@ -4,7 +4,7 @@ import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.ServiceInstanceCustomizer; -import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_EXTENSION; +import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getSubscribedServicesRevision; @@ -22,12 +22,12 @@ public int getPriority() { @Override public void customize(ServiceInstance serviceInstance) { - // FIXME to define the constant + String metadataStoredType = getMetadataStorageType(serviceInstance); - WritableMetadataService remoteWritableMetadataService = - WritableMetadataService.getExtension(metadataStoredType == null ? DEFAULT_EXTENSION : metadataStoredType); - remoteWritableMetadataService.refreshMetadata(getExportedServicesRevision(serviceInstance), + WritableMetadataService writableMetadataService = getExtension(metadataStoredType); + + writableMetadataService.refreshMetadata(getExportedServicesRevision(serviceInstance), getSubscribedServicesRevision(serviceInstance)); } } 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 78402633e56..93678618975 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 @@ -17,6 +17,8 @@ package org.apache.dubbo.registry.client.metadata; import org.apache.dubbo.common.URL; +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.registry.client.ServiceInstance; @@ -187,10 +189,10 @@ public static String getSubscribedServicesRevision(ServiceInstance serviceInstan * * @param registryURL the {@link URL} to connect the registry * @return if not found in {@link URL#getParameters() parameters} of {@link URL registry URL}, return - * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"} + * {@link #getDefaultMetadataStorageType()} */ public static String getMetadataStorageType(URL registryURL) { - return registryURL.getParameter(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE); + return registryURL.getParameter(METADATA_STORAGE_TYPE_KEY, getDefaultMetadataStorageType()); } /** @@ -198,11 +200,23 @@ public static String getMetadataStorageType(URL registryURL) { * * @param serviceInstance the specified {@link ServiceInstance} * @return if not found in {@link ServiceInstance#getMetadata() metadata} of {@link ServiceInstance}, return - * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"} + * {@link #getDefaultMetadataStorageType()} */ public static String getMetadataStorageType(ServiceInstance serviceInstance) { Map metadata = serviceInstance.getMetadata(); - return metadata.getOrDefault(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE); + return metadata.getOrDefault(METADATA_STORAGE_TYPE_KEY, getDefaultMetadataStorageType()); + } + + /** + * Get the default Metadata storage type from {@link ApplicationConfig} if present, or + * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"} + * + * @return non-null + */ + public static String getDefaultMetadataStorageType() { + return ConfigManager.getInstance().getApplication() + .map(ApplicationConfig::getMetadataStorageType) + .orElse(DEFAULT_METADATA_STORAGE_TYPE); } /** From 64c3425c90735a4e0332617b3c165211842d0c0c Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 19 Aug 2019 14:02:49 +0800 Subject: [PATCH 52/55] Polish apache/dubbo#4868 : [Enhancement] Refactor ConfigChangeEvent --- .../condition/config/ListenableRouter.java | 12 ++-- .../rpc/cluster/router/tag/TagRouter.java | 10 +-- ...angeEvent.java => ConfigChangedEvent.java} | 26 ++++--- .../configcenter/ConfigurationListener.java | 2 +- .../file/FileSystemDynamicConfiguration.java | 68 +++++++++++++------ .../apollo/ApolloDynamicConfiguration.java | 4 +- .../consul/ConsulDynamicConfiguration.java | 30 ++++---- .../etcd/EtcdDynamicConfiguration.java | 21 +++--- .../etcd/EtcdDynamicConfigurationTest.java | 6 +- .../nacos/NacosDynamicConfiguration.java | 4 +- .../nacos/NacosDynamicConfigurationTest.java | 6 +- .../support/zookeeper/CacheListener.java | 17 ++++- .../ZookeeperDynamicConfigurationTest.java | 6 +- .../AbstractConfiguratorListener.java | 8 +-- 14 files changed, 136 insertions(+), 84 deletions(-) rename dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/{ConfigChangeEvent.java => ConfigChangedEvent.java} (69%) diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java index 41044ec3fea..74dfce22c33 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java @@ -17,8 +17,8 @@ package org.apache.dubbo.rpc.cluster.router.condition.config; 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.logger.Logger; @@ -56,10 +56,10 @@ public ListenableRouter(URL url, String ruleKey) { } @Override - public synchronized void process(ConfigChangeEvent event) { + public synchronized void process(ConfigChangedEvent event) { if (logger.isInfoEnabled()) { logger.info("Notification of condition rule, change type is: " + event.getChangeType() + - ", raw rule is:\n " + event.getValue()); + ", raw rule is:\n " + event.getContent()); } if (event.getChangeType().equals(ConfigChangeType.DELETED)) { @@ -67,11 +67,11 @@ public synchronized void process(ConfigChangeEvent event) { conditionRouters = Collections.emptyList(); } else { try { - routerRule = ConditionRuleParser.parse(event.getValue()); + routerRule = ConditionRuleParser.parse(event.getContent()); generateConditions(routerRule); } catch (Exception e) { logger.error("Failed to parse the raw condition rule and it will not take effect, please check " + - "if the condition rule matches with the template, the raw rule is:\n " + event.getValue(), e); + "if the condition rule matches with the template, the raw rule is:\n " + event.getContent(), e); } } } @@ -121,7 +121,7 @@ private synchronized void init(String ruleKey) { ruleRepository.addListener(routerKey, this); String rule = ruleRepository.getRule(routerKey, DynamicConfiguration.DEFAULT_GROUP); if (StringUtils.isNotEmpty(rule)) { - this.process(new ConfigChangeEvent(routerKey, rule)); + this.process(new ConfigChangedEvent(routerKey, DynamicConfiguration.DEFAULT_GROUP, rule)); } } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java index 05b1a113a7a..46b8d9f2ba7 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java @@ -17,8 +17,8 @@ package org.apache.dubbo.rpc.cluster.router.tag; 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.constants.CommonConstants; @@ -61,17 +61,17 @@ public TagRouter(URL url) { } @Override - public synchronized void process(ConfigChangeEvent event) { + public synchronized void process(ConfigChangedEvent event) { if (logger.isDebugEnabled()) { logger.debug("Notification of tag rule, change type is: " + event.getChangeType() + ", raw rule is:\n " + - event.getValue()); + event.getContent()); } try { if (event.getChangeType().equals(ConfigChangeType.DELETED)) { this.tagRouterRule = null; } else { - this.tagRouterRule = TagRuleParser.parse(event.getValue()); + this.tagRouterRule = TagRuleParser.parse(event.getContent()); } } catch (Exception e) { logger.error("Failed to parse the raw tag router rule and it will not take effect, please check if the " + @@ -251,7 +251,7 @@ public void notify(List> invokers) { application = providerApplication; String rawRule = ruleRepository.getRule(key, DynamicConfiguration.DEFAULT_GROUP); if (StringUtils.isNotEmpty(rawRule)) { - this.process(new ConfigChangeEvent(key, rawRule)); + this.process(new ConfigChangedEvent(key, DynamicConfiguration.DEFAULT_GROUP, rawRule)); } } } 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/ConfigChangedEvent.java similarity index 69% rename from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java index 177551be929..20cd874a3f1 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/ConfigChangedEvent.java @@ -19,25 +19,29 @@ import java.util.EventObject; /** - * Config change event, immutable. + * An event raised when the config changed, immutable. * * @see ConfigChangeType */ -public class ConfigChangeEvent extends EventObject { +public class ConfigChangedEvent extends EventObject { + private final String key; - private final String value; + private final String group; + + private final String content; private final ConfigChangeType changeType; - public ConfigChangeEvent(String key, String value) { - this(key, value, ConfigChangeType.MODIFIED); + public ConfigChangedEvent(String key, String group, String content) { + this(key, group, content, ConfigChangeType.MODIFIED); } - public ConfigChangeEvent(String key, String value, ConfigChangeType changeType) { - super(key + "=" + value); + public ConfigChangedEvent(String key, String group, String content, ConfigChangeType changeType) { + super(key + "=" + content); this.key = key; - this.value = value; + this.group = group; + this.content = content; this.changeType = changeType; } @@ -45,8 +49,8 @@ public String getKey() { return key; } - public String getValue() { - return value; + public String getContent() { + return content; } public ConfigChangeType getChangeType() { @@ -57,7 +61,7 @@ public ConfigChangeType getChangeType() { public String toString() { return "ConfigChangeEvent{" + "key='" + key + '\'' + - ", value='" + value + '\'' + + ", value='" + content + '\'' + ", 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 2a1779a383d..33e9f1bd156 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 @@ -29,5 +29,5 @@ public interface ConfigurationListener extends EventListener { * * @param event config change event */ - void process(ConfigChangeEvent event); + void process(ConfigChangedEvent event); } 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 45c2b6bb95b..603356d66f0 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 @@ -18,13 +18,14 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration; -import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; import org.apache.dubbo.common.config.configcenter.ConfigChangeType; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; 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 org.apache.dubbo.common.utils.StringUtils; import com.sun.nio.file.SensitivityWatchEventModifier; import org.apache.commons.io.FileUtils; @@ -84,7 +85,7 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration 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_THREAD_POOL_SIZE = "1"; + public static final int DEFAULT_THREAD_POOL_SIZE = 1; public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8"; @@ -158,7 +159,7 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration private final String encoding; /** - * The {@link Set} of {@link #configDirectory(String) directories} that may be processing, + * The {@link Set} of {@link #groupDirectory(String) directories} that may be processing, *

    * if {@link #isBasedPoolingWatchService()} is false, this properties will be * {@link Collections#emptySet() empty} @@ -170,12 +171,24 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration private final Map> listenersRepository; public FileSystemDynamicConfiguration() { - this(URL.valueOf("file:///default")); + this(new File(DEFAULT_CONFIG_CENTER_DIR_PATH)); } - public FileSystemDynamicConfiguration(URL url) { - this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url), - getThreadPoolKeepAliveTime(url)); + public FileSystemDynamicConfiguration(File rootDirectory) { + this(rootDirectory, DEFAULT_CONFIG_CENTER_ENCODING); + } + + public FileSystemDynamicConfiguration(File rootDirectory, String encoding) { + this(rootDirectory, encoding, DEFAULT_THREAD_POOL_PREFIX); + } + + public FileSystemDynamicConfiguration(File rootDirectory, String encoding, String threadPoolPrefixName) { + this(rootDirectory, encoding, threadPoolPrefixName, DEFAULT_THREAD_POOL_SIZE); + } + + public FileSystemDynamicConfiguration(File rootDirectory, String encoding, String threadPoolPrefixName, + int threadPoolSize) { + this(rootDirectory, encoding, threadPoolPrefixName, threadPoolSize, DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME); } public FileSystemDynamicConfiguration(File rootDirectory, String encoding, @@ -189,6 +202,11 @@ public FileSystemDynamicConfiguration(File rootDirectory, String encoding, this.listenersRepository = new LinkedHashMap<>(); } + public FileSystemDynamicConfiguration(URL url) { + this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url), + getThreadPoolKeepAliveTime(url)); + } + private Set initProcessingDirectories() { return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet(); } @@ -222,13 +240,13 @@ public void removeListener(String key, String group, ConfigurationListener liste }); } - protected File configDirectory(String group) { + public File groupDirectory(String group) { String actualGroup = isBlank(group) ? DEFAULT_GROUP : group; return new File(rootDirectory, actualGroup); } - protected File configFile(String key, String group) { - return new File(configDirectory(group), key); + public File configFile(String key, String group) { + return new File(groupDirectory(group), key); } private void doInListener(String key, String group, BiConsumer> consumer) { @@ -275,7 +293,7 @@ private void processWatchEvents(WatchService watchService) { Path configFilePath = configDirectoryPath.resolve(currentPath); File configDirectory = configDirectoryPath.toFile(); executeMutually(configDirectory, () -> { - fireConfigChangeEvent(configFilePath.toFile(), configChangeType); + fireConfigChangeEvent(configDirectory, configFilePath.toFile(), configChangeType); signalConfigDirectory(configDirectory); return null; }); @@ -318,13 +336,13 @@ private List getListeners(File configFile) { return listenersRepository.computeIfAbsent(configFile, p -> new LinkedList<>()); } - private void fireConfigChangeEvent(File configFile, ConfigChangeType configChangeType) { + private void fireConfigChangeEvent(File configDirectory, File configFile, ConfigChangeType configChangeType) { String key = configFile.getName(); String value = getConfig(configFile); // fire ConfigChangeEvent one by one getListeners(configFile).forEach(listener -> { try { - listener.process(new ConfigChangeEvent(key, value, configChangeType)); + listener.process(new ConfigChangedEvent(key, configDirectory.getName(), value, configChangeType)); } catch (Throwable e) { if (logger.isErrorEnabled()) { logger.error(e.getMessage(), e); @@ -412,9 +430,9 @@ private boolean hasListeners(File configFile) { } /** - * Is processing on {@link #configDirectory(String) config rootDirectory} + * Is processing on {@link #groupDirectory(String) config rootDirectory} * - * @param configDirectory {@link #configDirectory(String) config rootDirectory} + * @param configDirectory {@link #groupDirectory(String) config rootDirectory} * @return if processing , return true, or false */ private boolean isProcessing(File configDirectory) { @@ -427,7 +445,7 @@ private void addProcessing(File configDirectory) { @Override public SortedSet getConfigKeys(String group) { - return Stream.of(configDirectory(group).listFiles(File::isFile)) + return Stream.of(groupDirectory(group).listFiles(File::isFile)) .map(File::getName) .collect(TreeSet::new, Set::add, Set::addAll); } @@ -462,11 +480,11 @@ protected void doClose() throws Exception { } - protected File getRootDirectory() { + public File getRootDirectory() { return rootDirectory; } - protected String getEncoding() { + public String getEncoding() { return encoding; } @@ -559,11 +577,19 @@ private static Optional newWatchService() { } protected static File initDirectory(URL url) { - 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)); + String directoryPath = url.getParameter(CONFIG_CENTER_DIR_PARAM_NAME, url.getPath()); + File rootDirectory = null; + if (!StringUtils.isBlank(directoryPath)) { + rootDirectory = new File("/" + directoryPath); + } + + if (!rootDirectory.exists()) { // If the directory does not exist + rootDirectory = new File(DEFAULT_CONFIG_CENTER_DIR_PATH); + } + if (!rootDirectory.exists() && !rootDirectory.mkdirs()) { throw new IllegalStateException(format("Dubbo config center rootDirectory[%s] can't be created!", - directoryPath)); + rootDirectory.getAbsolutePath())); } return rootDirectory; } diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java index 603dd73601e..1c5d638b361 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java @@ -17,8 +17,8 @@ package org.apache.dubbo.configcenter.support.apollo; 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.logger.Logger; @@ -200,7 +200,7 @@ public void onChange(com.ctrip.framework.apollo.model.ConfigChangeEvent changeEv return; } - ConfigChangeEvent event = new ConfigChangeEvent(key, change.getNewValue(), getChangeType(change)); + ConfigChangedEvent event = new ConfigChangedEvent(key, change.getNamespace(), change.getNewValue(), getChangeType(change)); listeners.forEach(listener -> listener.process(event)); } } diff --git a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java index e6d5c745ab6..c981381ddcf 100644 --- a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java @@ -18,8 +18,8 @@ package org.apache.dubbo.configcenter.consul; 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.logger.Logger; @@ -75,7 +75,7 @@ public ConsulDynamicConfiguration(URL url) { public void addListener(String key, String group, ConfigurationListener listener) { logger.info("register listener " + listener.getClass() + " for config with key: " + key + ", group: " + group); String normalizedKey = convertKey(group, key); - ConsulKVWatcher watcher = watchers.putIfAbsent(normalizedKey, new ConsulKVWatcher(normalizedKey)); + ConsulKVWatcher watcher = watchers.putIfAbsent(normalizedKey, new ConsulKVWatcher(key, group)); if (watcher == null) { watcher = watchers.get(normalizedKey); watcherService.submit(watcher); @@ -133,21 +133,25 @@ private int buildWatchTimeout(URL url) { } private class ConsulKVWatcher implements Runnable { - private String key; + private final String key; + private final String group; + private final String normalizedKey; private Set listeners; private boolean running = true; private boolean existing = false; - public ConsulKVWatcher(String key) { + public ConsulKVWatcher(String key, String group) { this.key = key; + this.group = group; + this.normalizedKey = convertKey(group, key); this.listeners = new HashSet<>(); } @Override public void run() { while (running) { - Long lastIndex = consulIndexes.computeIfAbsent(key, k -> -1L); - Response response = getValue(key); + Long lastIndex = consulIndexes.computeIfAbsent(normalizedKey, k -> -1L); + Response response = getValue(normalizedKey); if (response == null) { try { Thread.sleep(watchTimeout); @@ -164,20 +168,20 @@ public void run() { } consulIndexes.put(key, currentIndex); - ConfigChangeEvent event = null; + ConfigChangedEvent event = null; if (getValue != null) { String value = getValue.getDecodedValue(); if (existing) { - logger.info("notify change for key: " + key + ", the changed value is: " + value); - event = new ConfigChangeEvent(key, value); + logger.info("notify change for key: " + normalizedKey + ", the changed value is: " + value); + event = new ConfigChangedEvent(key, group, value); } else { - logger.info("notify change for key: " + key + ", the added value is: " + value); - event = new ConfigChangeEvent(key, value, ADDED); + logger.info("notify change for key: " + normalizedKey + ", the added value is: " + value); + event = new ConfigChangedEvent(key, group, value, ADDED); } } else { if (existing) { - logger.info("notify change for key: " + key + ", the value is deleted"); - event = new ConfigChangeEvent(key, null, ConfigChangeType.DELETED); + logger.info("notify change for key: " + normalizedKey + ", the value is deleted"); + event = new ConfigChangedEvent(key, group, null, ConfigChangeType.DELETED); } } diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java index 356161a67fe..f686e860331 100644 --- a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java @@ -18,8 +18,8 @@ package org.apache.dubbo.configcenter.support.etcd; 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.utils.StringUtils; @@ -81,8 +81,7 @@ public class EtcdDynamicConfiguration implements DynamicConfiguration { @Override public void addListener(String key, String group, ConfigurationListener listener) { if (watchListenerMap.get(listener) == null) { - String normalizedKey = convertKey(group, key); - EtcdConfigWatcher watcher = new EtcdConfigWatcher(normalizedKey, listener); + EtcdConfigWatcher watcher = new EtcdConfigWatcher(key, group, listener); watchListenerMap.put(listener, watcher); watcher.watch(); } @@ -134,10 +133,17 @@ public class EtcdConfigWatcher implements StreamObserver { private StreamObserver observer; protected long watchId; private ManagedChannel channel; - private String key; - public EtcdConfigWatcher(String key, ConfigurationListener listener) { + private final String key; + + private final String group; + + private String normalizedKey; + + public EtcdConfigWatcher(String key, String group, ConfigurationListener listener) { this.key = key; + this.group = group; + this.normalizedKey = convertKey(group, key); this.listener = listener; this.channel = etcdClient.getChannel(); } @@ -150,8 +156,7 @@ public void onNext(WatchResponse watchResponse) { if (etcdEvent.getType() == Event.EventType.DELETE) { type = ConfigChangeType.DELETED; } - ConfigChangeEvent event = new ConfigChangeEvent( - etcdEvent.getKv().getKey().toString(UTF_8), + ConfigChangedEvent event = new ConfigChangedEvent(key, group, etcdEvent.getKv().getValue().toString(UTF_8), type); listener.process(event); } @@ -175,7 +180,7 @@ private void watch() { watchStub = WatchGrpc.newStub(channel); observer = watchStub.watch(this); WatchCreateRequest.Builder builder = WatchCreateRequest.newBuilder() - .setKey(ByteString.copyFromUtf8(key)) + .setKey(ByteString.copyFromUtf8(normalizedKey)) .setProgressNotify(true); WatchRequest req = WatchRequest.newBuilder().setCreateRequest(builder).build(); observer.onNext(req); diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java index c0ea8c39dac..86dd306bf81 100644 --- a/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java @@ -18,7 +18,7 @@ package org.apache.dubbo.configcenter.support.etcd; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; @@ -104,10 +104,10 @@ public TestListener(CountDownLatch latch) { } @Override - public void process(ConfigChangeEvent event) { + public void process(ConfigChangedEvent event) { Integer count = countMap.computeIfAbsent(event.getKey(), k -> 0); countMap.put(event.getKey(), ++count); - value = event.getValue(); + value = event.getContent(); latch.countDown(); } 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 5b4052709df..b82c8e72dfb 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 @@ -18,8 +18,8 @@ package org.apache.dubbo.configcenter.support.nacos; 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.logger.Logger; @@ -231,7 +231,7 @@ public Executor getExecutor() { @Override public void innerReceive(String dataId, String group, String configInfo) { String oldValue = cacheData.get(dataId); - ConfigChangeEvent event = new ConfigChangeEvent(dataId, configInfo, getChangeType(configInfo, oldValue)); + ConfigChangedEvent event = new ConfigChangedEvent(dataId, group, configInfo, getChangeType(configInfo, oldValue)); if (configInfo == null) { cacheData.remove(dataId); } else { diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java index a5ed3e7589e..350936c2c03 100644 --- a/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java @@ -18,7 +18,7 @@ package org.apache.dubbo.configcenter.support.nacos; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; @@ -142,11 +142,11 @@ public TestListener(CountDownLatch latch) { } @Override - public void process(ConfigChangeEvent event) { + public void process(ConfigChangedEvent event) { System.out.println(this + ": " + event); Integer count = countMap.computeIfAbsent(event.getKey(), k -> 0); countMap.put(event.getKey(), ++count); - value = event.getValue(); + value = event.getContent(); latch.countDown(); } diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java index be24cc2cba7..a0acd51ef4d 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java @@ -16,8 +16,8 @@ */ package org.apache.dubbo.configcenter.support.zookeeper; -import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; import org.apache.dubbo.common.config.configcenter.ConfigChangeType; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.StringUtils; @@ -76,6 +76,19 @@ private String pathToKey(String path) { return groupKey.substring(groupKey.indexOf(DOT_SEPARATOR) + 1); } + private String getGroup(String path) { + if (!StringUtils.isEmpty(path)) { + int beginIndex = path.indexOf(rootPath + PATH_SEPARATOR); + if (beginIndex > -1) { + int endIndex = path.indexOf(PATH_SEPARATOR, beginIndex); + if (endIndex > beginIndex) { + return path.substring(beginIndex, endIndex); + } + } + } + return path; + } + @Override public void dataChanged(String path, Object value, EventType eventType) { @@ -111,7 +124,7 @@ public void dataChanged(String path, Object value, EventType eventType) { return; } - ConfigChangeEvent configChangeEvent = new ConfigChangeEvent(key, (String) value, changeType); + ConfigChangedEvent configChangeEvent = new ConfigChangedEvent(key, getGroup(path), (String) value, changeType); Set listeners = keyListeners.get(path); if (CollectionUtils.isNotEmpty(listeners)) { listeners.forEach(listener -> listener.process(configChangeEvent)); diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java index b2d03fc31f4..284c77a2c50 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java @@ -17,7 +17,7 @@ package org.apache.dubbo.configcenter.support.zookeeper; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; @@ -170,12 +170,12 @@ public TestListener(CountDownLatch latch) { } @Override - public void process(ConfigChangeEvent event) { + public void process(ConfigChangedEvent event) { System.out.println(this + ": " + event); Integer count = countMap.computeIfAbsent(event.getKey(), k -> new Integer(0)); countMap.put(event.getKey(), ++count); - value = event.getValue(); + value = event.getContent(); latch.countDown(); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java index cf774ab83f8..53fa81a0011 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java @@ -16,8 +16,8 @@ */ package org.apache.dubbo.registry.integration; -import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent; import org.apache.dubbo.common.config.configcenter.ConfigChangeType; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.extension.ExtensionLoader; @@ -50,16 +50,16 @@ protected final void initWith(String key) { } @Override - public void process(ConfigChangeEvent event) { + public void process(ConfigChangedEvent event) { if (logger.isInfoEnabled()) { logger.info("Notification of overriding rule, change type is: " + event.getChangeType() + - ", raw config content is:\n " + event.getValue()); + ", raw config content is:\n " + event.getContent()); } if (event.getChangeType().equals(ConfigChangeType.DELETED)) { configurators.clear(); } else { - if (!genConfiguratorsFromRawRule(event.getValue())) { + if (!genConfiguratorsFromRawRule(event.getContent())) { return; } } From 940452ef8147ccf20c7faa27617e0e2a27fc42c3 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 19 Aug 2019 14:18:22 +0800 Subject: [PATCH 53/55] Polish apache/dubbo#4868 : [Enhancement] Refactor ConfigChangeEvent --- .../configcenter/ConfigChangedEvent.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java index 20cd874a3f1..8ea32e27302 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.config.configcenter; import java.util.EventObject; +import java.util.Objects; /** * An event raised when the config changed, immutable. @@ -49,6 +50,10 @@ public String getKey() { return key; } + public String getGroup() { + return group; + } + public String getContent() { return content; } @@ -57,12 +62,29 @@ public ConfigChangeType getChangeType() { return changeType; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ConfigChangedEvent)) return false; + ConfigChangedEvent that = (ConfigChangedEvent) o; + return Objects.equals(getKey(), that.getKey()) && + Objects.equals(group, that.group) && + Objects.equals(getContent(), that.getContent()) && + getChangeType() == that.getChangeType(); + } + + @Override + public int hashCode() { + return Objects.hash(getKey(), group, getContent(), getChangeType()); + } + @Override public String toString() { - return "ConfigChangeEvent{" + + return "ConfigChangedEvent{" + "key='" + key + '\'' + - ", value='" + content + '\'' + + ", group='" + group + '\'' + + ", content='" + content + '\'' + ", changeType=" + changeType + - '}'; + "} " + super.toString(); } } From f676f5e8b449adb9641af34572a9e4554e7b3449 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 19 Aug 2019 15:35:14 +0800 Subject: [PATCH 54/55] Polish apache/dubbo#4873 : [Feature] Add a conditional EventListener into Event Module --- .../dubbo/event/AbstractEventDispatcher.java | 7 ++ .../dubbo/event/ConditionalEventListener.java | 35 +++++++++ .../event/ConditionalEventListenerTest.java | 73 +++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 dubbo-event/src/main/java/org/apache/dubbo/event/ConditionalEventListener.java create mode 100644 dubbo-event/src/test/java/org/apache/dubbo/event/ConditionalEventListenerTest.java diff --git a/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java b/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java index a2182ebe3c6..80ba3bde048 100644 --- a/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java +++ b/dubbo-event/src/main/java/org/apache/dubbo/event/AbstractEventDispatcher.java @@ -119,6 +119,13 @@ public void dispatch(Event event) { executor.execute(() -> { sortedListeners(entry -> entry.getKey().isAssignableFrom(event.getClass())) .forEach(listener -> { + if (listener instanceof ConditionalEventListener) { + ConditionalEventListener predicateEventListener = (ConditionalEventListener) listener; + if (!predicateEventListener.accept(event)) { // No accept + return; + } + } + // Handle the event listener.onEvent(event); }); }); diff --git a/dubbo-event/src/main/java/org/apache/dubbo/event/ConditionalEventListener.java b/dubbo-event/src/main/java/org/apache/dubbo/event/ConditionalEventListener.java new file mode 100644 index 00000000000..3c6fce92ab4 --- /dev/null +++ b/dubbo-event/src/main/java/org/apache/dubbo/event/ConditionalEventListener.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.event; + +/** + * An {@link EventListener} extending the the conditional feature that {@link #accept(Event) decides} some + * {@link Event event} is handled or not by current listener. + * + * @see EventListener + * @since 2.7.4 + */ +public interface ConditionalEventListener extends EventListener { + + /** + * Accept the event is handled or not by current listener + * + * @param event {@link Event event} + * @return if handled, return true, or false + */ + boolean accept(E event); +} diff --git a/dubbo-event/src/test/java/org/apache/dubbo/event/ConditionalEventListenerTest.java b/dubbo-event/src/test/java/org/apache/dubbo/event/ConditionalEventListenerTest.java new file mode 100644 index 00000000000..ad196f5a153 --- /dev/null +++ b/dubbo-event/src/test/java/org/apache/dubbo/event/ConditionalEventListenerTest.java @@ -0,0 +1,73 @@ +/* + * 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.event; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * {@link ConditionalEventListener} test + * + * @since 2.7.4 + */ +public class ConditionalEventListenerTest { + + private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + + @BeforeEach + public void init() { + eventDispatcher.removeAllEventListeners(); + } + + @Test + public void testOnEvent() { + + OnlyHelloWorldEventListener listener = new OnlyHelloWorldEventListener(); + + eventDispatcher.addEventListener(listener); + + eventDispatcher.dispatch(new EchoEvent("1")); + + assertNull(listener.getSource()); + + eventDispatcher.dispatch(new EchoEvent("Hello,World")); + + assertEquals("Hello,World", listener.getSource()); + } + + static class OnlyHelloWorldEventListener implements ConditionalEventListener { + + private String source; + + @Override + public boolean accept(EchoEvent event) { + return "Hello,World".equals(event.getSource()); + } + + @Override + public void onEvent(EchoEvent event) { + source = (String) event.getSource(); + } + + public String getSource() { + return source; + } + } +} From 4356c52a4ec01c07725b7a0d9711e0f99d272846 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 19 Aug 2019 16:05:16 +0800 Subject: [PATCH 55/55] Polish apache/dubbo#4875 : [Feature] Refactor ServiceInstancesChangedListener --- .../DubboServiceConsumerBootstrap.java | 6 +- .../DubboServiceProviderMinimumBootstrap.java | 34 ++++ .../client/DefaultServiceInstance.java | 23 ++- .../EventPublishingServiceDiscovery.java | 4 +- .../client/FileSystemServiceDiscovery.java | 155 +++++++++++++++--- .../registry/client/ServiceDiscovery.java | 15 +- .../client/ServiceDiscoveryRegistry.java | 10 +- .../registry/client/ServiceInstance.java | 3 +- .../ServiceInstancesChangedListener.java | 30 +++- .../client/DefaultServiceInstanceTest.java | 3 +- .../FileSystemServiceDiscoveryTest.java | 60 +++++++ .../client/InMemoryServiceDiscovery.java | 6 - .../ServiceInstancesChangedListenerTest.java | 7 +- ...efaultServiceInstanceDeserializerTest.java | 58 +++++++ .../consul/ConsulServiceDiscovery.java | 6 - .../registry/etcd/EtcdServiceDiscovery.java | 6 +- .../registry/nacos/NacosServiceDiscovery.java | 4 +- .../zookeeper/ZookeeperServiceDiscovery.java | 4 +- .../ZookeeperServiceDiscoveryTest.java | 11 +- 19 files changed, 383 insertions(+), 62 deletions(-) create mode 100644 dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderMinimumBootstrap.java create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/FileSystemServiceDiscoveryTest.java create mode 100644 dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/fastjson/DefaultServiceInstanceDeserializerTest.java 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 e765643f111..275d01995c6 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,7 +16,6 @@ */ package org.apache.dubbo.bootstrap; -import org.apache.dubbo.bootstrap.rest.UserService; import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.context.ConfigManager; @@ -33,13 +32,14 @@ public static void main(String[] args) throws Exception { .application("dubbo-consumer-demo") .protocol(builder -> builder.port(20887).name("dubbo")) // 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")) + .registry("file",builder-> builder.address("file://1111?registry.type=service&subscribed.services=dubbo-provider-demo")) // .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181")) // Nacos // .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-provider-demo")) // .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1")) .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo")) - .reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest")) +// .reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest")) .onlyRegisterProvider(true) .start() .await(); diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderMinimumBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderMinimumBootstrap.java new file mode 100644 index 00000000000..c0764e8f609 --- /dev/null +++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderMinimumBootstrap.java @@ -0,0 +1,34 @@ +/* + * 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; + +/** + * TODO + */ +public class DubboServiceProviderMinimumBootstrap { + + public static void main(String[] args) { + new DubboBootstrap() + .application("dubbo-provider-demo") +// .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry.type=service")) + .registry(builder -> builder.address("file://?registry.type=service")) + .protocol(builder -> builder.port(-1).name("dubbo")) + .service(builder -> builder.interfaceClass(EchoService.class).ref(new EchoServiceImpl())) + .start() + .await(); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java index 8e28adf5371..b9f5da7be98 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java @@ -27,11 +27,13 @@ */ public class DefaultServiceInstance implements ServiceInstance { - private final String id; + private static final long serialVersionUID = 1149677083747278100L; - private final String serviceName; + private String id; - private final String host; + private String serviceName; + + private String host; private Integer port; @@ -41,6 +43,9 @@ public class DefaultServiceInstance implements ServiceInstance { private Map metadata = new HashMap<>(); + public DefaultServiceInstance() { + } + public DefaultServiceInstance(String id, String serviceName, String host, Integer port) { if (port != null && port.intValue() < 1) { throw new IllegalArgumentException("The port must be greater than zero!"); @@ -57,6 +62,18 @@ public DefaultServiceInstance(String serviceName, String host, Integer port) { this(null, serviceName, host, port); } + public void setId(String id) { + this.id = id; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public void setHost(String host) { + this.host = host; + } + @Override public String getId() { return id; diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java index dc20a0ffa39..3ba497011f9 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java @@ -218,8 +218,8 @@ public String toString() { } @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { - serviceDiscovery.addServiceInstancesChangedListener(serviceName, listener); + public void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { + serviceDiscovery.addServiceInstancesChangedListener(listener); } @Override 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 index e49d392436b..3d70039d23b 100644 --- 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 @@ -17,16 +17,35 @@ 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.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.event.EventListener; import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; -import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; +import com.alibaba.fastjson.JSON; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import static com.alibaba.fastjson.JSON.toJSONString; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; +import static java.lang.String.format; +import static java.nio.channels.FileChannel.open; +import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME; +import static org.apache.dubbo.config.DubboShutdownHook.getDubboShutdownHook; /** * File System {@link ServiceDiscovery} implementation @@ -36,6 +55,10 @@ */ public class FileSystemServiceDiscovery implements ServiceDiscovery, EventListener { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final Map fileLocksCache = new ConcurrentHashMap<>(); + private FileSystemDynamicConfiguration dynamicConfiguration; @Override @@ -46,27 +69,96 @@ public void onEvent(ServiceInstancesChangedEvent event) { @Override public void initialize(URL registryURL) throws Exception { dynamicConfiguration = createDynamicConfiguration(registryURL); + registerDubboShutdownHook(); + registerListener(); + } + + private void registerDubboShutdownHook() { + getDubboShutdownHook().addCallback(this::destroy); + getDubboShutdownHook().register(); + } + + private void registerListener() { + getServices().forEach(serviceName -> { + dynamicConfiguration.getConfigKeys(serviceName).forEach(serviceInstanceId -> { + dynamicConfiguration.addListener(serviceInstanceId, serviceName, this::onConfigChanged); + }); + }); + } + + public void onConfigChanged(ConfigChangedEvent event) { + } @Override public void destroy() throws Exception { dynamicConfiguration.close(); + releaseAndRemoveRegistrationFiles(); + } + + private void releaseAndRemoveRegistrationFiles() { + fileLocksCache.keySet().forEach(file -> { + releaseFileLock(file); + removeFile(file); + }); } - private String getConfigKey(ServiceInstance serviceInstance) { - return serviceInstance.getId(); + private void removeFile(File file) { + FileUtils.deleteQuietly(file); } - private String getConfigGroup(ServiceInstance serviceInstance) { + private String getServiceInstanceId(ServiceInstance serviceInstance) { + String id = serviceInstance.getId(); + if (StringUtils.isBlank(id)) { + return serviceInstance.getHost() + "." + serviceInstance.getPort(); + } + return id; + } + + private String getServiceName(ServiceInstance serviceInstance) { return serviceInstance.getServiceName(); } + @Override + public List getInstances(String serviceName) { + return dynamicConfiguration.getConfigKeys(serviceName) + .stream() + .map(serviceInstanceId -> dynamicConfiguration.getConfig(serviceInstanceId, serviceName)) + .map(content -> JSON.parseObject(content, DefaultServiceInstance.class)) + .collect(Collectors.toList()); + } + @Override public void register(ServiceInstance serviceInstance) throws RuntimeException { - String key = getConfigKey(serviceInstance); - String group = getConfigGroup(serviceInstance); + String serviceInstanceId = getServiceInstanceId(serviceInstance); + String serviceName = getServiceName(serviceInstance); String content = toJSONString(serviceInstance); - dynamicConfiguration.publishConfig(key, group, content); + if (dynamicConfiguration.publishConfig(serviceInstanceId, serviceName, content)) { + lockFile(serviceInstanceId, serviceName); + } + } + + private void lockFile(String serviceInstanceId, String serviceName) { + File serviceInstanceFile = serviceInstanceFile(serviceInstanceId, serviceName); + Path serviceInstanceFilePath = serviceInstanceFile.toPath(); + + fileLocksCache.computeIfAbsent(serviceInstanceFile, file -> { + FileLock fileLock = null; + try { + FileChannel fileChannel = open(serviceInstanceFilePath, StandardOpenOption.READ, StandardOpenOption.WRITE, LinkOption.NOFOLLOW_LINKS); + fileLock = fileChannel.tryLock(); + } catch (IOException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } + if (fileLock != null) { + if (logger.isInfoEnabled()) { + logger.info(format("%s has been locked", serviceInstanceFilePath.toAbsolutePath())); + } + } + return fileLock; + }); } @Override @@ -76,25 +168,48 @@ public void update(ServiceInstance serviceInstance) throws RuntimeException { @Override public void unregister(ServiceInstance serviceInstance) throws RuntimeException { - String key = getConfigKey(serviceInstance); - String group = getConfigGroup(serviceInstance); + String key = getServiceInstanceId(serviceInstance); + String group = getServiceName(serviceInstance); + releaseFileLock(key, group); dynamicConfiguration.removeConfig(key, group); } - @Override - public Set getServices() { - return null; + private void releaseFileLock(String serviceInstanceId, String serviceName) { + File serviceInstanceFile = serviceInstanceFile(serviceInstanceId, serviceName); + releaseFileLock(serviceInstanceFile); } - @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws - NullPointerException, IllegalArgumentException { + private void releaseFileLock(File serviceInstanceFile) { + fileLocksCache.computeIfPresent(serviceInstanceFile, (f, fileLock) -> { + releaseFileLock(fileLock); + if (logger.isInfoEnabled()) { + logger.info(format("The file[%s] has been released", serviceInstanceFile.getAbsolutePath())); + } + return null; + }); + } + + private void releaseFileLock(FileLock fileLock) { + try (FileChannel fileChannel = fileLock.channel()) { + fileLock.release(); + } catch (IOException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } + } + private File serviceInstanceFile(String serviceInstanceId, String serviceName) { + return dynamicConfiguration.configFile(serviceInstanceId, serviceName); + } + + @Override + public Set getServices() { + return dynamicConfiguration.getConfigGroups(); } private static FileSystemDynamicConfiguration createDynamicConfiguration(URL connectionURL) { - String protocol = connectionURL.getProtocol(); - DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getExtension(protocol); - return (FileSystemDynamicConfiguration) factory.getDynamicConfiguration(connectionURL); + String path = System.getProperty("user.home") + File.separator + ".dubbo" + File.separator + "registry"; + return new FileSystemDynamicConfiguration(connectionURL.addParameter(CONFIG_CENTER_DIR_PARAM_NAME, path)); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java index 3381d5a562a..bf33cba2613 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java @@ -20,6 +20,8 @@ import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.common.lang.Prioritized; 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.event.listener.ServiceInstancesChangedListener; import java.util.LinkedHashMap; @@ -30,6 +32,7 @@ import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableMap; +import static org.apache.dubbo.event.EventDispatcher.getDefaultExtension; /** * The common operations of Service Discovery @@ -190,14 +193,18 @@ default Map> getInstances(Iterable service /** * Add an instance of {@link ServiceInstancesChangedListener} for specified service + *

    + * Default, the ServiceInstancesChangedListener will be {@link EventDispatcher#addEventListener(EventListener) added} + * into {@link EventDispatcher} * - * @param serviceName the service name - * @param listener an instance of {@link ServiceInstancesChangedListener} + * @param listener an instance of {@link ServiceInstancesChangedListener} * @throws NullPointerException * @throws IllegalArgumentException */ - void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) - throws NullPointerException, IllegalArgumentException; + default void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) + throws NullPointerException, IllegalArgumentException { + getDefaultExtension().addEventListener(listener); + } // ==================================================================================== // diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index fd86ab62375..0a39fb13496 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -27,6 +27,8 @@ import org.apache.dubbo.metadata.store.RemoteWritableMetadataService; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; import org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory; import org.apache.dubbo.registry.client.selector.ServiceInstanceSelector; import org.apache.dubbo.registry.support.FailbackRegistry; @@ -275,8 +277,12 @@ protected void subscribeURLs(URL url, NotifyListener listener, String serviceNam subscribeURLs(url, listener, serviceName, serviceInstances); // Add Listener - serviceDiscovery.addServiceInstancesChangedListener(serviceName, event -> { - subscribeURLs(url, listener, event.getServiceName(), new ArrayList<>(event.getServiceInstances())); + serviceDiscovery.addServiceInstancesChangedListener(new ServiceInstancesChangedListener(serviceName) { + + @Override + public void onEvent(ServiceInstancesChangedEvent event) { + subscribeURLs(url, listener, event.getServiceName(), new ArrayList<>(event.getServiceInstances())); + } }); } 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 251372d033e..a5edd08f7ac 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,6 +16,7 @@ */ package org.apache.dubbo.registry.client; +import java.io.Serializable; import java.util.Map; /** @@ -24,7 +25,7 @@ * * @since 2.7.4 */ -public interface ServiceInstance { +public interface ServiceInstance extends Serializable { /** * The id of the registered service instance. diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java index 4db3688aec0..008c3f7cf1e 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java @@ -16,21 +16,47 @@ */ package org.apache.dubbo.registry.client.event.listener; +import org.apache.dubbo.event.ConditionalEventListener; import org.apache.dubbo.event.EventListener; import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; +import java.util.Objects; + /** * The Service Discovery Changed {@link EventListener Event Listener} * * @see ServiceInstancesChangedEvent * @since 2.7.4 */ -public interface ServiceInstancesChangedListener extends EventListener { +public abstract class ServiceInstancesChangedListener implements ConditionalEventListener { + + private final String serviceName; + + protected ServiceInstancesChangedListener(String serviceName) { + this.serviceName = serviceName; + } /** * On {@link ServiceInstancesChangedEvent the service instances change event} * * @param event {@link ServiceInstancesChangedEvent} */ - void onEvent(ServiceInstancesChangedEvent event); + public abstract void onEvent(ServiceInstancesChangedEvent event); + + /** + * Get the correlative service name + * + * @return the correlative service name + */ + public final String getServiceName() { + return serviceName; + } + + /** + * @param event {@link ServiceInstancesChangedEvent event} + * @return If service name matches, return true, or false + */ + public final boolean accept(ServiceInstancesChangedEvent event) { + return Objects.equals(getServiceName(), event.getServiceName()); + } } 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 c48bfa97584..93b0be84b86 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 @@ -19,6 +19,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static java.lang.String.valueOf; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -33,7 +34,7 @@ public class DefaultServiceInstanceTest { public DefaultServiceInstance instance; public static DefaultServiceInstance createInstance() { - DefaultServiceInstance instance = new DefaultServiceInstance("A", "127.0.0.1", 8080); + DefaultServiceInstance instance = new DefaultServiceInstance(valueOf(System.nanoTime()), "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; diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/FileSystemServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/FileSystemServiceDiscoveryTest.java new file mode 100644 index 00000000000..2cb4c226e53 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/FileSystemServiceDiscoveryTest.java @@ -0,0 +1,60 @@ +/* + * 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.URLBuilder; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.apache.dubbo.registry.client.DefaultServiceInstanceTest.createInstance; + +/** + * {@link FileSystemServiceDiscovery} Test + * + * @since 2.7.4 + */ +public class FileSystemServiceDiscoveryTest { + + private FileSystemServiceDiscovery serviceDiscovery; + + private ServiceInstance serviceInstance; + + @BeforeEach + public void init() throws Exception { + serviceDiscovery = new FileSystemServiceDiscovery(); + serviceDiscovery.initialize(new URLBuilder().build()); + serviceInstance = createInstance(); + } + + @AfterEach + public void destroy() throws Exception { + serviceDiscovery.destroy(); + serviceInstance = null; + } + + @Test + public void testRegisterAndUnregister() { + + serviceDiscovery.register(serviceInstance); + + serviceDiscovery.unregister(serviceInstance); + + serviceDiscovery.register(serviceInstance); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java index 6f7c3ea4330..83ca8e6c188 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java @@ -20,7 +20,6 @@ import org.apache.dubbo.common.utils.DefaultPage; import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.event.EventDispatcher; -import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; import java.util.ArrayList; import java.util.HashMap; @@ -103,9 +102,4 @@ public void initialize(URL registryURL) throws Exception { @Override public void destroy() { } - - @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { - dispatcher.addEventListener(listener); - } } 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 index 898e7324057..c4eedf1868d 100644 --- 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 @@ -44,7 +44,12 @@ public void testOnEvent() { AtomicReference eventRef = new AtomicReference<>(); - eventDispatcher.addEventListener((ServiceInstancesChangedListener) eventRef::set); + eventDispatcher.addEventListener(new ServiceInstancesChangedListener("test") { + @Override + public void onEvent(ServiceInstancesChangedEvent event) { + eventRef.set(event); + } + }); // Dispatch a ServiceInstancesChangedEvent eventDispatcher.dispatch(event); diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/fastjson/DefaultServiceInstanceDeserializerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/fastjson/DefaultServiceInstanceDeserializerTest.java new file mode 100644 index 00000000000..291c792954c --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/fastjson/DefaultServiceInstanceDeserializerTest.java @@ -0,0 +1,58 @@ +///* +// * 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.fastjson; +// +//import org.apache.dubbo.registry.client.DefaultServiceInstance; +// +//import com.alibaba.fastjson.JSON; +//import com.alibaba.fastjson.parser.ParserConfig; +//import org.junit.jupiter.api.BeforeAll; +//import org.junit.jupiter.api.Test; +// +///** +// * {@link DefaultServiceInstanceDeserializer} Test +// * +// * @since 2.7.4 +// */ +//public class DefaultServiceInstanceDeserializerTest { +// +// private static final String JSON_CONTENT = "{\n" + +// " \"enabled\": true,\n" + +// " \"healthy\": true,\n" + +// " \"host\": \"fe80:0:0:0:1c49:6eff:fe54:2495%7\",\n" + +// " \"metadata\": {\n" + +// " \"dubbo.metadata-service.url-params\": \"{\\\"dubbo\\\":{\\\"application\\\":\\\"dubbo-provider-demo\\\",\\\"deprecated\\\":\\\"false\\\",\\\"group\\\":\\\"dubbo-provider-demo\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"timestamp\\\":\\\"1566132738256\\\",\\\"dubbo\\\":\\\"2.0.2\\\",\\\"provider.host\\\":\\\"fe80:0:0:0:1c49:6eff:fe54:2495%7\\\",\\\"provider.port\\\":\\\"20880\\\"}}\",\n" + +// " \"dubbo.subscribed-services.revision\": \"1\",\n" + +// " \"dubbo.metadata.storage-type\": \"default\",\n" + +// " \"dubbo.exported-services.revision\": \"640372560\"\n" + +// " },\n" + +// " \"port\": 20880,\n" + +// " \"serviceName\": \"dubbo-provider-demo\"\n" + +// "}"; +// +// @BeforeAll +// public static void init() { +// ParserConfig.getGlobalInstance().putDeserializer(DefaultServiceInstance.class, new DefaultServiceInstanceDeserializer()); +// } +// +// @Test +// public void testDeserialze() { +// +// DefaultServiceInstance serviceInstance = JSON.parseObject(JSON_CONTENT, DefaultServiceInstance.class); +// +// } +//} diff --git a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java index 22e44a149c8..830c23ba7cc 100644 --- a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java @@ -25,7 +25,6 @@ import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; -import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils; import com.ecwid.consul.v1.ConsulClient; @@ -117,11 +116,6 @@ public Set getServices() { return null; } - @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { - - } - @Override public List getInstances(String serviceName) throws NullPointerException { Response> response = getHealthServices(serviceName, -1, buildWatchTimeout()); diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java index 45da96e8415..a5cff2b46ec 100644 --- a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java @@ -49,8 +49,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; - /** * 2019-07-08 */ @@ -161,8 +159,8 @@ public Set getServices() { } @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { - registerServiceWatcher(serviceName); + public void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { + registerServiceWatcher(listener.getServiceName()); dispatcher.addEventListener(listener); } diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java index 8863e8915c4..beb3cd19c85 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java @@ -107,10 +107,10 @@ public List getInstances(String serviceName) throws NullPointer } @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) + public void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { execute(namingService, service -> { - service.subscribe(serviceName, e -> { // Register Nacos EventListener + service.subscribe(listener.getServiceName(), e -> { // Register Nacos EventListener if (e instanceof NamingEvent) { NamingEvent event = (NamingEvent) e; handleEvent(event, listener); 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 feac09358f1..772d5c9c37a 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 @@ -145,9 +145,9 @@ public Page getInstances(String serviceName, int offset, int pa } @Override - public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) + public void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException { - registerServiceWatcher(serviceName); + registerServiceWatcher(listener.getServiceName()); dispatcher.addEventListener(listener); } 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 12c1a1981c7..5dd975dbdfe 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 @@ -21,6 +21,8 @@ import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceInstance; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; import org.apache.curator.test.TestingServer; import org.junit.jupiter.api.AfterEach; @@ -124,9 +126,12 @@ public void testGetInstances() throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); // Add Listener - discovery.addServiceInstancesChangedListener(SERVICE_NAME, event -> { - serviceInstances.addAll(event.getServiceInstances()); - latch.countDown(); + discovery.addServiceInstancesChangedListener(new ServiceInstancesChangedListener(SERVICE_NAME) { + @Override + public void onEvent(ServiceInstancesChangedEvent event) { + serviceInstances.addAll(event.getServiceInstances()); + latch.countDown(); + } }); discovery.register(createServiceInstance(SERVICE_NAME, LOCALHOST, 8082));