diff --git a/NOTICE b/NOTICE index e414ebfbe51..9e952c6dffd 100644 --- a/NOTICE +++ b/NOTICE @@ -12,11 +12,3 @@ Please visit the Netty web site for more information: * http://netty.io/ Copyright 2014 The Netty Project - -The product contains code form the Google Protocol Buffers project: - -Please visit the following site for more information: -https://developers.google.com/protocol-buffers/ - -Copyright 2008 Google Inc. All rights reserved. - diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml index 9c9a8ea6302..774117b228f 100644 --- a/dubbo-all/pom.xml +++ b/dubbo-all/pom.xml @@ -122,6 +122,13 @@ compile true + + org.apache.dubbo + dubbo-remoting-redis + ${project.version} + compile + true + org.apache.dubbo dubbo-remoting-http @@ -129,6 +136,13 @@ compile true + + org.apache.dubbo + dubbo-remoting-zookeeper + ${project.version} + compile + true + org.apache.dubbo dubbo-rpc-api @@ -328,6 +342,13 @@ compile true + + org.apache.dubbo + dubbo-container-api + ${project.version} + compile + true + org.apache.dubbo dubbo-container-spring @@ -638,6 +659,7 @@ org.apache.dubbo:dubbo-remoting-mina org.apache.dubbo:dubbo-remoting-grizzly org.apache.dubbo:dubbo-remoting-p2p + org.apache.dubbo:dubbo-remoting-redis org.apache.dubbo:dubbo-remoting-http org.apache.dubbo:dubbo-remoting-zookeeper org.apache.dubbo:dubbo-rpc-api @@ -686,8 +708,6 @@ org.apache.dubbo:dubbo-serialization-gson org.apache.dubbo:dubbo-serialization-msgpack org.apache.dubbo:dubbo-serialization-protobuf - org.apache.dubbo:dubbo-configcenter-api - org.apache.dubbo:dubbo-configcenter-definition org.apache.dubbo:dubbo-configcenter-apollo org.apache.dubbo:dubbo-configcenter-zookeeper org.apache.dubbo:dubbo-configcenter-consul diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml index a41b215ed2a..235108f1d26 100644 --- a/dubbo-bom/pom.xml +++ b/dubbo-bom/pom.xml @@ -163,6 +163,16 @@ dubbo-remoting-etcd3 ${project.version} + + org.apache.dubbo + dubbo-remoting-redis + ${project.version} + + + org.apache.dubbo + dubbo-remoting-zookeeper + ${project.version} + org.apache.dubbo dubbo-rpc-api @@ -268,6 +278,11 @@ dubbo-registry-etcd3 ${project.version} + + org.apache.dubbo + dubbo-registry-eureka + ${project.version} + org.apache.dubbo dubbo-registry-consul @@ -293,6 +308,11 @@ dubbo-monitor-default ${project.version} + + org.apache.dubbo + dubbo-container-api + ${project.version} + org.apache.dubbo dubbo-container-spring @@ -308,11 +328,19 @@ dubbo-container-logback ${project.version} + + org.apache.dubbo dubbo-qos ${project.version} + + org.apache.dubbo + dubbo-auth + ${project.version} + + org.apache.dubbo dubbo-serialization-api @@ -368,6 +396,11 @@ dubbo-serialization-protobuf ${project.version} + + org.apache.dubbo + dubbo-serialization-msgpack + ${project.version} + org.apache.dubbo dubbo-compatible diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java index f7cf9514193..21ed1e821fd 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java @@ -103,4 +103,9 @@ public interface Constants { * prefix of arguments router key */ String ARGUMENTS = "arguments"; + + /** + * Url merge processor key + */ + String URL_MERGE_PROCESSOR_KEY = "urlmergeprocessor"; } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ProviderURLMergeProcessor.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/UrlMergeProcessor.java similarity index 72% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ProviderURLMergeProcessor.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/UrlMergeProcessor.java index 9c91f384fba..ba7f4486149 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ProviderURLMergeProcessor.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/UrlMergeProcessor.java @@ -14,16 +14,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.rpc.cluster.support; +package org.apache.dubbo.rpc.cluster; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.SPI; import java.util.Map; -@SPI -public interface ProviderURLMergeProcessor { - URL mergeProviderUrl(URL providerUrl, Map localParametersMap); +@SPI("default") +public interface UrlMergeProcessor { + + /** + * Merging the URL parameters of provider and consumer + * @param remoteUrl providerUrl + * @param localParametersMap consumer url parameters + * @return + */ + URL mergeUrl(URL remoteUrl, Map localParametersMap); - boolean accept(URL providerUrl, Map localParametersMap); } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java index 108810d770f..266b08d5029 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java @@ -126,7 +126,26 @@ private URL configureIfMatch(String host, URL url) { String currentApplication = url.getParameter(APPLICATION_KEY, url.getUsername()); if (configApplication == null || ANY_VALUE.equals(configApplication) || configApplication.equals(currentApplication)) { - Set conditionKeys = new HashSet(); + + Set tildeKeys = new HashSet<>(); + for (Map.Entry entry : configuratorUrl.getParameters().entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + String tildeKey = StringUtils.isNotEmpty(key) && key.startsWith(TILDE) ? key : null; + + if (tildeKey != null || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) { + if (value != null && !ANY_VALUE.equals(value) + && !value.equals(url.getParameter(tildeKey != null ? key.substring(1) : key))) { + return url; + } + } + + if (tildeKey != null) { + tildeKeys.add(tildeKey); + } + } + + Set conditionKeys = new HashSet<>(); conditionKeys.add(CATEGORY_KEY); conditionKeys.add(Constants.CHECK_KEY); conditionKeys.add(DYNAMIC_KEY); @@ -138,20 +157,8 @@ private URL configureIfMatch(String host, URL url) { conditionKeys.add(CONFIG_VERSION_KEY); conditionKeys.add(COMPATIBLE_CONFIG_KEY); conditionKeys.add(INTERFACES); - for (Map.Entry entry : configuratorUrl.getParameters().entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - boolean startWithTilde = startWithTilde(key); - if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) { - if (startWithTilde) { - conditionKeys.add(key); - } - if (value != null && !ANY_VALUE.equals(value) - && !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) { - return url; - } - } - } + conditionKeys.addAll(tildeKeys); + return doConfigure(url, configuratorUrl.removeParameters(conditionKeys)); } } @@ -159,13 +166,6 @@ private URL configureIfMatch(String host, URL url) { return url; } - private boolean startWithTilde(String key) { - if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) { - return true; - } - return false; - } - protected abstract URL doConfigure(URL currentUrl, URL configUrl); } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java index f097f9201eb..299292c6830 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java @@ -18,31 +18,12 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.cluster.UrlMergeProcessor; -import java.util.HashMap; -import java.util.List; import java.util.Map; -import static org.apache.dubbo.common.constants.CommonConstants.ALIVE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REFERENCE_FILTER_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.URL_MERGE_PROCESSOR_KEY; /** * ClusterUtils @@ -53,93 +34,17 @@ private ClusterUtils() { } public static URL mergeUrl(URL remoteUrl, Map localMap) { - Map map = new HashMap(); - Map remoteMap = remoteUrl.getParameters(); - if (remoteMap != null && remoteMap.size() > 0) { - map.putAll(remoteMap); + String ump = localMap.get(URL_MERGE_PROCESSOR_KEY); + UrlMergeProcessor urlMergeProcessor; - // Remove configurations from provider, some items should be affected by provider. - map.remove(THREAD_NAME_KEY); - map.remove(DEFAULT_KEY_PREFIX + THREAD_NAME_KEY); - - map.remove(THREADPOOL_KEY); - map.remove(DEFAULT_KEY_PREFIX + THREADPOOL_KEY); - - map.remove(CORE_THREADS_KEY); - map.remove(DEFAULT_KEY_PREFIX + CORE_THREADS_KEY); - - map.remove(THREADS_KEY); - map.remove(DEFAULT_KEY_PREFIX + THREADS_KEY); - - map.remove(QUEUES_KEY); - map.remove(DEFAULT_KEY_PREFIX + QUEUES_KEY); - - map.remove(ALIVE_KEY); - map.remove(DEFAULT_KEY_PREFIX + ALIVE_KEY); - - map.remove(Constants.TRANSPORTER_KEY); - map.remove(DEFAULT_KEY_PREFIX + Constants.TRANSPORTER_KEY); - } - - if (localMap != null && localMap.size() > 0) { - Map copyOfLocalMap = new HashMap<>(localMap); - - if(map.containsKey(GROUP_KEY)){ - copyOfLocalMap.remove(GROUP_KEY); - } - if(map.containsKey(VERSION_KEY)){ - copyOfLocalMap.remove(VERSION_KEY); - } - if (map.containsKey(GENERIC_KEY)) { - copyOfLocalMap.remove(GENERIC_KEY); - } - - copyOfLocalMap.remove(RELEASE_KEY); - copyOfLocalMap.remove(DUBBO_VERSION_KEY); - copyOfLocalMap.remove(METHODS_KEY); - copyOfLocalMap.remove(TIMESTAMP_KEY); - copyOfLocalMap.remove(TAG_KEY); - - map.putAll(copyOfLocalMap); - - if (remoteMap != null) { - map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY)); - - // Combine filters and listeners on Provider and Consumer - String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY); - String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY); - if (remoteFilter != null && remoteFilter.length() > 0 - && localFilter != null && localFilter.length() > 0) { - map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter); - } - String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY); - String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY); - if (remoteListener != null && remoteListener.length() > 0 - && localListener != null && localListener.length() > 0) { - map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener); - } - } - } - - return remoteUrl.clearParameters().addParameters(map); - } - - public static URL mergeProviderUrl(URL remoteUrl, Map localMap) { - - //urlprocessor => upc - List providerURLMergeProcessors = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class) - .getActivateExtension(remoteUrl, "upc"); - - if (providerURLMergeProcessors != null && providerURLMergeProcessors.size() > 0) { - for (ProviderURLMergeProcessor providerURLMergeProcessor : providerURLMergeProcessors) { - if (providerURLMergeProcessor.accept(remoteUrl, localMap)) { - return providerURLMergeProcessor.mergeProviderUrl(remoteUrl, localMap); - } - } + if (StringUtils.isNotEmpty(ump)) { + urlMergeProcessor = ExtensionLoader.getExtensionLoader(UrlMergeProcessor.class).getExtension(ump); + } else { + urlMergeProcessor = ExtensionLoader.getExtensionLoader(UrlMergeProcessor.class).getExtension("default"); } - return mergeUrl(remoteUrl, localMap); + return urlMergeProcessor.mergeUrl(remoteUrl, localMap); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/DefaultUrlMergeProcessor.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/DefaultUrlMergeProcessor.java new file mode 100644 index 00000000000..c341e676527 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/DefaultUrlMergeProcessor.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.rpc.cluster.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.rpc.cluster.UrlMergeProcessor; + +import java.util.HashMap; +import java.util.Map; + +import static org.apache.dubbo.common.constants.CommonConstants.ALIVE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REFERENCE_FILTER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_KEY; + + +public class DefaultUrlMergeProcessor implements UrlMergeProcessor { + + @Override + public URL mergeUrl(URL remoteUrl, Map localParametersMap) { + + Map map = new HashMap<>(); + Map remoteMap = remoteUrl.getParameters(); + + if (remoteMap != null && remoteMap.size() > 0) { + map.putAll(remoteMap); + + // Remove configurations from provider, some items should be affected by provider. + map.remove(THREAD_NAME_KEY); + map.remove(DEFAULT_KEY_PREFIX + THREAD_NAME_KEY); + + map.remove(THREADPOOL_KEY); + map.remove(DEFAULT_KEY_PREFIX + THREADPOOL_KEY); + + map.remove(CORE_THREADS_KEY); + map.remove(DEFAULT_KEY_PREFIX + CORE_THREADS_KEY); + + map.remove(THREADS_KEY); + map.remove(DEFAULT_KEY_PREFIX + THREADS_KEY); + + map.remove(QUEUES_KEY); + map.remove(DEFAULT_KEY_PREFIX + QUEUES_KEY); + + map.remove(ALIVE_KEY); + map.remove(DEFAULT_KEY_PREFIX + ALIVE_KEY); + + map.remove(Constants.TRANSPORTER_KEY); + map.remove(DEFAULT_KEY_PREFIX + Constants.TRANSPORTER_KEY); + } + + if (localParametersMap != null && localParametersMap.size() > 0) { + Map copyOfLocalMap = new HashMap<>(localParametersMap); + + if(map.containsKey(GROUP_KEY)){ + copyOfLocalMap.remove(GROUP_KEY); + } + if(map.containsKey(VERSION_KEY)){ + copyOfLocalMap.remove(VERSION_KEY); + } + if (map.containsKey(GENERIC_KEY)) { + copyOfLocalMap.remove(GENERIC_KEY); + } + + copyOfLocalMap.remove(RELEASE_KEY); + copyOfLocalMap.remove(DUBBO_VERSION_KEY); + copyOfLocalMap.remove(METHODS_KEY); + copyOfLocalMap.remove(TIMESTAMP_KEY); + copyOfLocalMap.remove(TAG_KEY); + + map.putAll(copyOfLocalMap); + + if (remoteMap != null) { + map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY)); + + // Combine filters and listeners on Provider and Consumer + String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY); + String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY); + if (remoteFilter != null && remoteFilter.length() > 0 + && localFilter != null && localFilter.length() > 0) { + map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter); + } + + String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY); + String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY); + if (remoteListener != null && remoteListener.length() > 0 + && localListener != null && localListener.length() > 0) { + map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener); + } + } + } + + return remoteUrl.clearParameters().addParameters(map); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java index 4f4400b3f33..9fc0993e033 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java @@ -26,7 +26,7 @@ */ public class FailbackCluster extends AbstractCluster { - public final static String NAME = "failback"; + public static final String NAME = "failback"; @Override public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java index 14a8565d20b..1d6e8de3c8c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java @@ -26,7 +26,7 @@ */ public class FailfastCluster extends AbstractCluster { - public final static String NAME = "failfast"; + public static final String NAME = "failfast"; @Override public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java index 7f1bc54666f..2865eb06b98 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java @@ -26,7 +26,7 @@ */ public class FailoverCluster extends AbstractCluster { - public final static String NAME = "failover"; + public static final String NAME = "failover"; @Override public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java index 767ab316b87..280528e2cbc 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java @@ -26,7 +26,7 @@ */ public class FailsafeCluster extends AbstractCluster { - public final static String NAME = "failsafe"; + public static final String NAME = "failsafe"; @Override public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java index b28cffdd243..8c380c1623b 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java @@ -26,7 +26,7 @@ */ public class ForkingCluster extends AbstractCluster { - public final static String NAME = "forking"; + public static final String NAME = "forking"; @Override public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java index c11781e2f49..5c9bf0c112d 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java @@ -26,7 +26,7 @@ */ public class ZoneAwareCluster extends AbstractCluster { - public final static String NAME = "zone-aware"; + public static final String NAME = "zone-aware"; @Override protected AbstractClusterInvoker doJoin(Directory directory) throws RpcException { diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.UrlMergeProcessor b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.UrlMergeProcessor new file mode 100644 index 00000000000..26b23fa1dbf --- /dev/null +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.UrlMergeProcessor @@ -0,0 +1 @@ +default=org.apache.dubbo.rpc.cluster.support.DefaultUrlMergeProcessor diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java index 01cb5301c74..e3e799ebf62 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java @@ -72,6 +72,7 @@ public void testMergeUrl() throws Exception { .addParameter(DEFAULT_KEY_PREFIX + THREAD_NAME_KEY, "test") .addParameter(APPLICATION_KEY, "provider") .addParameter(REFERENCE_FILTER_KEY, "filter1,filter2") + .addParameter(TAG_KEY,"TTT") .build(); URL consumerURL = new URLBuilder(DUBBO_PROTOCOL, "localhost", 55555) @@ -79,6 +80,7 @@ public void testMergeUrl() throws Exception { .addParameter(THREADPOOL_KEY, "foo") .addParameter(APPLICATION_KEY, "consumer") .addParameter(REFERENCE_FILTER_KEY, "filter3") + .addParameter(TAG_KEY,"UUU") .build(); URL url = ClusterUtils.mergeUrl(providerURL, consumerURL.getParameters()); @@ -108,6 +110,8 @@ public void testMergeUrl() throws Exception { Assertions.assertEquals(url.getParameter(APPLICATION_KEY), "consumer"); Assertions.assertEquals(url.getParameter(REMOTE_APPLICATION_KEY), "provider"); Assertions.assertEquals(url.getParameter(REFERENCE_FILTER_KEY), "filter1,filter2,filter3"); + + Assertions.assertEquals(url.getParameter(TAG_KEY), "TTT"); } @Test diff --git a/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/availablerule.javascript b/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/availablerule.javascript index c76de32ee40..40b72b46fcb 100644 --- a/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/availablerule.javascript +++ b/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/availablerule.javascript @@ -1,4 +1,19 @@ -function route(invokers,invocation,context){ +// 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. + +function route(invokers,invocation,context){ var result = new java.util.ArrayList(invokers.size()); for (i=0;i1 && invocation.getMethodName() .equals("method1")) { result.add(invokers.get(0)) ; diff --git a/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/notAvailablerule.javascript b/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/notAvailablerule.javascript index 1fcdcaeb0d6..e323d541306 100644 --- a/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/notAvailablerule.javascript +++ b/dubbo-cluster/src/test/resources/org/apache/dubbo/rpc/cluster/router/file/notAvailablerule.javascript @@ -1,4 +1,19 @@ -function route(invokers,invocation,context){ +// 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. + +function route(invokers,invocation,context){ var result = new java.util.ArrayList(invokers.size()); for (i=0;i 0) { + if (StringUtils.isNotEmpty(group)) { buf.append(group).append("/"); } buf.append(path); - if (version != null && version.length() > 0) { + if (StringUtils.isNotEmpty(version)) { buf.append(":").append(version); } return buf.toString(); @@ -74,8 +74,13 @@ public static String interfaceFromServiceKey(String serviceKey) { */ public String getDisplayServiceKey() { StringBuilder serviceNameBuilder = new StringBuilder(); - serviceNameBuilder.append(serviceInterfaceName); - serviceNameBuilder.append(COLON_SEPARATOR).append(version); + if(StringUtils.isNotEmpty(serviceInterfaceName)){ + serviceNameBuilder.append(serviceInterfaceName); + } + + if(StringUtils.isNotEmpty(version)){ + serviceNameBuilder.append(COLON_SEPARATOR).append(version); + } return serviceNameBuilder.toString(); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java index 252c3aa719f..3267c673569 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java @@ -382,7 +382,7 @@ private CtConstructor getCtConstructor(Constructor c) throws NotFoundExceptio return getCtClass(c.getDeclaringClass()).getConstructor(ReflectUtils.getDesc(c)); } - public static interface DC { + public interface DC { } // dynamic class tag interface. } \ No newline at end of file diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java index 918f2b1639b..8525d985c1d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java @@ -38,17 +38,17 @@ * @author Shigeru Chiba */ public class CustomizedLoaderClassPath implements ClassPath { - private WeakReference clref; + private WeakReference clref; /** * Creates a search path representing a class loader. */ public CustomizedLoaderClassPath(ClassLoader cl) { - clref = new WeakReference(cl); + clref = new WeakReference<>(cl); } public String toString() { - Object cl = null; + ClassLoader cl = null; if (clref != null) { cl = clref.get(); } @@ -63,7 +63,7 @@ public String toString() { */ public InputStream openClassfile(String classname) { String cname = classname.replace('.', '/') + ".class"; - ClassLoader cl = (ClassLoader) clref.get(); + ClassLoader cl = clref.get(); if (cl == null) { return null; // not found } else { @@ -84,7 +84,7 @@ public InputStream openClassfile(String classname) { */ public URL find(String classname) { String cname = classname.replace('.', '/') + ".class"; - ClassLoader cl = (ClassLoader) clref.get(); + ClassLoader cl = clref.get(); if (cl == null) { return null; // not found } else { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java index 3b8961d83f2..1107abbd862 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java @@ -16,12 +16,13 @@ */ package org.apache.dubbo.common.compiler; +import org.apache.dubbo.common.compiler.support.JavassistCompiler; import org.apache.dubbo.common.extension.SPI; /** * Compiler. (SPI, Singleton, ThreadSafe) */ -@SPI("javassist") +@SPI(JavassistCompiler.NAME) public interface Compiler { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java index 3a058849d8f..0a77d5c20b4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java @@ -28,6 +28,8 @@ */ public class JavassistCompiler extends AbstractCompiler { + public static final String NAME = "javassist"; + private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+([\\w\\.\\*]+);\n"); private static final Pattern EXTENDS_PATTERN = Pattern.compile("\\s+extends\\s+([\\w\\.]+)[^\\{]*\\{\n"); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java index c82e48dd4c0..e5d5b22401d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java @@ -53,6 +53,8 @@ */ public class JdkCompiler extends AbstractCompiler { + public static final String NAME = "jdk"; + private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); private final DiagnosticCollector diagnosticCollector = new DiagnosticCollector(); 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 936a59c6045..95787bedd48 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 @@ -253,6 +253,14 @@ public interface CommonConstants { */ String DUBBO_PREFERRED_NETWORK_INTERFACE = "dubbo.network.interface.preferred"; + /** + * The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that + * the Dubbo application will be ignored + * + * @since 2.7.6 + */ + String DUBBO_NETWORK_IGNORED_INTERFACE = "dubbo.network.interface.ignored"; + @Deprecated String SHUTDOWN_WAIT_SECONDS_KEY = "dubbo.service.shutdown.wait.seconds"; String SHUTDOWN_WAIT_KEY = "dubbo.service.shutdown.wait"; @@ -401,4 +409,9 @@ public interface CommonConstants { String ON_DISCONNECT_KEY = "ondisconnect"; String TOKEN = "token"; + + String DUBBO_MONITOR_ADDRESS = "dubbo.monitor.address"; + + String DISPATHER = "dispather"; + } 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 c7edc68fb24..820dbd97801 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 @@ -270,7 +270,7 @@ public List getActivateExtension(URL url, String[] values, String group) { List activateExtensions = new ArrayList<>(); // solve the bug of using @SPI's wrapper method to report a null pointer exception. TreeMap activateExtensionsMap = new TreeMap<>(ActivateComparator.COMPARATOR); - List names = values == null ? new ArrayList<>(0) : asList(values); + Set names = CollectionUtils.ofSet(values); if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) { getExtensionClasses(); for (Map.Entry entry : cachedActivates.entrySet()) { @@ -300,8 +300,7 @@ && isActive(activateValue, url)) { } } List loadedExtensions = new ArrayList<>(); - for (int i = 0; i < names.size(); i++) { - String name = names.get(i); + for (String name : names) { if (!name.startsWith(REMOVE_VALUE_PREFIX) && !names.contains(REMOVE_VALUE_PREFIX + name)) { if (DEFAULT_KEY.equals(name)) { @@ -406,17 +405,6 @@ public Object getLoadedAdaptiveExtensionInstances() { return cachedAdaptiveInstance.get(); } -// public T getPrioritizedExtensionInstance() { -// Set supported = getSupportedExtensions(); -// -// Set instances = new HashSet<>(); -// Set prioritized = new HashSet<>(); -// for (String s : supported) { -// -// } -// -// } - /** * Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException} * will be thrown. @@ -447,6 +435,17 @@ public T getExtension(String name, boolean wrap) { return (T) instance; } + /** + * get the original type. + * @param name + * @return + */ + public T getOriginalInstance(String name) { + getExtension(name); + Class clazz = getExtensionClasses().get(name); + return (T) EXTENSION_INSTANCES.get(clazz); + } + /** * Get the extension by specified name if found, or {@link #getDefaultExtension() returns the default one} * diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java index 312cd690fff..adb054b662b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java @@ -19,6 +19,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Adaptive; import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool; import java.util.concurrent.Executor; @@ -27,7 +28,7 @@ /** * ThreadPool */ -@SPI("fixed") +@SPI(FixedThreadPool.NAME) public interface ThreadPool { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java index ebd89449f47..21b22aed5c3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java @@ -51,7 +51,6 @@ public class DefaultExecutorRepository implements ExecutorRepository { private ScheduledExecutorService serviceExporterExecutor; - private ScheduledExecutorService reconnectScheduledExecutor; private ConcurrentMap> data = new ConcurrentHashMap<>(); @@ -60,8 +59,6 @@ public DefaultExecutorRepository() { ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-framework-scheduler")); scheduledExecutors.addItem(scheduler); } -// -// reconnectScheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-reconnect-scheduler")); serviceExporterExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Dubbo-exporter-scheduler")); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java index 6dbbced16ff..97cb5be3179 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java @@ -45,6 +45,8 @@ */ public class CachedThreadPool implements ThreadPool { + public static final String NAME = "cached"; + @Override public Executor getExecutor(URL url) { String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPool.java index 6d126894aa9..05546e77cf6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPool.java @@ -42,6 +42,8 @@ */ public class EagerThreadPool implements ThreadPool { + public static final String NAME = "eager"; + @Override public Executor getExecutor(URL url) { String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java index 606d7e1f913..a08226a0420 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java @@ -41,6 +41,8 @@ */ public class FixedThreadPool implements ThreadPool { + public static final String NAME = "fixed"; + @Override public Executor getExecutor(URL url) { String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/limited/LimitedThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/limited/LimitedThreadPool.java index 87c46d37423..0605c4800c5 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/limited/LimitedThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/limited/LimitedThreadPool.java @@ -43,6 +43,8 @@ */ public class LimitedThreadPool implements ThreadPool { + public static final String NAME = "limited"; + @Override public Executor getExecutor(URL url) { String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java index 055ba48e0a6..bd21c1b651c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java @@ -25,7 +25,7 @@ */ public class CharSequenceComparator implements Comparator { - public final static CharSequenceComparator INSTANCE = new CharSequenceComparator(); + public static final CharSequenceComparator INSTANCE = new CharSequenceComparator(); private CharSequenceComparator() { } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java index 8270c1da675..faf7d18893c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java @@ -32,7 +32,7 @@ */ public class MethodComparator implements Comparator { - public final static MethodComparator INSTANCE = new MethodComparator(); + public static final MethodComparator INSTANCE = new MethodComparator(); private MethodComparator() { } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java index 01855f4b5fb..e99d59e6937 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java @@ -33,6 +33,7 @@ import java.net.ServerSocket; import java.net.SocketException; import java.net.UnknownHostException; +import java.util.BitSet; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; @@ -48,6 +49,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PREFERRED_NETWORK_INTERFACE; import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_KEY; import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_NETWORK_IGNORED_INTERFACE; import static org.apache.dubbo.common.utils.CollectionUtils.first; /** @@ -69,7 +71,7 @@ public class NetUtils { private static final int RND_PORT_RANGE = 10000; // valid port range is (0, 65535] - private static final int MIN_PORT = 0; + private static final int MIN_PORT = 1; private static final int MAX_PORT = 65535; private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); @@ -82,25 +84,31 @@ public class NetUtils { private static final String SPLIT_IPV4_CHARACTER = "\\."; private static final String SPLIT_IPV6_CHARACTER = ":"; + /** + * store the used port. + * the set used only on the synchronized method. + */ + private static BitSet USED_PORT = new BitSet(65536); + public static int getRandomPort() { return RND_PORT_START + ThreadLocalRandom.current().nextInt(RND_PORT_RANGE); } - public static int getAvailablePort() { - try (ServerSocket ss = new ServerSocket()) { - ss.bind(null); - return ss.getLocalPort(); - } catch (IOException e) { - return getRandomPort(); - } + public synchronized static int getAvailablePort() { + int randomPort = getRandomPort(); + return getAvailablePort(randomPort); } - public static int getAvailablePort(int port) { - if (port <= 0) { - return getAvailablePort(); + public synchronized static int getAvailablePort(int port) { + if (port < MIN_PORT) { + port = MIN_PORT; } for (int i = port; i < MAX_PORT; i++) { + if (USED_PORT.get(i)) { + continue; + } try (ServerSocket ignored = new ServerSocket(i)) { + USED_PORT.set(i); return i; } catch (IOException e) { // continue @@ -110,7 +118,7 @@ public static int getAvailablePort(int port) { } public static boolean isInvalidPort(int port) { - return port <= MIN_PORT || port > MAX_PORT; + return port < MIN_PORT || port > MAX_PORT; } public static boolean isValidAddress(String address) { @@ -305,22 +313,35 @@ private static InetAddress getLocalAddress0() { } /** - * @param networkInterface {@link NetworkInterface} - * @return if the specified {@link NetworkInterface} should be ignored, return true + * Returns {@code true} if the specified {@link NetworkInterface} should be ignored with the given conditions. + * @param networkInterface the {@link NetworkInterface} to check + * @return {@code true} if the specified {@link NetworkInterface} should be ignored, otherwise {@code false} * @throws SocketException SocketException if an I/O error occurs. - * @since 2.7.6 */ private static boolean ignoreNetworkInterface(NetworkInterface networkInterface) throws SocketException { - return networkInterface == null + if (networkInterface == null || networkInterface.isLoopback() || networkInterface.isVirtual() - || !networkInterface.isUp(); + || !networkInterface.isUp()){ + return true; + } + String ignoredInterfaces = System.getProperty(DUBBO_NETWORK_IGNORED_INTERFACE); + String networkInterfaceDisplayName; + if(StringUtils.isNotEmpty(ignoredInterfaces) + &&StringUtils.isNotEmpty(networkInterfaceDisplayName=networkInterface.getDisplayName())){ + for(String ignoredInterface: ignoredInterfaces.split(",")){ + if(networkInterfaceDisplayName.matches(ignoredInterface.trim())){ + return true; + } + } + } + return false; } /** * Get the valid {@link NetworkInterface network interfaces} * - * @return non-null + * @return the valid {@link NetworkInterface}s * @throws SocketException SocketException if an I/O error occurs. * @since 2.7.6 */ @@ -558,7 +579,7 @@ public static boolean matchIpRange(String pattern, String host, int port) throws if (!ipPatternContainExpression(pattern)) { InetAddress patternAddress = InetAddress.getByName(pattern); return patternAddress.getHostAddress().equals(host); - } + } String[] ipAddress = host.split(splitCharacter); for (int i = 0; i < mask.length; i++) { @@ -575,7 +596,8 @@ public static boolean matchIpRange(String pattern, String host, int port) throws if (ip < min || ip > max) { return false; } - } else if ("0".equals(ipAddress[i]) && ("0".equals(mask[i]) || "00".equals(mask[i]) || "000".equals(mask[i]) || "0000".equals(mask[i]))) { + } else if ("0".equals(ipAddress[i]) && + ("0".equals(mask[i]) || "00".equals(mask[i]) || "000".equals(mask[i]) || "0000".equals(mask[i]))) { continue; } else if (!mask[i].equals(ipAddress[i])) { return false; @@ -609,7 +631,8 @@ private static boolean ipPatternContainExpression(String pattern) { private static void checkHostPattern(String pattern, String[] mask, boolean isIpv4) { if (!isIpv4) { if (mask.length != 8 && ipPatternContainExpression(pattern)) { - throw new IllegalArgumentException("If you config ip expression that contains '*' or '-', please fill qualified ip pattern like 234e:0:4567:0:0:0:3d:*. "); + throw new IllegalArgumentException( + "If you config ip expression that contains '*' or '-', please fill qualified ip pattern like 234e:0:4567:0:0:0:3d:*. "); } if (mask.length != 8 && !pattern.contains("::")) { throw new IllegalArgumentException("The host is ipv6, but the pattern is not ipv6 pattern : " + pattern); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java index 7b17515199b..fa1d6a8468a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java @@ -62,7 +62,7 @@ public class UrlUtils { /** * in the url string,mark the param begin */ - private final static String URL_PARAM_STARTING_SYMBOL = "?"; + private static final String URL_PARAM_STARTING_SYMBOL = "?"; public static URL parseURL(String address, Map defaults) { if (address == null || address.length() == 0) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java index 0c3b443bb1d..b0d5b5ae6b4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java @@ -91,6 +91,10 @@ public class ConfigCenterConfig extends AbstractConfig { public ConfigCenterConfig() { } + public ConfigCenterConfig(String address) { + setAddress(address); + } + public URL toUrl() { Map map = new HashMap<>(); appendParameters(map, this); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java index 659b7bbf563..d4e90c6c2be 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java @@ -30,6 +30,8 @@ public interface Constants { String LAYER_KEY = "layer"; + String STUB_KEY = "stub"; + /** * General */ @@ -79,6 +81,7 @@ public interface Constants { String MULTICAST = "multicast"; + String MULTIPLE = "multiple"; String DUBBO_IP_TO_REGISTRY = "DUBBO_IP_TO_REGISTRY"; @@ -107,10 +110,10 @@ public interface Constants { String SHUTDOWN_TIMEOUT_KEY = "shutdown.timeout"; - String PROTOCOLS_SUFFIX = "dubbo.protocols."; + String PROTOCOLS_PREFIX = "dubbo.protocols."; - String REGISTRIES_SUFFIX = "dubbo.registries."; + String REGISTRIES_PREFIX = "dubbo.registries."; String ZOOKEEPER_PROTOCOL = "zookeeper"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java index 53e63d29bf1..61c60226e6e 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java @@ -58,6 +58,13 @@ public class ConsumerConfig extends AbstractReferenceConfig { */ private Integer shareconnections; + + /** + * Url Merge Processor + * Used to customize the URL merge of consumer and provider + */ + private String urlmergeprocessor; + @Override public void setTimeout(Integer timeout) { super.setTimeout(timeout); @@ -115,4 +122,12 @@ public Integer getShareconnections() { public void setShareconnections(Integer shareconnections) { this.shareconnections = shareconnections; } + + public String getUrlmergeprocessor() { + return urlmergeprocessor; + } + + public void setUrlmergeprocessor(String urlmergeprocessor) { + this.urlmergeprocessor = urlmergeprocessor; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java index b8af63cab25..daa45b50f71 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java @@ -23,7 +23,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SSL_ENABLED_KEY; -import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX; +import static org.apache.dubbo.config.Constants.PROTOCOLS_PREFIX; /** * ProtocolConfig @@ -530,7 +530,7 @@ public void refresh() { } super.refresh(); if (StringUtils.isNotEmpty(this.getId())) { - this.setPrefix(PROTOCOLS_SUFFIX); + this.setPrefix(PROTOCOLS_PREFIX); super.refresh(); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java index 62eb3770860..d084c292ac2 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java @@ -455,7 +455,7 @@ public String toString() { sb.append(", telnet='").append(telnet).append('\''); sb.append(", prompt='").append(prompt).append('\''); sb.append(", status='").append(status).append('\''); - sb.append(", wait=").append(wait); + sb.append(", wait=").append(wait).append('\''); sb.append(", isDefault=").append(isDefault); sb.append('}'); return sb.toString(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java index d822b057226..3d012408790 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java @@ -29,7 +29,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY; import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY; import static org.apache.dubbo.common.utils.PojoUtils.updatePropertyIfAbsent; -import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX; +import static org.apache.dubbo.config.Constants.REGISTRIES_PREFIX; /** * RegistryConfig @@ -510,7 +510,7 @@ public void setWeight(Integer weight) { public void refresh() { super.refresh(); if (StringUtils.isNotEmpty(this.getId())) { - this.setPrefix(REGISTRIES_SUFFIX); + this.setPrefix(REGISTRIES_PREFIX); super.refresh(); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java index 83f86594c71..b861e5e9691 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; public class SslConfig extends AbstractConfig { @@ -40,6 +41,16 @@ public class SslConfig extends AbstractConfig { private String clientKeyPassword; private String clientTrustCertCollectionPath; + /** + * set support cipher + */ + private List ciphers; + + /** + * set support protocols + */ + private List protocols; + private InputStream serverKeyCertChainPathStream; private InputStream serverPrivateKeyPathStream; private InputStream serverTrustCertCollectionPathStream; @@ -120,6 +131,24 @@ public void setClientTrustCertCollectionPath(String clientTrustCertCollectionPat this.clientTrustCertCollectionPath = clientTrustCertCollectionPath; } + @Parameter(key = "ciphers") + public List getCiphers() { + return ciphers; + } + + public void setCiphers(List ciphers) { + this.ciphers = ciphers; + } + + @Parameter(key = "protocols") + public List getProtocols() { + return protocols; + } + + public void setProtocols(List protocols) { + this.protocols = protocols; + } + public InputStream getServerKeyCertChainPathStream() throws IOException { if (serverKeyCertChainPath != null) { serverKeyCertChainPathStream = IOUtils.getURL(serverKeyCertChainPath).openStream(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java index 65367cae58c..2cbc124dcb8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java @@ -59,8 +59,8 @@ import static org.apache.dubbo.common.utils.ReflectUtils.getProperty; import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty; import static org.apache.dubbo.config.AbstractConfig.getTagName; -import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX; -import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX; +import static org.apache.dubbo.config.Constants.PROTOCOLS_PREFIX; +import static org.apache.dubbo.config.Constants.REGISTRIES_PREFIX; public class ConfigManager extends LifecycleAdapter implements FrameworkExt { @@ -165,6 +165,10 @@ public Collection getMetadataConfigs() { return getConfigs(getTagName(MetadataReportConfig.class)); } + public MetadataReportConfig getMetadataConfig(String id) { + return getConfig(getTagName(MetadataReportConfig.class), id); + } + public Collection getDefaultMetadataConfigs() { Collection defaults = getDefaultConfigs(getConfigsMap(getTagName(MetadataReportConfig.class))); if (CollectionUtils.isEmpty(defaults)) { @@ -258,9 +262,9 @@ public Collection getProtocols() { public Set getProtocolIds() { Set protocolIds = new HashSet<>(); protocolIds.addAll(getSubProperties(ApplicationModel.getEnvironment() - .getExternalConfigurationMap(), PROTOCOLS_SUFFIX)); + .getExternalConfigurationMap(), PROTOCOLS_PREFIX)); protocolIds.addAll(getSubProperties(ApplicationModel.getEnvironment() - .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX)); + .getAppExternalConfigurationMap(), PROTOCOLS_PREFIX)); return unmodifiableSet(protocolIds); } @@ -293,9 +297,9 @@ public Collection getRegistries() { public Set getRegistryIds() { Set registryIds = new HashSet<>(); registryIds.addAll(getSubProperties(ApplicationModel.getEnvironment().getExternalConfigurationMap(), - REGISTRIES_SUFFIX)); + REGISTRIES_PREFIX)); registryIds.addAll(getSubProperties(ApplicationModel.getEnvironment().getAppExternalConfigurationMap(), - REGISTRIES_SUFFIX)); + REGISTRIES_PREFIX)); return unmodifiableSet(registryIds); } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java index 1075aec70d8..937e7bdee6d 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java @@ -59,8 +59,8 @@ public void test() { assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0").getDisplayServiceKey(), "org.apache.dubbo.common.TestInterface:1.0.0"); assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface").getDisplayServiceKey(), - "org.apache.dubbo.common.TestInterface:null"); - assertEquals(BaseServiceMetadata.revertDisplayServiceKey(null).getDisplayServiceKey(),"null:null"); - assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0:1").getDisplayServiceKey(),"null:null"); + "org.apache.dubbo.common.TestInterface"); + assertEquals(BaseServiceMetadata.revertDisplayServiceKey(null).getDisplayServiceKey(),""); + assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0:1").getDisplayServiceKey(),""); } } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JavaCodeTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JavaCodeTest.java index 9d150d352f4..3023044ced6 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JavaCodeTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JavaCodeTest.java @@ -20,7 +20,7 @@ public class JavaCodeTest { - public final static AtomicInteger SUBFIX = new AtomicInteger(8); + public static final AtomicInteger SUBFIX = new AtomicInteger(8); String getSimpleCode() { StringBuilder code = new StringBuilder(); diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java index b6416aa3029..562902de526 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java @@ -24,7 +24,9 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; +import java.net.NetworkInterface; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_NETWORK_IGNORED_INTERFACE; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; @@ -50,7 +52,7 @@ public void testGetRandomPort() throws Exception { @Test public void testGetAvailablePort() throws Exception { - assertThat(NetUtils.getAvailablePort(), greaterThan(0)); + assertThat(NetUtils.getAvailablePort(), greaterThanOrEqualTo(0)); assertThat(NetUtils.getAvailablePort(12345), greaterThanOrEqualTo(12345)); assertThat(NetUtils.getAvailablePort(-1), greaterThanOrEqualTo(0)); } @@ -322,4 +324,78 @@ public void testIsMulticastAddress() { assertTrue(NetUtils.isMulticastAddress("224.0.0.1")); assertFalse(NetUtils.isMulticastAddress("127.0.0.1")); } + + @Test + public void testFindNetworkInterface(){ + assertNotNull(NetUtils.findNetworkInterface()); + } + + @Test + public void testIgnoreAllInterfaces(){ + // store the origin ignored interfaces + String originIgnoredInterfaces = this.getIgnoredInterfaces(); + try{ + // ignore all interfaces + this.setIgnoredInterfaces("*"); + assertNull(NetUtils.findNetworkInterface()); + }finally { + // recover the origin ignored interfaces + this.setIgnoredInterfaces(originIgnoredInterfaces); + } + } + + @Test + public void testIgnoreGivenInterface(){ + // store the origin ignored interfaces + String originIgnoredInterfaces = this.getIgnoredInterfaces(); + try{ + NetworkInterface networkInterface = NetUtils.findNetworkInterface(); + assertNotNull(networkInterface); + // ignore the given network interface's display name + this.setIgnoredInterfaces(networkInterface.getDisplayName()); + NetworkInterface newNetworkInterface = NetUtils.findNetworkInterface(); + if(newNetworkInterface!=null){ + assertTrue(!networkInterface.getDisplayName().equals(newNetworkInterface.getDisplayName())); + } + }finally { + // recover the origin ignored interfaces + this.setIgnoredInterfaces(originIgnoredInterfaces); + } + } + + @Test + public void testIgnoreGivenPrefixInterfaceName(){ + // store the origin ignored interfaces + String originIgnoredInterfaces = this.getIgnoredInterfaces(); + try{ + NetworkInterface networkInterface = NetUtils.findNetworkInterface(); + assertNotNull(networkInterface); + // ignore the given prefix network interface's display name + String displayName = networkInterface.getDisplayName(); + if(StringUtils.isNotEmpty(displayName)&&displayName.length()>2){ + String ignoredInterfaces = displayName.substring(0,1)+".*"; + this.setIgnoredInterfaces(ignoredInterfaces); + NetworkInterface newNetworkInterface = NetUtils.findNetworkInterface(); + if(newNetworkInterface!=null){ + assertTrue(!newNetworkInterface.getDisplayName().startsWith(displayName.substring(0,1))); + } + } + }finally { + // recover the origin ignored interfaces + this.setIgnoredInterfaces(originIgnoredInterfaces); + } + } + + private String getIgnoredInterfaces(){ + return System.getProperty(DUBBO_NETWORK_IGNORED_INTERFACE); + } + + private void setIgnoredInterfaces(String ignoredInterfaces){ + if(ignoredInterfaces!=null){ + System.setProperty(DUBBO_NETWORK_IGNORED_INTERFACE,ignoredInterfaces); + }else{ + System.setProperty(DUBBO_NETWORK_IGNORED_INTERFACE,""); + } + } + } diff --git a/dubbo-compatible/pom.xml b/dubbo-compatible/pom.xml index b96623a137d..abb337e13b5 100644 --- a/dubbo-compatible/pom.xml +++ b/dubbo-compatible/pom.xml @@ -28,11 +28,31 @@ ${project.artifactId} The compatible module of dubbo project + + org.apache.dubbo + dubbo-container-api + ${project.parent.version} + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + jetty-servlet + + + org.apache.dubbo dubbo-filter-cache ${project.parent.version} + + org.apache.dubbo + dubbo-filter-validation + ${project.parent.version} + org.apache.dubbo dubbo-config-spring diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index 0935057b368..f4ef6e0a57e 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -59,11 +59,13 @@ org.apache.dubbo dubbo-filter-validation ${project.parent.version} + test org.apache.dubbo dubbo-filter-cache ${project.parent.version} + test diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java index 7c6e02db639..e69900055e3 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java @@ -208,6 +208,7 @@ public synchronized T get() { return ref; } + @Override public synchronized void destroy() { if (ref == null) { return; @@ -236,6 +237,10 @@ public synchronized void init() { if (bootstrap == null) { bootstrap = DubboBootstrap.getInstance(); + // compatible with api call. + if (null != this.getRegistries()) { + bootstrap.registries(this.getRegistries()); + } bootstrap.initialize(); } 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 b5182312ea3..0afbf18228f 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 @@ -96,6 +96,7 @@ import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_BIND; import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_REGISTRY; import static org.apache.dubbo.config.Constants.MULTICAST; +import static org.apache.dubbo.config.Constants.MULTIPLE; import static org.apache.dubbo.config.Constants.SCOPE_NONE; import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY; import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY; @@ -215,6 +216,10 @@ public void unexport() { public synchronized void export() { if (bootstrap == null) { bootstrap = DubboBootstrap.getInstance(); + // compatible with api call. + if (null != this.getRegistry()) { + bootstrap.registries(this.getRegistries()); + } bootstrap.initialize(); } @@ -630,6 +635,10 @@ private String findConfigedHosts(ProtocolConfig protocolConfig, // skip multicast registry since we cannot connect to it via Socket continue; } + if (MULTIPLE.equalsIgnoreCase(registryURL.getParameter("registry"))) { + // skip, multiple-registry address is a fake ip + continue; + } try (Socket socket = new Socket()) { SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort()); socket.connect(addr, 1000); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java index 10ad5e87712..ee94001469d 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java @@ -680,6 +680,10 @@ private ConfigCenterConfig registryAsConfigCenter(RegistryConfig registryConfig) String protocol = registryConfig.getProtocol(); Integer port = registryConfig.getPort(); String id = "config-center-" + protocol + "-" + port; + if (configManager.getConfigCenter(id) != null) { + return null; + } + ConfigCenterConfig cc = new ConfigCenterConfig(); cc.setId(id); if (cc.getParameters() == null) { @@ -781,6 +785,10 @@ private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryCon String protocol = registryConfig.getProtocol(); Integer port = registryConfig.getPort(); String id = "metadata-center-" + protocol + "-" + port; + if (configManager.getMetadataConfig(id) != null) { + return null; + } + MetadataReportConfig metadataReportConfig = new MetadataReportConfig(); metadataReportConfig.setId(id); if (metadataReportConfig.getParameters() == null) { @@ -1178,7 +1186,7 @@ private void doRegisterServiceInstance(ServiceInstance serviceInstance) { { calInstanceRevision(serviceDiscovery, serviceInstance); if (logger.isDebugEnabled()) { - logger.info("Start registering instance address to registry" + serviceDiscovery.getUrl() + ", instance " + serviceInstance); + logger.debug("Start registering instance address to registry" + serviceDiscovery.getUrl() + ", instance " + serviceInstance); } // register metadata serviceDiscovery.register(serviceInstance); @@ -1200,9 +1208,6 @@ private URL selectMetadataServiceExportedURL() { for (String urlValue : urlValues) { URL url = URL.valueOf(urlValue); - if (MetadataService.class.getName().equals(url.getServiceInterface())) { - continue; - } if ("rest".equals(url.getProtocol())) { // REST first selectedURL = url; break; @@ -1244,8 +1249,6 @@ private ServiceInstance createServiceInstance(String serviceName, String host, i public void destroy() { if (destroyLock.tryLock()) { try { - DubboShutdownHook.destroyAll(); - if (started.compareAndSet(true, false) && destroyed.compareAndSet(false, true)) { @@ -1264,6 +1267,8 @@ public void destroy() { ExtensionLoader exts = getExtensionLoader(DubboBootstrapStartStopListener.class); exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(this)); } + + DubboShutdownHook.destroyAll(); } finally { destroyLock.unlock(); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConsumerBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConsumerBuilder.java index dd37e92e467..cb7fab59472 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConsumerBuilder.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConsumerBuilder.java @@ -61,6 +61,12 @@ public class ConsumerBuilder extends AbstractReferenceBuilder 0) { address = sysaddress; } else if (monitor != null) { @@ -331,8 +336,8 @@ public static void checkMock(Class interfaceClass, AbstractInterfaceConfig co public static void validateAbstractInterfaceConfig(AbstractInterfaceConfig config) { checkName(LOCAL_KEY, config.getLocal()); - checkName("stub", config.getStub()); - checkMultiName("owner", config.getOwner()); + checkName(STUB_KEY, config.getStub()); + checkMultiName(OWNER, config.getOwner()); checkExtension(ProxyFactory.class, PROXY_KEY, config.getProxy()); checkExtension(Cluster.class, CLUSTER_KEY, config.getCluster()); @@ -351,7 +356,7 @@ public static void validateServiceConfig(ServiceConfig config) { checkName(TOKEN_KEY, config.getToken()); checkPathName(PATH_KEY, config.getPath()); - checkMultiExtension(ExporterListener.class, "listener", config.getListener()); + checkMultiExtension(ExporterListener.class, LISTENER_KEY, config.getListener()); validateAbstractInterfaceConfig(config); @@ -376,7 +381,7 @@ public static void validateServiceConfig(ServiceConfig config) { } public static void validateReferenceConfig(ReferenceConfig config) { - checkMultiExtension(InvokerListener.class, "listener", config.getListener()); + checkMultiExtension(InvokerListener.class, LISTENER_KEY, config.getListener()); checkKey(VERSION_KEY, config.getVersion()); checkKey(GROUP_KEY, config.getGroup()); checkName(CLIENT_KEY, config.getClient()); @@ -471,9 +476,9 @@ public static void validateMonitorConfig(MonitorConfig config) { public static void validateProtocolConfig(ProtocolConfig config) { if (config != null) { String name = config.getName(); - checkName("name", name); + checkName(NAME, name); checkHost(HOST_KEY, config.getHost()); - checkPathName("contextpath", config.getContextpath()); + checkPathName(CONTEXTPATH_KEY, config.getContextpath()); if (DUBBO_PROTOCOL.equals(name)) { @@ -484,11 +489,11 @@ public static void validateProtocolConfig(ProtocolConfig config) { } checkMultiExtension(TelnetHandler.class, TELNET, config.getTelnet()); - checkMultiExtension(StatusChecker.class, "status", config.getStatus()); + checkMultiExtension(StatusChecker.class, STATUS_KEY, config.getStatus()); checkExtension(Transporter.class, TRANSPORTER_KEY, config.getTransporter()); checkExtension(Exchanger.class, EXCHANGER_KEY, config.getExchanger()); checkExtension(Dispatcher.class, DISPATCHER_KEY, config.getDispatcher()); - checkExtension(Dispatcher.class, "dispather", config.getDispather()); + checkExtension(Dispatcher.class, DISPATHER, config.getDispather()); checkExtension(ThreadPool.class, THREADPOOL_KEY, config.getThreadpool()); } } @@ -522,7 +527,7 @@ public static void validateRegistryConfig(RegistryConfig config) { public static void validateMethodConfig(MethodConfig config) { checkExtension(LoadBalance.class, LOADBALANCE_KEY, config.getLoadbalance()); checkParameterName(config.getParameters()); - checkMethodName("name", config.getName()); + checkMethodName(NAME, config.getName()); String mock = config.getMock(); if (StringUtils.isNotEmpty(mock)) { @@ -630,7 +635,7 @@ public static void checkParameterName(Map parameters) { ignoreCheckKeys.add(BACKUP_KEY); String ignoreCheckKeysStr = parameters.get(IGNORE_CHECK_KEYS); if (!StringUtils.isBlank(ignoreCheckKeysStr)) { - ignoreCheckKeys.addAll(Arrays.asList(ignoreCheckKeysStr.split(","))); + ignoreCheckKeys.addAll(Arrays.asList(ignoreCheckKeysStr.split(COMMA_SEPARATOR))); } for (Map.Entry entry : parameters.entrySet()) { if (!ignoreCheckKeys.contains(entry.getKey())) { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java index 9cc037a8b4b..7bad3d5fdab 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java @@ -29,6 +29,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import static org.apache.dubbo.common.BaseServiceMetadata.buildServiceKey; + /** * A simple util class for cache {@link ReferenceConfigBase}. *

@@ -54,15 +56,7 @@ public class ReferenceConfigCache { throw new IllegalArgumentException("No interface info in ReferenceConfig" + referenceConfig); } - StringBuilder ret = new StringBuilder(); - if (!StringUtils.isBlank(referenceConfig.getGroup())) { - ret.append(referenceConfig.getGroup()).append("/"); - } - ret.append(iName); - if (!StringUtils.isBlank(referenceConfig.getVersion())) { - ret.append(":").append(referenceConfig.getVersion()); - } - return ret.toString(); + return buildServiceKey(iName, referenceConfig.getGroup(), referenceConfig.getVersion()); }; static final ConcurrentMap CACHE_HOLDER = new ConcurrentHashMap(); diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/SslConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/SslConfigTest.java new file mode 100644 index 00000000000..4547c6ada03 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/SslConfigTest.java @@ -0,0 +1,142 @@ +/* + * 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.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class SslConfigTest { + + @Test + public void testServerKeyCertChainPath() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setServerKeyCertChainPath("test-server-key-cert-chain-path"); + assertThat(sslConfig.getServerKeyCertChainPath(),equalTo("test-server-key-cert-chain-path")); + } + + @Test + public void testServerPrivateKeyPath() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setServerPrivateKeyPath("test-server-private-key-path"); + assertThat(sslConfig.getServerPrivateKeyPath(),equalTo("test-server-private-key-path")); + } + + @Test + public void testServerKeyPassword() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setServerKeyPassword("test-server-key-password"); + assertThat(sslConfig.getServerKeyPassword(),equalTo("test-server-key-password")); + } + + @Test + public void testServerTrustCertCollectionPath() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setServerTrustCertCollectionPath("test-server-trust-cert-collection-path"); + assertThat(sslConfig.getServerTrustCertCollectionPath(),equalTo("test-server-trust-cert-collection-path")); + } + + @Test + public void testClientKeyCertChainPath() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setClientKeyCertChainPath("test-client-trust-cert-collection-path"); + assertThat(sslConfig.getClientKeyCertChainPath(),equalTo("test-client-trust-cert-collection-path")); + } + + @Test + public void testClientPrivateKeyPath() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setClientPrivateKeyPath("test-client-private-key-path"); + assertThat(sslConfig.getClientPrivateKeyPath(),equalTo("test-client-private-key-path")); + } + + @Test + public void testClientKeyPassword() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setClientKeyPassword("test-client-key-password"); + assertThat(sslConfig.getClientKeyPassword(),equalTo("test-client-key-password")); + } + + @Test + public void testClientTrustCertCollectionPath() throws Exception { + SslConfig sslConfig = new SslConfig(); + sslConfig.setClientTrustCertCollectionPath("test-client-trust-cert-collection-path"); + assertThat(sslConfig.getClientTrustCertCollectionPath(),equalTo("test-client-trust-cert-collection-path")); + } + + @Test + public void testServerKeyCertChainPathStream() throws Exception { + SslConfig sslConfig = new SslConfig(); + String string = "test-server-key-cert-chain-path-stream"; + InputStream inputStream = IOUtils.toInputStream(string, StandardCharsets.UTF_8); + sslConfig.setServerKeyCertChainPathStream(inputStream); + assertThat(sslConfig.getServerKeyCertChainPathStream(),equalTo(inputStream)); + } + + @Test + public void testServerPrivateKeyPathStream() throws Exception { + SslConfig sslConfig = new SslConfig(); + String string = "test-server-private-key-path-stream"; + InputStream inputStream = IOUtils.toInputStream(string, StandardCharsets.UTF_8); + sslConfig.setServerPrivateKeyPathStream(inputStream); + assertThat(sslConfig.getServerPrivateKeyPathStream(),equalTo(inputStream)); + } + + @Test + public void testServerTrustCertCollectionPathStream() throws Exception { + SslConfig sslConfig = new SslConfig(); + String string = "test-server-trust-cert-collection-path-stream"; + InputStream inputStream = IOUtils.toInputStream(string, StandardCharsets.UTF_8); + sslConfig.setServerTrustCertCollectionPathStream(inputStream); + assertThat(sslConfig.getServerTrustCertCollectionPathStream(),equalTo(inputStream)); + } + + @Test + public void testClientKeyCertChainPathStream() throws Exception { + SslConfig sslConfig = new SslConfig(); + String string = "test-client-key-cert-chain-path-stream"; + InputStream inputStream = IOUtils.toInputStream(string, StandardCharsets.UTF_8); + sslConfig.setClientKeyCertChainPathStream(inputStream); + assertThat(sslConfig.getClientKeyCertChainPathStream(),equalTo(inputStream)); + } + + @Test + public void testClientPrivateKeyPathStream() throws Exception { + SslConfig sslConfig = new SslConfig(); + String string = "test-client-private-key-path-stream"; + InputStream inputStream = IOUtils.toInputStream(string, StandardCharsets.UTF_8); + sslConfig.setClientPrivateKeyPathStream(inputStream); + assertThat(sslConfig.getClientPrivateKeyPathStream(),equalTo(inputStream)); + } + + @Test + public void testClientTrustCertCollectionPathStream() throws Exception { + SslConfig sslConfig = new SslConfig(); + String string = "test-client-trust-cert-collection-path-stream"; + InputStream inputStream = IOUtils.toInputStream(string, StandardCharsets.UTF_8); + sslConfig.setClientTrustCertCollectionPathStream(inputStream); + assertThat(sslConfig.getClientTrustCertCollectionPathStream(),equalTo(inputStream)); + } + +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java index e329f235119..1fffe4c1a93 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java @@ -101,21 +101,25 @@ public void compatibleApplicationShutdown() { @Test public void testLoadRegistries() { - System.setProperty("dubbo.registry.address", "addr1"); - AbstractInterfaceConfigTest.InterfaceConfig interfaceConfig = new AbstractInterfaceConfigTest.InterfaceConfig(); - // FIXME: now we need to check first, then load - interfaceConfig.setApplication(new ApplicationConfig("testLoadRegistries")); - interfaceConfig.checkRegistry(); - List urls = ConfigValidationUtils.loadRegistries(interfaceConfig, true); - Assertions.assertEquals(1, urls.size()); - URL url = urls.get(0); - Assertions.assertEquals("registry", url.getProtocol()); - Assertions.assertEquals("addr1:9090", url.getAddress()); - Assertions.assertEquals(RegistryService.class.getName(), url.getPath()); - Assertions.assertTrue(url.getParameters().containsKey("timestamp")); - Assertions.assertTrue(url.getParameters().containsKey("pid")); - Assertions.assertTrue(url.getParameters().containsKey("registry")); - Assertions.assertTrue(url.getParameters().containsKey("dubbo")); + try { + System.setProperty("dubbo.registry.address", "addr1"); + AbstractInterfaceConfigTest.InterfaceConfig interfaceConfig = new AbstractInterfaceConfigTest.InterfaceConfig(); + // FIXME: now we need to check first, then load + interfaceConfig.setApplication(new ApplicationConfig("testLoadRegistries")); + interfaceConfig.checkRegistry(); + List urls = ConfigValidationUtils.loadRegistries(interfaceConfig, true); + Assertions.assertEquals(1, urls.size()); + URL url = urls.get(0); + Assertions.assertEquals("registry", url.getProtocol()); + Assertions.assertEquals("addr1:9090", url.getAddress()); + Assertions.assertEquals(RegistryService.class.getName(), url.getPath()); + Assertions.assertTrue(url.getParameters().containsKey("timestamp")); + Assertions.assertTrue(url.getParameters().containsKey("pid")); + Assertions.assertTrue(url.getParameters().containsKey("registry")); + Assertions.assertTrue(url.getParameters().containsKey("dubbo")); + } finally { + System.clearProperty("dubbo.registry.address"); + } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java index 28b6a6cf8b1..e6ea0603bbe 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java @@ -39,7 +39,7 @@ public class DubboConfigAliasPostProcessor implements BeanDefinitionRegistryPost /** * The bean name of {@link DubboConfigConfigurationRegistrar} */ - public final static String BEAN_NAME = "dubboConfigAliasPostProcessor"; + public static final String BEAN_NAME = "dubboConfigAliasPostProcessor"; private BeanDefinitionRegistry registry; diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java index aa2ab886f6f..a429358a49b 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java @@ -90,7 +90,7 @@ public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware, ResourceLoaderAware, BeanClassLoaderAware { - private final static List> serviceAnnotationTypes = asList( + private static final List> serviceAnnotationTypes = asList( // @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007 DubboService.class, // @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd index 0fc55896912..a0ea159997f 100644 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd @@ -982,6 +982,11 @@ + + + + + diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java index b14f172bb91..11ae86a8de1 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java @@ -24,7 +24,10 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; import java.io.FileOutputStream; import java.io.IOException; @@ -41,6 +44,7 @@ * Notice: EmbeddedApollo(apollo mock server) only support < junit5, please not upgrade the junit version in this UT, * the junit version in this UT is junit4, and the dependency comes from apollo-mockserver. */ +@TestMethodOrder(OrderAnnotation.class) public class ApolloDynamicConfigurationTest { private static final String SESSION_TIMEOUT_KEY = "session"; private static final String DEFAULT_NAMESPACE = "dubbo"; @@ -84,6 +88,7 @@ public void setUp() { * Test get rule. */ @Test + @Order(1) public void testGetRule() { String mockKey = "mockKey1"; String mockValue = String.valueOf(new Random().nextInt()); @@ -101,6 +106,7 @@ public void testGetRule() { * @throws InterruptedException the interrupted exception */ @Test + @Order(2) public void testGetInternalProperty() throws InterruptedException { String mockKey = "mockKey2"; String mockValue = String.valueOf(new Random().nextInt()); @@ -123,6 +129,7 @@ public void testGetInternalProperty() throws InterruptedException { * @throws Exception the exception */ @Test + @Order(3) public void testAddListener() throws Exception { String mockKey = "mockKey3"; String mockValue = String.valueOf(new Random().nextInt()); @@ -145,6 +152,44 @@ public void process(org.apache.dubbo.common.config.configcenter.ConfigChangedEve assertEquals(ConfigChangeType.MODIFIED, result.getChangeType()); } + /** + * Test remove listener. + * + * @throws Exception the exception + */ + @Test + @Order(4) + public void testRemoveListener() throws Exception { + String mockKey = "mockKey4"; + String mockValue = String.valueOf(new Random().nextInt()); + + final SettableFuture future = SettableFuture.create(); + + apolloDynamicConfiguration = new ApolloDynamicConfiguration(url); + apolloDynamicConfiguration.addListener(mockKey, DEFAULT_NAMESPACE, new ConfigurationListener() { + @Override + public void process(org.apache.dubbo.common.config.configcenter.ConfigChangedEvent event) { + future.set(event); + } + }); + + putData(mockKey, mockValue); + future.get(3000, TimeUnit.MILLISECONDS); + + apolloDynamicConfiguration.removeListener(mockKey, DEFAULT_NAMESPACE, new ConfigurationListener() { + @Override + public void process(org.apache.dubbo.common.config.configcenter.ConfigChangedEvent event) { + future.set(event); + } + }); + + deleteData(mockKey); + org.apache.dubbo.common.config.configcenter.ConfigChangedEvent result = future.get(3000, TimeUnit.MILLISECONDS); + assertEquals(mockValue, result.getContent()); + assertEquals(mockKey, result.getKey()); + assertEquals(ConfigChangeType.MODIFIED, result.getChangeType()); + } + private static void putData(String namespace, String key, String value) { embeddedApollo.addOrModifyProperty(namespace, key, value); } @@ -153,6 +198,9 @@ private static void putData(String key, String value) { embeddedApollo.addOrModifyProperty(DEFAULT_NAMESPACE, key, value); } + private static void deleteData(String key) { + embeddedApollo.deleteProperty(DEFAULT_NAMESPACE, key); + } private static void putMockRuleData(String key, String value, String group) { String fileName = ApolloDynamicConfigurationTest.class.getResource("/").getPath() + "mockdata-" + group + ".properties"; putMockData(key, value, fileName); 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 66bd0e9e528..494b36a8804 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 @@ -57,6 +57,10 @@ public void removeListener(String key, ConfigurationListener configurationListen } } + public void removeAllListeners() { + keyListeners.clear(); + } + public Set getConfigurationListeners(String key) { return keyListeners.get(key); } diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java index 6489ab105b8..d445bd3c211 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.Set; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -81,6 +82,13 @@ public String getInternalProperty(String key) { @Override protected void doClose() throws Exception { zkClient.close(); + if (executor instanceof ExecutorService) { + ExecutorService executorService = (ExecutorService) executor; + if (!executorService.isShutdown()) { + executorService.shutdown(); + } + } + cacheListener.removeAllListeners(); } @Override 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 518ab9a8dfb..1792dcfa049 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 @@ -31,6 +31,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.HashMap; @@ -46,6 +47,7 @@ /** * TODO refactor using mockito */ +@Disabled("Disabled Due to Zookeeper in Github Actions") public class ZookeeperDynamicConfigurationTest { private CuratorFramework client; diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml index 1e5a7d51b39..b2682e855ef 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml @@ -51,6 +51,14 @@ org.apache.dubbo dubbo-registry-nacos + + org.apache.dubbo + dubbo-registry-redis + + + org.apache.dubbo + dubbo-registry-multiple + com.alibaba.nacos nacos-client diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml index e7d33968659..e5e30a77566 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml @@ -42,6 +42,14 @@ org.apache.dubbo dubbo-registry-multicast + + org.apache.dubbo + dubbo-registry-redis + + + org.apache.dubbo + dubbo-registry-multiple + org.apache.dubbo dubbo-registry-nacos 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 05d6f8f684a..a0b3a5f04cf 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 @@ -29,6 +29,8 @@ + + diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 84442a3faf4..77d2e6b2690 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -93,6 +93,7 @@ 3.23.1-GA 3.2.5.Final 4.1.51.Final + 2.0.39.Final 1.1.7 2.4.4 4.5.3 @@ -195,6 +196,12 @@ netty-all ${netty4_version} + + io.netty + netty-tcnative-boringssl-static + ${netty4_ssl_version} + test + org.apache.mina mina-core diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java index 77256bb5ee5..8c582033881 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java @@ -16,18 +16,21 @@ */ package org.apache.dubbo.cache; +import org.apache.dubbo.cache.support.lru.LruCacheFactory; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Adaptive; import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.rpc.Invocation; +import static org.apache.dubbo.common.constants.FilterConstants.CACHE_KEY; + /** * Interface needs to be implemented by all the cache store provider.Along with implementing CacheFactory interface * entry needs to be added in org.apache.dubbo.cache.CacheFactory file in a classpath META-INF sub directories. * * @see Cache */ -@SPI("lru") +@SPI(LruCacheFactory.NAME) public interface CacheFactory { /** @@ -37,7 +40,7 @@ public interface CacheFactory { * @param invocation * @return Instance of Cache containing cached value against method url and invocation. */ - @Adaptive("cache") + @Adaptive(CACHE_KEY) Cache getCache(URL url, Invocation invocation); } diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java index 5259d74b6eb..3330d738e56 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java @@ -32,6 +32,8 @@ public class ExpiringCacheFactory extends AbstractCacheFactory { + public static final String NAME = "expiring"; + /** * Takes url as an method argument and return new instance of cache store implemented by JCache. * @param url url of the method diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java index c4d713f0b17..be5640ce584 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java @@ -35,6 +35,8 @@ */ public class JCacheFactory extends AbstractCacheFactory { + public static final String NAME = "jcache"; + /** * Takes url as an method argument and return new instance of cache store implemented by JCache. * @param url url of the method diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lfu/LfuCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lfu/LfuCacheFactory.java index f04edca4290..7fd384b9d37 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lfu/LfuCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lfu/LfuCacheFactory.java @@ -30,6 +30,8 @@ */ public class LfuCacheFactory extends AbstractCacheFactory { + public static final String NAME = "lfu"; + /** * Takes url as an method argument and return new instance of cache store implemented by LfuCache. * @param url url of the method diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java index cda21292e8f..b118399196d 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java @@ -30,6 +30,8 @@ */ public class LruCacheFactory extends AbstractCacheFactory { + public static final String NAME = "lru"; + /** * Takes url as an method argument and return new instance of cache store implemented by LruCache. * @param url url of the method diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java index d094668bb29..8245d5dbd34 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java @@ -80,7 +80,7 @@ */ public abstract class AbstractMetadataReport implements MetadataReport { - protected final static String DEFAULT_ROOT = "dubbo"; + protected static final String DEFAULT_ROOT = "dubbo"; private static final int ONE_DAY_IN_MILLISECONDS = 60 * 24 * 60 * 1000; private static final int FOUR_HOURS_IN_MILLISECONDS = 60 * 4 * 60 * 1000; diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataResolver.java index d2e400af523..fb042325411 100644 --- a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataResolver.java +++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataResolver.java @@ -61,9 +61,9 @@ */ public abstract class AbstractServiceRestMetadataResolver implements ServiceRestMetadataResolver { - private final static ThreadLocal> threadLocalCache = withInitial(HashMap::new); + private static final ThreadLocal> threadLocalCache = withInitial(HashMap::new); - private final static Map> parameterProcessorsMap = loadAnnotatedMethodParameterProcessors(); + private static final Map> parameterProcessorsMap = loadAnnotatedMethodParameterProcessors(); private final String processorName = getClass().getSimpleName(); diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ExecutableElementComparator.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ExecutableElementComparator.java index 31603faabef..183101c9514 100644 --- a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ExecutableElementComparator.java +++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ExecutableElementComparator.java @@ -36,7 +36,7 @@ */ public class ExecutableElementComparator implements Comparator { - public final static ExecutableElementComparator INSTANCE = new ExecutableElementComparator(); + public static final ExecutableElementComparator INSTANCE = new ExecutableElementComparator(); private ExecutableElementComparator() { } diff --git a/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java index 93e9eaf0365..5d49f4c2345 100644 --- a/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java +++ b/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java @@ -50,15 +50,15 @@ */ public class RedisMetadataReport extends AbstractMetadataReport { - private final static String REDIS_DATABASE_KEY = "database"; + private static final String REDIS_DATABASE_KEY = "database"; /** * maximum number of retries */ - private final static int MAX_ATTEMPTS = 2; + private static final int MAX_ATTEMPTS = 2; /** * the default slot of the redis database */ - private final static int DEFAULT_REDIS_DATABASE_SLOT = 0; + private static final int DEFAULT_REDIS_DATABASE_SLOT = 0; JedisPool pool; Set jedisClusterNodes; diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java index b7851167d25..a620d06b0b4 100644 --- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java +++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java @@ -27,9 +27,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.SynchronousQueue; @@ -55,7 +53,7 @@ public abstract class AbstractMonitorFactory implements MonitorFactory { */ private static final Map MONITORS = new ConcurrentHashMap(); - private static final Map> FUTURES = new ConcurrentHashMap>(); + private static final Map> FUTURES = new ConcurrentHashMap>(); /** * The monitor create executor @@ -85,10 +83,18 @@ public Monitor getMonitor(URL url) { } final URL monitorUrl = url; - final CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> AbstractMonitorFactory.this.createMonitor(monitorUrl)); - FUTURES.put(key, completableFuture); - completableFuture.thenRunAsync(new MonitorListener(key), EXECUTOR); - + future = EXECUTOR.submit(() -> { + try { + Monitor m = createMonitor(monitorUrl); + MONITORS.put(key, m); + FUTURES.remove(key); + return m; + } catch (Throwable e) { + logger.warn("Create monitor failed, monitor data will not be collected until you fix this problem. monitorUrl: " + monitorUrl, e); + return null; + } + }); + FUTURES.put(key, future); return null; } finally { // unlock @@ -98,28 +104,4 @@ public Monitor getMonitor(URL url) { protected abstract Monitor createMonitor(URL url); - - class MonitorListener implements Runnable { - - private String key; - - public MonitorListener(String key) { - this.key = key; - } - - @Override - public void run() { - try { - CompletableFuture completableFuture = AbstractMonitorFactory.FUTURES.get(key); - AbstractMonitorFactory.MONITORS.put(key, completableFuture.get()); - AbstractMonitorFactory.FUTURES.remove(key); - } catch (InterruptedException e) { - logger.warn("Thread was interrupted unexpectedly, monitor will never be got."); - AbstractMonitorFactory.FUTURES.remove(key); - } catch (ExecutionException e) { - logger.warn("Create monitor failed, monitor data will not be collected until you fix this problem. ", e); - } - } - } - } diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java index a51c7e75006..dab941d89d7 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java +++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java @@ -19,14 +19,18 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.monitor.Monitor; import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.ProtocolServer; import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol; +import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import java.util.List; + import static org.apache.dubbo.common.constants.CommonConstants.REFERENCE_FILTER_KEY; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.nullValue; @@ -45,10 +49,19 @@ public class DubboMonitorFactoryTest { public void setUp() throws Exception { initMocks(this); this.dubboMonitorFactory = new DubboMonitorFactory(); - this.dubboMonitorFactory.setProtocol(new DubboProtocol()); + this.dubboMonitorFactory.setProtocol(DubboProtocol.getDubboProtocol()); this.dubboMonitorFactory.setProxyFactory(proxyFactory); } + @AfterEach + public void tearDownAfterClass() { + DubboProtocol.getDubboProtocol().destroy(); + List servers = DubboProtocol.getDubboProtocol().getServers(); + for (ProtocolServer server : servers) { + server.close(); + } + } + @Test public void testCreateMonitor() { URL urlWithoutPath = URL.valueOf("http://10.10.10.11"); diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java index ada0e6f51c5..97b67a17974 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java +++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java @@ -266,7 +266,7 @@ public void testInvokeMetricsService() { //ignore } } - Protocol protocol = new DubboProtocol(); + Protocol protocol = DubboProtocol.getDubboProtocol(); URL metricUrl = URL.valueOf("dubbo://" + url.getHost() + ":" + url.getPort() + "/" + MetricsService.class.getName() + "?" + METRICS_PORT + "=" + port); Invoker invoker = protocol.refer(MetricsService.class, metricUrl); invocation = new RpcInvocation("getMetricsByGroup", DemoService.class.getName(), "", new Class[]{String.class}, new Object[]{DUBBO_GROUP}); @@ -291,6 +291,8 @@ public void testInvokeMetricsService() { Assertions.assertEquals(100.0, metricMap.get("bucket_count")); Assertions.assertEquals(100.0 / 5, metricMap.get("qps")); Assertions.assertEquals(50.0 / 100.0, metricMap.get("success_rate")); + + invoker.destroy(); } public void testInvokeMetricsMethodService() { @@ -320,7 +322,7 @@ public void testInvokeMetricsMethodService() { } } - Protocol protocol = new DubboProtocol(); + Protocol protocol = DubboProtocol.getDubboProtocol(); URL metricUrl = URL.valueOf("dubbo://" + url.getHost() + ":" + url.getPort() + "/" + MetricsService.class.getName() + "?" + METRICS_PORT + "=" + port); Invoker invoker = protocol.refer(MetricsService.class, metricUrl); Invocation invocation = new RpcInvocation("getMetricsByGroup", DemoService.class.getName(), "", new Class[]{String.class}, new Object[]{DUBBO_GROUP}); @@ -365,5 +367,7 @@ public void testInvokeMetricsMethodService() { methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void sayName()").get("success_rate")); Assertions.assertEquals(50.0 / 100.0, methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void echo(Integer)").get("success_rate")); + + invoker.destroy(); } } diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/DefaultCommandExecutor.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/DefaultCommandExecutor.java index 342f256de1d..e499e1364c6 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/DefaultCommandExecutor.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/DefaultCommandExecutor.java @@ -17,13 +17,17 @@ package org.apache.dubbo.qos.command; import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.StringUtils; + +import static org.apache.dubbo.common.constants.CommonConstants.PROPERTIES_CHAR_SEPARATOR; public class DefaultCommandExecutor implements CommandExecutor { @Override public String execute(CommandContext commandContext) throws NoSuchCommandException { BaseCommand command = null; try { - command = ExtensionLoader.getExtensionLoader(BaseCommand.class).getExtension(commandContext.getCommandName()); + String extName = StringUtils.camelToSplitName(commandContext.getCommandName(), PROPERTIES_CHAR_SEPARATOR); + command = ExtensionLoader.getExtensionLoader(BaseCommand.class).getExtension(extName); } catch (Throwable throwable) { //can't find command } diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Help.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Help.java index ba370ccd85f..696d58f102d 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Help.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Help.java @@ -25,18 +25,25 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; @Cmd(name = "help", summary = "help command", example = { "help", "help online" }) public class Help implements BaseCommand { + + private static final String MAIN_HELP = "mainHelp"; + + private static Map processedTable = new WeakHashMap<>(); + @Override public String execute(CommandContext commandContext, String[] args) { if (args != null && args.length > 0) { - return commandHelp(args[0]); + return processedTable.computeIfAbsent(args[0], commandName -> commandHelp(commandName)); } else { - return mainHelp(); + return processedTable.computeIfAbsent(MAIN_HELP, commandName -> mainHelp()); } } diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/PublishMetadata.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/PublishMetadata.java index 990854c04af..1e54e19bf20 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/PublishMetadata.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/PublishMetadata.java @@ -51,7 +51,7 @@ public String execute(CommandContext commandContext, String[] args) { int delay = Integer.parseInt(args[0]); if (future == null || future.isDone() || future.isCancelled()) { future = executorRepository.nextScheduledExecutor() - .scheduleWithFixedDelay(ServiceInstanceMetadataUtils::refreshMetadataAndInstance, 0, delay, TimeUnit.MILLISECONDS); + .schedule(ServiceInstanceMetadataUtils::refreshMetadataAndInstance, delay, TimeUnit.SECONDS); } } catch (NumberFormatException e) { logger.error("Wrong delay param", e); diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java index 2c6b4226a37..156a8a7a836 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java @@ -32,7 +32,10 @@ import java.util.Map; import java.util.stream.Collectors; -@Cmd(name = "ready",summary = "Judge if application or service has started? ") +@Cmd(name = "ready", summary = "Judge if application or service has started? ", example = { + "ready", + "ready xx.xx.xxx.service" +}) public class Ready implements BaseCommand { @Override diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java index 0f33ae38adc..cc6cdba1c87 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java @@ -26,10 +26,7 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.util.concurrent.DefaultThreadFactory; - +import org.apache.dubbo.remoting.transport.netty4.NettyEventLoopFactory; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -85,11 +82,11 @@ public void start() throws Throwable { if (!started.compareAndSet(false, true)) { return; } - boss = new NioEventLoopGroup(1, new DefaultThreadFactory("qos-boss", true)); - worker = new NioEventLoopGroup(0, new DefaultThreadFactory("qos-worker", true)); + boss = NettyEventLoopFactory.eventLoopGroup(1, "qos-boss"); + worker = NettyEventLoopFactory.eventLoopGroup(0, "qos-worker"); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(boss, worker); - serverBootstrap.channel(NioServerSocketChannel.class); + serverBootstrap.channel(NettyEventLoopFactory.serverSocketChannelClass()); serverBootstrap.option(ChannelOption.SO_REUSEADDR, true); serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true); serverBootstrap.childHandler(new ChannelInitializer() { diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/handler/HttpProcessHandler.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/handler/HttpProcessHandler.java index 408e1857c96..5f0ad93541b 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/handler/HttpProcessHandler.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/handler/HttpProcessHandler.java @@ -56,48 +56,44 @@ public class HttpProcessHandler extends SimpleChannelInboundHandler protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception { CommandContext commandContext = HttpCommandDecoder.decode(msg); // return 404 when fail to construct command context + FullHttpResponse response; if (commandContext == null) { log.warn("can not found commandContext url: " + msg.getUri()); - FullHttpResponse response = http404(); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + response = http404(); } else { commandContext.setRemote(ctx.channel()); try { String result = commandExecutor.execute(commandContext); - FullHttpResponse response = http200(result); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + response = http200(result); } catch (NoSuchCommandException ex) { log.error("can not find commandContext: " + commandContext, ex); - FullHttpResponse response = http404(); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + response = http404(); } catch (Exception qosEx) { log.error("execute commandContext: " + commandContext + " got exception", qosEx); - FullHttpResponse response = http500(qosEx.getMessage()); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + response = http500(qosEx.getMessage()); } } + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } private static final FullHttpResponse http200(String result) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(result.getBytes())); - HttpHeaders httpHeaders = response.headers(); - httpHeaders.set(HttpHeaders.Names.CONTENT_TYPE, "text/plain"); - httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes()); - return response; + return fillFullHttpResponse(response); } private static final FullHttpResponse http404() { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND); - HttpHeaders httpHeaders = response.headers(); - httpHeaders.set(HttpHeaders.Names.CONTENT_TYPE, "text/plain"); - httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes()); - return response; + return fillFullHttpResponse(response); } private static final FullHttpResponse http500(String errorMessage) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR , Unpooled.wrappedBuffer(errorMessage.getBytes())); + return fillFullHttpResponse(response); + } + + private static FullHttpResponse fillFullHttpResponse(FullHttpResponse response) { HttpHeaders httpHeaders = response.headers(); httpHeaders.set(HttpHeaders.Names.CONTENT_TYPE, "text/plain"); httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes()); diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/PublishMetadataTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/PublishMetadataTest.java new file mode 100644 index 00000000000..6e60eba12b1 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/PublishMetadataTest.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.qos.command.impl; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class PublishMetadataTest { + + @BeforeEach + public void setUp() { + ApplicationModel.getConfigManager().setApplication(new ApplicationConfig("app")); + } + + @AfterEach + public void clear(){ + ApplicationModel.reset(); + } + + @Test + public void testNoDelay() { + PublishMetadata publishMetadata = new PublishMetadata(); + String msg = publishMetadata.execute(null, null); + Assertions.assertEquals(msg, "publish metadata succeeded."); + } + + @Test + public void testWithDelay() { + PublishMetadata publishMetadata = new PublishMetadata(); + String[] args = {"10"}; + String msg = publishMetadata.execute(null, args); + Assertions.assertEquals(msg,"publish task submitted, will publish in " + args[0] + " seconds."); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/VersionTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/VersionTest.java new file mode 100644 index 00000000000..50a73f38a31 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/VersionTest.java @@ -0,0 +1,29 @@ +/* + * 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.qos.command.impl; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class VersionTest { + @Test + public void test(){ + Version version = new Version(); + String msg = version.execute(null,null); + Assertions.assertNotNull(msg); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/support/DemoService.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/support/DemoService.java new file mode 100644 index 00000000000..d7f515e8384 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/support/DemoService.java @@ -0,0 +1,21 @@ +/* + * 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.qos.command.support; + +public interface DemoService { + void sayHello(String name); +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/support/impl/DemoServiceImpl.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/support/impl/DemoServiceImpl.java new file mode 100644 index 00000000000..2dbca55658d --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/support/impl/DemoServiceImpl.java @@ -0,0 +1,26 @@ +/* + * 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.qos.command.support.impl; + +import org.apache.dubbo.qos.command.support.DemoService; + +public class DemoServiceImpl implements DemoService { + @Override + public void sayHello(String name) { + System.out.println("hello :" + name); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CountTelnetHandlerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CountTelnetHandlerTest.java new file mode 100644 index 00000000000..1d6f77a6061 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CountTelnetHandlerTest.java @@ -0,0 +1,109 @@ +/* + * 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.qos.legacy; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.qos.legacy.channel.MockChannel; +import org.apache.dubbo.qos.legacy.service.DemoService; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.telnet.support.TelnetUtils; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcStatus; +import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; + +public class CountTelnetHandlerTest { + + private TelnetHandler handler = new CountTelnetHandler(); + private MockChannel mockChannel; + private Invoker mockInvoker; + private URL url = URL.valueOf("dubbo://127.0.0.1:20884/demo"); + private CountDownLatch latch; + + @BeforeEach + public void setUp() { + latch = new CountDownLatch(2); + mockChannel = new MockChannel(url, latch); + mockInvoker = mock(Invoker.class); + given(mockInvoker.getInterface()).willReturn(DemoService.class); + given(mockInvoker.getUrl()).willReturn(url); + } + + @AfterEach + public void tearDown() { + ProtocolUtils.closeAll(); + mockChannel.close(); + reset(mockInvoker); + } + + @Test + public void test() throws Exception { + String methodName = "sayHello"; + String message = "org.apache.dubbo.qos.legacy.service.DemoService sayHello 1"; + + DubboProtocol.getDubboProtocol().export(mockInvoker); + RpcStatus.beginCount(url, methodName); + RpcStatus.endCount(url, methodName, 10L, true); + handler.telnet(mockChannel, message); + latch.await(); + + StringBuilder sb = new StringBuilder(); + for (Object o : mockChannel.getReceivedObjects()) { + sb.append(o.toString()); + } + + assertThat(sb.toString(), containsString(buildTable(methodName, + 10, 10, "1", "0", "0"))); + } + + public static String buildTable(String methodName, long averageElapsed, + long maxElapsed, String total, String failed, String active) { + List header = new LinkedList<>(); + header.add("method"); + header.add("total"); + header.add("failed"); + header.add("active"); + header.add("average"); + header.add("max"); + + List> table = new LinkedList<>(); + List row = new LinkedList(); + row.add(methodName); + row.add(total); + row.add(failed); + row.add(active); + row.add(averageElapsed + "ms"); + row.add(maxElapsed + "ms"); + + table.add(row); + + return TelnetUtils.toTable(header, table); + } + +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/TraceTelnetHandlerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/TraceTelnetHandlerTest.java new file mode 100644 index 00000000000..13c626e7692 --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/TraceTelnetHandlerTest.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.qos.legacy; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.qos.legacy.service.DemoService; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol; +import org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter; +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 java.lang.reflect.Field; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; + +public class TraceTelnetHandlerTest { + + private TelnetHandler handler; + private Channel mockChannel; + private Invoker mockInvoker; + private URL url = URL.valueOf("dubbo://127.0.0.1:20884/demo"); + + @BeforeEach + public void setUp() { + handler = new TraceTelnetHandler(); + mockChannel = mock(Channel.class); + mockInvoker = mock(Invoker.class); + given(mockInvoker.getInterface()).willReturn(DemoService.class); + given(mockInvoker.getUrl()).willReturn(url); + } + + @AfterEach + public void tearDown() { + reset(mockChannel, mockInvoker); + ProtocolUtils.closeAll(); + } + + @Test + public void testTraceTelnetAddTracer() throws Exception { + String method = "sayHello"; + String message = "org.apache.dubbo.qos.legacy.service.DemoService sayHello 1"; + Class type = DemoService.class; + + DubboProtocol.getDubboProtocol().export(mockInvoker); + handler.telnet(mockChannel, message); + + String key = type.getName() + "." + method; + Field tracers = TraceFilter.class.getDeclaredField("TRACERS"); + tracers.setAccessible(true); + ConcurrentHashMap> map = + (ConcurrentHashMap>) tracers.get(new ConcurrentHashMap>()); + + Set channels = map.getOrDefault(key, null); + Assertions.assertNotNull(channels); + + Assertions.assertTrue(channels.contains(mockChannel)); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/channel/MockChannel.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/channel/MockChannel.java new file mode 100644 index 00000000000..4eb09a30edc --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/channel/MockChannel.java @@ -0,0 +1,145 @@ +/* + * 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.qos.legacy.channel; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +public class MockChannel implements Channel { + public static final String ERROR_WHEN_SEND = "error_when_send"; + InetSocketAddress localAddress; + InetSocketAddress remoteAddress; + private URL remoteUrl; + private ChannelHandler handler; + private boolean isClosed; + private volatile boolean closing; + private Map attributes = new HashMap(1); + private List receivedObjects = new LinkedList<>(); + private CountDownLatch latch; + + public MockChannel() { + + } + + public MockChannel(URL remoteUrl) { + this.remoteUrl = remoteUrl; + } + + public MockChannel(URL remoteUrl, CountDownLatch latch) { + this.remoteUrl = remoteUrl; + this.latch = latch; + } + + public MockChannel(ChannelHandler handler) { + this.handler = handler; + } + + @Override + public URL getUrl() { + return remoteUrl; + } + + @Override + public ChannelHandler getChannelHandler() { + return handler; + } + + @Override + public InetSocketAddress getLocalAddress() { + return localAddress; + } + + @Override + public void send(Object message) throws RemotingException { + if (remoteUrl.getParameter(ERROR_WHEN_SEND, Boolean.FALSE)) { + throw new RemotingException(localAddress, remoteAddress, "mock error"); + } else { + receivedObjects.add(message); + if (latch != null) { + latch.countDown(); + } + } + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + send(message); + } + + @Override + public void close() { + close(0); + } + + @Override + public void close(int timeout) { + isClosed = true; + } + + @Override + public void startClose() { + closing = true; + } + + @Override + public boolean isClosed() { + return isClosed; + } + + @Override + public InetSocketAddress getRemoteAddress() { + return remoteAddress; + } + + @Override + public boolean isConnected() { + return isClosed; + } + + @Override + public boolean hasAttribute(String key) { + return attributes.containsKey(key); + } + + @Override + public Object getAttribute(String key) { + return attributes.get(key); + } + + @Override + public void setAttribute(String key, Object value) { + attributes.put(key, value); + } + + @Override + public void removeAttribute(String key) { + attributes.remove(key); + } + + public List getReceivedObjects() { + return receivedObjects; + } +} diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml index 8cb14965440..ea28ef1c8b2 100644 --- a/dubbo-registry/dubbo-registry-api/pom.xml +++ b/dubbo-registry/dubbo-registry-api/pom.xml @@ -43,21 +43,6 @@ dubbo-cluster ${project.parent.version} - - org.apache.dubbo - dubbo-container-api - ${project.parent.version} - - - org.eclipse.jetty - jetty-server - - - org.eclipse.jetty - jetty-servlet - - - org.apache.dubbo diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java index c8dffc47fa6..4234afd6b53 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java @@ -17,7 +17,6 @@ package org.apache.dubbo.registry.client.metadata; import org.apache.dubbo.common.URL; -import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.ServiceInstanceCustomizer; @@ -44,7 +43,6 @@ public void customize(ServiceInstance serviceInstance) { writableMetadataService.getExportedURLs() .stream() .map(URL::valueOf) - .filter(url -> !MetadataService.class.getName().equals(url.getServiceInterface())) .forEach(url -> { // TODO, same protocol listen on different ports will override with each other. protocols.put(url.getProtocol(), url.getPort()); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java index 8b8a5b786e1..d658e3c87dc 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java @@ -24,7 +24,6 @@ import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.registry.client.ServiceInstance; import org.apache.dubbo.registry.client.ServiceInstanceCustomizer; -import org.apache.dubbo.registry.client.metadata.store.InMemoryWritableMetadataService; import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.HashMap; @@ -40,13 +39,11 @@ public class ServiceInstanceMetadataCustomizer implements ServiceInstanceCustomi @Override public void customize(ServiceInstance serviceInstance) { - Map params = new HashMap<>(); ExtensionLoader loader = ExtensionLoader.getExtensionLoader(MetadataParamsFilter.class); Set paramsFilters = loader.getSupportedExtensionInstances(); - InMemoryWritableMetadataService localMetadataService - = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(); + WritableMetadataService localMetadataService = WritableMetadataService.getDefaultExtension(); // pick the first interface metadata available. // FIXME, check the same key in different urls has the same value MetadataInfo metadataInfo = localMetadataService.getMetadataInfos().values().iterator().next(); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java index 40a8cfd84f5..f3aad018eed 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java @@ -244,7 +244,7 @@ public AtomicBoolean invokersChanged() { private synchronized void compareAddresses(ClusterInvoker serviceDiscoveryInvoker, ClusterInvoker invoker) { this.invokersChanged.set(true); if (logger.isDebugEnabled()) { - logger.info(invoker.getDirectory().getAllInvokers() == null ? "null" : invoker.getDirectory().getAllInvokers().size() + ""); + logger.debug(invoker.getDirectory().getAllInvokers() == null ? "null" : invoker.getDirectory().getAllInvokers().size() + ""); } Set detectors = ExtensionLoader.getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java index 62f9f7ef342..bc6287cdba5 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java @@ -37,7 +37,7 @@ */ public class InterfaceCompatibleRegistryProtocol extends RegistryProtocol { - private final static Logger logger = LoggerFactory.getLogger(InterfaceCompatibleRegistryProtocol.class); + private static final Logger logger = LoggerFactory.getLogger(InterfaceCompatibleRegistryProtocol.class); @Override protected URL getRegistryUrl(Invoker originInvoker) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java index 44a938e34e1..6e2ab5a338c 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java @@ -39,7 +39,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -127,7 +126,7 @@ public synchronized void notify(List urls) { List supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null); if (supportedListeners != null && !supportedListeners.isEmpty()) { for (AddressListener addressListener : supportedListeners) { - providerURLs = addressListener.notify(providerURLs, getConsumerUrl(),this); + providerURLs = addressListener.notify(providerURLs, getConsumerUrl(), this); } } refreshOverrideAndInvoker(providerURLs); @@ -174,7 +173,6 @@ private void refreshInvoker(List invokerUrls) { routerChain.setInvokers(this.invokers); destroyAllInvokers(); // Close all invokers } else { - this.forbidden = false; // Allow to access Map> oldUrlInvokerMap = this.urlInvokerMap; // local reference if (invokerUrls == Collections.emptyList()) { invokerUrls = new ArrayList<>(); @@ -188,6 +186,7 @@ private void refreshInvoker(List invokerUrls) { if (invokerUrls.isEmpty()) { return; } + this.forbidden = false; // Allow to access Map> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map /** @@ -211,11 +210,9 @@ private void refreshInvoker(List invokerUrls) { this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers; this.urlInvokerMap = newUrlInvokerMap; - try { - destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker - } catch (Exception e) { - logger.warn("destroyUnusedInvokers error. ", e); - } + // Close the unused Invoker + destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); + } // notify invokers refreshed @@ -224,23 +221,18 @@ private void refreshInvoker(List invokerUrls) { private List> toMergeInvokerList(List> invokers) { List> mergedInvokers = new ArrayList<>(); - Map>> groupMap = new HashMap<>(); - for (Invoker invoker : invokers) { - String group = invoker.getUrl().getParameter(GROUP_KEY, ""); - groupMap.computeIfAbsent(group, k -> new ArrayList<>()); - groupMap.get(group).add(invoker); - } + // group by invoker#url#group + Map>> groupMap = + invokers.stream().collect(Collectors.groupingBy(x -> x.getUrl().getParameter(GROUP_KEY, ""))); - if (groupMap.size() == 1) { - mergedInvokers.addAll(groupMap.values().iterator().next()); - } else if (groupMap.size() > 1) { + if (groupMap.size() > 1) { for (List> groupList : groupMap.values()) { StaticDirectory staticDirectory = new StaticDirectory<>(groupList); staticDirectory.buildRouterChain(); mergedInvokers.add(CLUSTER.join(staticDirectory)); } } else { - mergedInvokers = invokers; + mergedInvokers.addAll(invokers); } return mergedInvokers; } @@ -441,22 +433,10 @@ private void destroyUnusedInvokers(Map> oldUrlInvokerMap, Map deleted = null; if (oldUrlInvokerMap != null) { - for (Map.Entry> entry : oldUrlInvokerMap.entrySet()) { - if (!newUrlInvokerMap.containsKey(entry.getKey())) { - if (deleted == null) { - deleted = new ArrayList<>(); - } - deleted.add(entry.getKey()); - } - } - } - - if (deleted != null) { - for (URL url : deleted) { - if (url != null) { - Invoker invoker = oldUrlInvokerMap.get(url); + for (URL key : oldUrlInvokerMap.keySet()) { + if (null != key && !newUrlInvokerMap.containsKey(key)) { + Invoker invoker = oldUrlInvokerMap.get(key); if (invoker != null) { try { invoker.destroy(); @@ -479,7 +459,7 @@ public boolean isAvailable() { } Map> localUrlInvokerMap = urlInvokerMap; try { - if (CollectionUtils.isNotEmptyMap(localUrlInvokerMap) + if (!forbidden && CollectionUtils.isNotEmptyMap(localUrlInvokerMap) && localUrlInvokerMap.values().stream().anyMatch(Invoker::isAvailable)) { return true; } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java index 7c7de92a596..6d7f476e522 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java @@ -132,10 +132,10 @@ public class RegistryProtocol implements Protocol { APPLICATION_KEY, VERSION_KEY, GROUP_KEY, DUBBO_VERSION_KEY, RELEASE_KEY }; - private final static String REGISTRY_PROTOCOL_LISTENER_KEY = "registry.protocol.listener"; - private final static int DEFAULT_PORT = 9090; + private static final String REGISTRY_PROTOCOL_LISTENER_KEY = "registry.protocol.listener"; + private static final int DEFAULT_PORT = 9090; - private final static Logger LOGGER = LoggerFactory.getLogger(RegistryProtocol.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RegistryProtocol.class); private final Map overrideListeners = new ConcurrentHashMap<>(); private final Map serviceConfigurationListeners = new ConcurrentHashMap<>(); private final ProviderConfigurationListener providerConfigurationListener = new ProviderConfigurationListener(); diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdRegistry.java b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdRegistry.java index 26089ca1ccd..ef7ee630293 100644 --- a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdRegistry.java +++ b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdRegistry.java @@ -58,9 +58,9 @@ */ public class EtcdRegistry extends FailbackRegistry { - private final static int DEFAULT_ETCD_PORT = 2379; + private static final int DEFAULT_ETCD_PORT = 2379; - private final static String DEFAULT_ROOT = "dubbo"; + private static final String DEFAULT_ROOT = "dubbo"; private final String root; 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 c517ee6ce18..45f82cc5959 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 @@ -52,7 +52,7 @@ */ public class EtcdServiceDiscovery extends AbstractServiceDiscovery implements EventListener { - private final static Logger logger = LoggerFactory.getLogger(EtcdServiceDiscovery.class); + private static final Logger logger = LoggerFactory.getLogger(EtcdServiceDiscovery.class); private final String root = "/services"; diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java index 2b751c23f13..8ae4488aa5a 100644 --- a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java +++ b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java @@ -43,7 +43,7 @@ */ public class MultipleRegistry extends AbstractRegistry { - private final static Logger LOGGER = LoggerFactory.getLogger(MultipleRegistry.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MultipleRegistry.class); public static final String REGISTRY_FOR_SERVICE = "service-registry"; public static final String REGISTRY_FOR_REFERENCE = "reference-registry"; diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistryServiceDiscovery.java b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistryServiceDiscovery.java index da6d11181e1..5c04a8907b8 100644 --- a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistryServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistryServiceDiscovery.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.DefaultPage; import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.event.ConditionalEventListener; @@ -98,11 +99,17 @@ public void addServiceInstancesChangedListener(ServiceInstancesChangedListener l @Override public Page getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException { - List serviceInstanceList = new ArrayList<>(); for (ServiceDiscovery serviceDiscovery : serviceDiscoveries.values()) { Page serviceInstancePage = serviceDiscovery.getInstances(serviceName, offset, pageSize, healthyOnly); - serviceInstanceList.addAll(serviceInstancePage.getData()); + if (CollectionUtils.isNotEmpty(serviceInstancePage.getData())) { + // remove duplicate instance + for (ServiceInstance instance : serviceInstancePage.getData()) { + if (!serviceInstanceList.contains(instance)) { + serviceInstanceList.add(instance); + } + } + } } return new DefaultPage<>(offset, pageSize, serviceInstanceList, serviceInstanceList.size()); @@ -117,6 +124,11 @@ public Set getServices() { return services; } + @Override + public ServiceInstance getLocalInstance() { + return serviceInstance; + } + protected static class MultiServiceInstancesChangedListener implements ConditionalEventListener { private final ServiceInstancesChangedListener sourceListener; private final Map singleListenerMap = new ConcurrentHashMap<>(); @@ -134,15 +146,16 @@ public boolean accept(ServiceInstancesChangedEvent event) { public void onEvent(ServiceInstancesChangedEvent event) { List serviceInstances = new ArrayList<>(); for (SingleServiceInstancesChangedListener singleListener : singleListenerMap.values()) { - if (null != singleListener.event && null != singleListener.event.getServiceInstances()) { - for (ServiceInstance serviceInstance : singleListener.event.getServiceInstances()) { + ServiceInstancesChangedEvent source = singleListener.event; + if (source != null && source.getServiceInstances() != null) { + for (ServiceInstance serviceInstance : source.getServiceInstances()) { + // remove duplicate instance if (!serviceInstances.contains(serviceInstance)) { serviceInstances.add(serviceInstance); } } } } - sourceListener.onEvent(new ServiceInstancesChangedEvent(event.getServiceName(), serviceInstances)); } diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java index d93d8c3ed8f..a235013187e 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java @@ -49,6 +49,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import java.util.Collections; import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; @@ -64,6 +65,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; import static org.apache.dubbo.registry.Constants.ADMIN_PROTOCOL; +import static org.apache.dubbo.registry.nacos.NacosServiceName.NAME_SEPARATOR; import static org.apache.dubbo.registry.nacos.NacosServiceName.valueOf; /** @@ -286,19 +288,29 @@ private Set getServiceNames0(URL url) { private Set filterServiceNames(NacosServiceName serviceName) { Set serviceNames = new LinkedHashSet<>(); - execute(namingService -> { + execute(namingService -> serviceNames.addAll(namingService.getServicesOfServer(1, Integer.MAX_VALUE, + getUrl().getParameter(GROUP_KEY, Constants.DEFAULT_GROUP)).getData() + .stream() + .filter(this::isConformRules) + .map(NacosServiceName::new) + .filter(serviceName::isCompatible) + .map(NacosServiceName::toString) + .collect(Collectors.toList()))); - serviceNames.addAll(namingService.getServicesOfServer(1, Integer.MAX_VALUE, - getUrl().getParameter(GROUP_KEY, Constants.DEFAULT_GROUP)).getData() - .stream() - .map(NacosServiceName::new) - .filter(serviceName::isCompatible) - .map(NacosServiceName::toString) - .collect(Collectors.toList())); + return serviceNames; + } - }); + /** + * Verify whether it is a dubbo service + * + * @param serviceName + * @return + * @since 2.7.12 + */ + private boolean isConformRules(String serviceName) { + + return serviceName.split(NAME_SEPARATOR, -1).length == 4; - return serviceNames; } /** @@ -490,10 +502,9 @@ private void subscribeEventListener(String serviceName, final URL url, final Not if (isServiceNamesWithCompatibleMode(url)) { - /** - * Get all instances with corresponding serviceNames to avoid instance overwrite and but with empty instance mentioned - * in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899 - */ + + // Get all instances with corresponding serviceNames to avoid instance overwrite and but with empty instance mentioned + // in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899 NacosInstanceManageUtil.initOrRefreshServiceInstanceList(serviceName, instances); instances = NacosInstanceManageUtil.getAllCorrespondingServiceInstanceList(serviceName); } @@ -531,7 +542,7 @@ private void notifySubscriber(URL url, NotifyListener listener, Collection getCategories(URL url) { return ANY_VALUE.equals(url.getServiceInterface()) ? - ALL_SUPPORTED_CATEGORIES : Arrays.asList(DEFAULT_CATEGORY); + ALL_SUPPORTED_CATEGORIES : Collections.singletonList(DEFAULT_CATEGORY); } private URL buildURL(Instance instance) { diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceName.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceName.java index 27c45eea29a..e9853e12e5c 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceName.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceName.java @@ -103,7 +103,8 @@ public boolean isConcrete() { public boolean isCompatible(NacosServiceName concreteServiceName) { - if (!concreteServiceName.isConcrete()) { // The argument must be the concrete NacosServiceName + // The argument must be the concrete NacosServiceName + if (!concreteServiceName.isConcrete()) { return false; } @@ -160,7 +161,7 @@ private boolean isWildcard(String value) { } private boolean isRange(String value) { - return value != null && value.indexOf(VALUE_SEPARATOR) > -1 && value.split(VALUE_SEPARATOR).length > 1; + return value != null && value.contains(VALUE_SEPARATOR) && value.split(VALUE_SEPARATOR).length > 1; } public String getCategory() { @@ -203,11 +204,10 @@ public String getValue() { } private String toValue() { - return new StringBuilder(category) - .append(NAME_SEPARATOR).append(serviceInterface) - .append(NAME_SEPARATOR).append(version) - .append(NAME_SEPARATOR).append(group) - .toString(); + return category + + NAME_SEPARATOR + serviceInterface + + NAME_SEPARATOR + version + + NAME_SEPARATOR + group; } @Override diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java new file mode 100644 index 00000000000..0087f293594 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java @@ -0,0 +1,327 @@ +/* + * 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.nacos; + + +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.api.naming.pojo.ListView; +import com.alibaba.nacos.client.naming.NacosNamingService; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.nacos.util.NacosNamingServiceUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + + +import java.util.HashMap; +import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; + +import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.doNothing; + +public class NacosRegistryTest { + + + private NacosRegistryFactory nacosRegistryFactory; + + private NacosRegistry nacosRegistry; + + private static final String serviceInterface = "org.apache.dubbo.registry.nacos.NacosService"; + + private final URL serviceUrl = URL.valueOf("nacos://127.0.0.1:3333/" + serviceInterface + "?interface=" + + serviceInterface + "¬ify=false&methods=test1,test2&category=providers&version=1.0.0&group=default"); + + private URL registryUrl; + + + @BeforeEach + public void setUp() throws Exception { + + int nacosServerPort = NetUtils.getAvailablePort(); + + this.registryUrl = URL.valueOf("nacos://localhost:" + nacosServerPort); + + this.nacosRegistryFactory = new NacosRegistryFactory(); + + this.nacosRegistry = (NacosRegistry) nacosRegistryFactory.createRegistry(registryUrl); + + } + + + @AfterEach + public void tearDown() throws Exception { + } + + @Test + public void testRegister() { + NamingService namingService = mock(NacosNamingService.class); + try { + + String serviceName = "providers:org.apache.dubbo.registry.nacos.NacosService:1.0.0:default"; + String category = this.serviceUrl.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + URL newUrl = this.serviceUrl.addParameter(CATEGORY_KEY, category); + newUrl = newUrl.addParameter(PROTOCOL_KEY, this.serviceUrl.getProtocol()); + newUrl = newUrl.addParameter(PATH_KEY, this.serviceUrl.getPath()); + newUrl = newUrl.addParameters(NacosNamingServiceUtils.getNacosPreservedParam(this.serviceUrl)); + String ip = newUrl.getHost(); + int port = newUrl.getPort(); + Instance instance = new Instance(); + instance.setIp(ip); + instance.setPort(port); + instance.setMetadata(new HashMap<>(newUrl.getParameters())); + doNothing().when(namingService).registerInstance(serviceName, + Constants.DEFAULT_GROUP, instance); + } catch (NacosException e) { + // ignore + } + + NacosNamingServiceWrapper nacosNamingServiceWrapper = new + NacosNamingServiceWrapper(namingService); + nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); + + Set registered; + for (int i = 0; i < 2; i++) { + nacosRegistry.register(serviceUrl); + registered = nacosRegistry.getRegistered(); + assertThat(registered.contains(serviceUrl), is(true)); + } + + registered = nacosRegistry.getRegistered(); + assertThat(registered.size(), is(1)); + + } + + @Test + public void testUnRegister() { + NamingService namingService = mock(NacosNamingService.class); + + try { + + String serviceName = "providers:org.apache.dubbo.registry.nacos.NacosService:1.0.0:default"; + String category = this.serviceUrl.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + URL newUrl = this.serviceUrl.addParameter(CATEGORY_KEY, category); + newUrl = newUrl.addParameter(PROTOCOL_KEY, this.serviceUrl.getProtocol()); + newUrl = newUrl.addParameter(PATH_KEY, this.serviceUrl.getPath()); + newUrl = newUrl.addParameters(NacosNamingServiceUtils.getNacosPreservedParam(this.serviceUrl)); + String ip = newUrl.getHost(); + int port = newUrl.getPort(); + Instance instance = new Instance(); + instance.setIp(ip); + instance.setPort(port); + instance.setMetadata(new HashMap<>(newUrl.getParameters())); + doNothing().when(namingService).registerInstance(serviceName, + Constants.DEFAULT_GROUP, instance); + + doNothing().when(namingService).deregisterInstance(serviceName, + Constants.DEFAULT_GROUP, ip, port); + } catch (NacosException e) { + // ignore + } + + NacosNamingServiceWrapper nacosNamingServiceWrapper = new + NacosNamingServiceWrapper(namingService); + nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); + + nacosRegistry.register(serviceUrl); + Set registered = nacosRegistry.getRegistered(); + + assertThat(registered.contains(serviceUrl), is(true)); + assertThat(registered.size(), is(1)); + + nacosRegistry.unregister(serviceUrl); + assertThat(registered.contains(serviceUrl), is(false)); + assertThat(registered.size(), is(0)); + + } + + @Test + public void testSubscribe() { + NamingService namingService = mock(NacosNamingService.class); + + try { + + String serviceName = "providers:org.apache.dubbo.registry.nacos.NacosService:1.0.0:default"; + String category = this.serviceUrl.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + URL newUrl = this.serviceUrl.addParameter(CATEGORY_KEY, category); + newUrl = newUrl.addParameter(PROTOCOL_KEY, this.serviceUrl.getProtocol()); + newUrl = newUrl.addParameter(PATH_KEY, this.serviceUrl.getPath()); + newUrl = newUrl.addParameters(NacosNamingServiceUtils.getNacosPreservedParam(this.serviceUrl)); + String ip = newUrl.getHost(); + int port = newUrl.getPort(); + Instance instance = new Instance(); + instance.setIp(ip); + instance.setPort(port); + instance.setMetadata(new HashMap<>(newUrl.getParameters())); + + List instances = new ArrayList<>(); + instances.add(instance); + when(namingService.getAllInstances(serviceName, + this.registryUrl.getParameter(GROUP_KEY, Constants.DEFAULT_GROUP))).thenReturn(instances); + } catch (NacosException e) { + // ignore + } + + NacosNamingServiceWrapper nacosNamingServiceWrapper = new + NacosNamingServiceWrapper(namingService); + nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); + + NotifyListener listener = mock(NotifyListener.class); + nacosRegistry.subscribe(serviceUrl, listener); + + Map> subscribed = nacosRegistry.getSubscribed(); + assertThat(subscribed.size(), is(1)); + assertThat(subscribed.get(serviceUrl).size(), is(1)); + + } + + @Test + public void testUnSubscribe() { + NamingService namingService = mock(NacosNamingService.class); + + try { + + String serviceName = "providers:org.apache.dubbo.registry.nacos.NacosService:1.0.0:default"; + String category = this.serviceUrl.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + URL newUrl = this.serviceUrl.addParameter(CATEGORY_KEY, category); + newUrl = newUrl.addParameter(PROTOCOL_KEY, this.serviceUrl.getProtocol()); + newUrl = newUrl.addParameter(PATH_KEY, this.serviceUrl.getPath()); + newUrl = newUrl.addParameters(NacosNamingServiceUtils.getNacosPreservedParam(this.serviceUrl)); + String ip = newUrl.getHost(); + int port = newUrl.getPort(); + Instance instance = new Instance(); + instance.setIp(ip); + instance.setPort(port); + instance.setMetadata(new HashMap<>(newUrl.getParameters())); + + List instances = new ArrayList<>(); + instances.add(instance); + when(namingService.getAllInstances(serviceName, + this.registryUrl.getParameter(GROUP_KEY, Constants.DEFAULT_GROUP))).thenReturn(instances); + + } catch (NacosException e) { + // ignore + } + + NacosNamingServiceWrapper nacosNamingServiceWrapper = new + NacosNamingServiceWrapper(namingService); + nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); + + NotifyListener listener = mock(NotifyListener.class); + nacosRegistry.subscribe(serviceUrl, listener); + + Map> subscribed = nacosRegistry.getSubscribed(); + assertThat(subscribed.size(), is(1)); + assertThat(subscribed.get(serviceUrl).size(), is(1)); + + nacosRegistry.unsubscribe(serviceUrl, listener); + subscribed = nacosRegistry.getSubscribed(); + assertThat(subscribed.size(), is(1)); + assertThat(subscribed.get(serviceUrl).size(), is(0)); + } + + + @Test + public void testIsConformRules() { + NamingService namingService = mock(NacosNamingService.class); + URL serviceUrlWithoutCategory = URL.valueOf("nacos://127.0.0.1:3333/" + serviceInterface + "?interface=" + + serviceInterface + "¬ify=false&methods=test1,test2&version=1.0.0&group=default"); + try { + String serviceName = "providers:org.apache.dubbo.registry.nacos.NacosService:1.0.0:default"; + String category = this.serviceUrl.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + URL newUrl = this.serviceUrl.addParameter(CATEGORY_KEY, category); + newUrl = newUrl.addParameter(PROTOCOL_KEY, this.serviceUrl.getProtocol()); + newUrl = newUrl.addParameter(PATH_KEY, this.serviceUrl.getPath()); + newUrl = newUrl.addParameters(NacosNamingServiceUtils.getNacosPreservedParam(this.serviceUrl)); + String ip = newUrl.getHost(); + int port = newUrl.getPort(); + Instance instance = new Instance(); + instance.setIp(ip); + instance.setPort(port); + instance.setMetadata(new HashMap<>(newUrl.getParameters())); + + List instances = new ArrayList<>(); + instances.add(instance); + when(namingService.getAllInstances(serviceName, + this.registryUrl.getParameter(GROUP_KEY, Constants.DEFAULT_GROUP))).thenReturn(instances); + + String serviceNameWithoutVersion = "providers:org.apache.dubbo.registry.nacos.NacosService:default"; + String serviceName1 = "providers:org.apache.dubbo.registry.nacos.NacosService:1.0.0:default"; + List serviceNames = new ArrayList<>(); + serviceNames.add(serviceNameWithoutVersion); + serviceNames.add(serviceName1); + ListView result = new ListView<>(); + result.setData(serviceNames); + when(namingService.getServicesOfServer(1, Integer.MAX_VALUE, + registryUrl.getParameter(GROUP_KEY, Constants.DEFAULT_GROUP))).thenReturn(result); + } catch (NacosException e) { + // ignore + } + + NacosNamingServiceWrapper nacosNamingServiceWrapper = new + NacosNamingServiceWrapper(namingService); + nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); + + Set registered; + nacosRegistry.register(this.serviceUrl); + nacosRegistry.register(serviceUrlWithoutCategory); + registered = nacosRegistry.getRegistered(); + assertThat(registered.contains(serviceUrl), is(true)); + assertThat(registered.contains(serviceUrlWithoutCategory), is(true)); + assertThat(registered.size(), is(2)); + + + URL serviceUrlWithWildcard = URL.valueOf("nacos://127.0.0.1:3333/" + + serviceInterface + + "?interface=org.apache.dubbo.registry.nacos.NacosService" + + "¬ify=false&methods=test1,test2&category=providers&version=*&group=default"); + + URL serviceUrlWithOutWildcard = URL.valueOf("nacos://127.0.0.1:3333/" + + serviceInterface + + "?interface=org.apache.dubbo.registry.nacos.NacosService" + + "¬ify=false&methods=test1,test2&category=providers&version=1.0.0&group=default"); + + NotifyListener listener = mock(NotifyListener.class); + nacosRegistry.subscribe(serviceUrlWithWildcard, listener); + nacosRegistry.subscribe(serviceUrlWithOutWildcard, listener); + + Map> subscribed = nacosRegistry.getSubscribed(); + + assertThat(subscribed.size(), is(2)); + assertThat(subscribed.get(serviceUrlWithOutWildcard).size(), is(1)); + + assertThat(subscribed.size(), is(2)); + assertThat(subscribed.get(serviceUrlWithWildcard).size(), is(1)); + + + } +} diff --git a/dubbo-registry/dubbo-registry-redis/src/main/java/org/apache/dubbo/registry/redis/RedisRegistry.java b/dubbo-registry/dubbo-registry-redis/src/main/java/org/apache/dubbo/registry/redis/RedisRegistry.java index c569ed487b7..893b09486a8 100644 --- a/dubbo-registry/dubbo-registry-redis/src/main/java/org/apache/dubbo/registry/redis/RedisRegistry.java +++ b/dubbo-registry/dubbo-registry-redis/src/main/java/org/apache/dubbo/registry/redis/RedisRegistry.java @@ -75,7 +75,7 @@ */ public class RedisRegistry extends FailbackRegistry { - private final static String DEFAULT_ROOT = "dubbo"; + private static final String DEFAULT_ROOT = "dubbo"; private final ScheduledExecutorService expireExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboRegistryExpireTimer", true)); 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 b3bf8205be9..9686eff3969 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 @@ -59,7 +59,7 @@ */ public class ZookeeperRegistry extends FailbackRegistry { - private final static String DEFAULT_ROOT = "dubbo"; + private static final String DEFAULT_ROOT = "dubbo"; private final String root; 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 26f454c81f2..27142b02126 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 @@ -16,20 +16,21 @@ */ package org.apache.dubbo.registry.zookeeper; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.CuratorWatcher; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.function.ThrowableConsumer; 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.CollectionUtils; import org.apache.dubbo.common.utils.DefaultPage; import org.apache.dubbo.common.utils.Page; import org.apache.dubbo.registry.client.AbstractServiceDiscovery; 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.curator.framework.CuratorFramework; -import org.apache.curator.framework.api.CuratorWatcher; import org.apache.zookeeper.KeeperException; import java.util.Iterator; @@ -81,6 +82,7 @@ public URL getUrl() { return registryURL; } + @Override public void destroy() throws Exception { serviceDiscovery.close(); } @@ -99,6 +101,7 @@ public void doUpdate(ServiceInstance serviceInstance) { }); } + @Override public void unregister(ServiceInstance serviceInstance) throws RuntimeException { doInServiceRegistry(serviceDiscovery -> { serviceDiscovery.unregisterService(build(serviceInstance)); @@ -201,10 +204,18 @@ protected void registerServiceWatcher(String serviceName, ServiceInstancesChange throw new IllegalStateException("registerServiceWatcher create path=" + path + " fail.", e); } + CuratorWatcher prev = watcherCaches.get(path); CuratorWatcher watcher = watcherCaches.computeIfAbsent(path, key -> new ZookeeperServiceDiscoveryChangeWatcher(this, serviceName, listener)); try { - curatorFramework.getChildren().usingWatcher(watcher).forPath(path); + List addresses = curatorFramework.getChildren().usingWatcher(watcher).forPath(path); + // notify instance changed first time, + // in the multi-registry scenario, + // we need to merge pushed instances + if ((prev == null || watcher != prev) + && CollectionUtils.isNotEmpty(addresses)) { + listener.onEvent(new ServiceInstancesChangedEvent(serviceName, this.getInstances(serviceName))); + } } catch (KeeperException.NoNodeException e) { // ignored if (logger.isErrorEnabled()) { diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java index e01e863a73c..97684b84e70 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java @@ -60,7 +60,8 @@ public void process(WatchedEvent event) throws Exception { if (shouldKeepWatching()) { listener.onEvent(new ServiceInstancesChangedEvent(serviceName, zookeeperServiceDiscovery.getInstances(serviceName))); zookeeperServiceDiscovery.registerServiceWatcher(serviceName, listener); - zookeeperServiceDiscovery.dispatchServiceInstancesChangedEvent(serviceName); + // only the current registry will be queried, which may be pushed empty. + // zookeeperServiceDiscovery.dispatchServiceInstancesChangedEvent(serviceName); } } } diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactoryTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactoryTest.java new file mode 100644 index 00000000000..bae8ac7b38f --- /dev/null +++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactoryTest.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.registry.zookeeper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.client.ServiceDiscovery; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ZookeeperServiceDiscoveryFactoryTest { + + @Test + public void testCreateZookeeperServiceDiscovery() { + final URL url = URL.valueOf("test://test:80"); + final ZookeeperServiceDiscoveryFactory factory = new ZookeeperServiceDiscoveryFactory(); + ServiceDiscovery discovery = factory.createDiscovery(url); + + Assertions.assertTrue(discovery instanceof ZookeeperServiceDiscovery); + } +} 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 f04a5b56e6e..3db2de465cd 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,23 +18,30 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.NetUtils; +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; import org.apache.curator.test.TestingServer; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.internal.util.collections.Sets; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; import static java.util.Arrays.asList; import static org.apache.dubbo.common.utils.NetUtils.getAvailablePort; 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; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -105,102 +112,103 @@ private DefaultServiceInstance createServiceInstance(String serviceName, String return new DefaultServiceInstance(generateId(host, port), serviceName, host, port); } -// @Test -// public void testGetInstances() throws InterruptedException { -// -// List instances = asList( -// createServiceInstance(SERVICE_NAME, LOCALHOST, 8080), -// createServiceInstance(SERVICE_NAME, LOCALHOST, 8081), -// createServiceInstance(SERVICE_NAME, LOCALHOST, 8082) -// ); -// -// instances.forEach(discovery::register); -// -// List serviceInstances = new LinkedList<>(); -// -// CountDownLatch latch = new CountDownLatch(1); -// -// // Add Listener -// 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)); -// discovery.update(createServiceInstance(SERVICE_NAME, LOCALHOST, 8082)); -// -// latch.await(); -// -// assertFalse(serviceInstances.isEmpty()); -// -// // offset starts 0 -// int offset = 0; -// // requestSize > total elements -// int requestSize = 5; -// -// Page page = discovery.getInstances(SERVICE_NAME, offset, requestSize); -// assertEquals(0, page.getOffset()); -// assertEquals(5, page.getPageSize()); -// assertEquals(3, page.getTotalSize()); -// assertEquals(3, page.getData().size()); -// assertTrue(page.hasData()); -// -// for (ServiceInstance instance : page.getData()) { -// assertTrue(instances.contains(instance)); -// } -// -// // requestSize < total elements -// requestSize = 2; -// -// page = discovery.getInstances(SERVICE_NAME, offset, requestSize); -// assertEquals(0, page.getOffset()); -// assertEquals(2, page.getPageSize()); -// assertEquals(3, page.getTotalSize()); -// assertEquals(2, page.getData().size()); -// assertTrue(page.hasData()); -// -// for (ServiceInstance instance : page.getData()) { -// assertTrue(instances.contains(instance)); -// } -// -// offset = 1; -// page = discovery.getInstances(SERVICE_NAME, offset, requestSize); -// assertEquals(1, page.getOffset()); -// assertEquals(2, page.getPageSize()); -// assertEquals(3, page.getTotalSize()); -// assertEquals(2, page.getData().size()); -// assertTrue(page.hasData()); -// -// for (ServiceInstance instance : page.getData()) { -// assertTrue(instances.contains(instance)); -// } -// -// offset = 2; -// page = discovery.getInstances(SERVICE_NAME, offset, requestSize); -// assertEquals(2, page.getOffset()); -// assertEquals(2, page.getPageSize()); -// assertEquals(3, page.getTotalSize()); -// assertEquals(1, page.getData().size()); -// assertTrue(page.hasData()); -// -// offset = 3; -// page = discovery.getInstances(SERVICE_NAME, offset, requestSize); -// assertEquals(3, page.getOffset()); -// assertEquals(2, page.getPageSize()); -// assertEquals(3, page.getTotalSize()); -// assertEquals(0, page.getData().size()); -// assertFalse(page.hasData()); -// -// offset = 5; -// page = discovery.getInstances(SERVICE_NAME, offset, requestSize); -// assertEquals(5, page.getOffset()); -// assertEquals(2, page.getPageSize()); -// assertEquals(3, page.getTotalSize()); -// assertEquals(0, page.getData().size()); -// assertFalse(page.hasData()); -// -// } + @Test + public void testGetInstances() throws InterruptedException { + + List instances = asList( + createServiceInstance(SERVICE_NAME, LOCALHOST, 8080), + createServiceInstance(SERVICE_NAME, LOCALHOST, 8081), + createServiceInstance(SERVICE_NAME, LOCALHOST, 8082) + ); + + instances.forEach(discovery::register); + + List serviceInstances = new LinkedList<>(); + + CountDownLatch latch = new CountDownLatch(1); + + // Add Listener + discovery.addServiceInstancesChangedListener( + new ServiceInstancesChangedListener(Sets.newSet(SERVICE_NAME), discovery) { + @Override + public void onEvent(ServiceInstancesChangedEvent event) { + serviceInstances.addAll(event.getServiceInstances()); + latch.countDown(); + } + }); + + discovery.register(createServiceInstance(SERVICE_NAME, LOCALHOST, 8082)); + discovery.update(createServiceInstance(SERVICE_NAME, LOCALHOST, 8082)); + + latch.await(); + + assertFalse(serviceInstances.isEmpty()); + + // offset starts 0 + int offset = 0; + // requestSize > total elements + int requestSize = 5; + + Page page = discovery.getInstances(SERVICE_NAME, offset, requestSize); + assertEquals(0, page.getOffset()); + assertEquals(5, page.getPageSize()); + assertEquals(3, page.getTotalSize()); + assertEquals(3, page.getData().size()); + assertTrue(page.hasData()); + + for (ServiceInstance instance : page.getData()) { + assertTrue(instances.contains(instance)); + } + + // requestSize < total elements + requestSize = 2; + + page = discovery.getInstances(SERVICE_NAME, offset, requestSize); + assertEquals(0, page.getOffset()); + assertEquals(2, page.getPageSize()); + assertEquals(3, page.getTotalSize()); + assertEquals(2, page.getData().size()); + assertTrue(page.hasData()); + + for (ServiceInstance instance : page.getData()) { + assertTrue(instances.contains(instance)); + } + + offset = 1; + page = discovery.getInstances(SERVICE_NAME, offset, requestSize); + assertEquals(1, page.getOffset()); + assertEquals(2, page.getPageSize()); + assertEquals(3, page.getTotalSize()); + assertEquals(2, page.getData().size()); + assertTrue(page.hasData()); + + for (ServiceInstance instance : page.getData()) { + assertTrue(instances.contains(instance)); + } + + offset = 2; + page = discovery.getInstances(SERVICE_NAME, offset, requestSize); + assertEquals(2, page.getOffset()); + assertEquals(2, page.getPageSize()); + assertEquals(3, page.getTotalSize()); + assertEquals(1, page.getData().size()); + assertTrue(page.hasData()); + + offset = 3; + page = discovery.getInstances(SERVICE_NAME, offset, requestSize); + assertEquals(3, page.getOffset()); + assertEquals(2, page.getPageSize()); + assertEquals(3, page.getTotalSize()); + assertEquals(0, page.getData().size()); + assertFalse(page.hasData()); + + offset = 5; + page = discovery.getInstances(SERVICE_NAME, offset, requestSize); + assertEquals(5, page.getOffset()); + assertEquals(2, page.getPageSize()); + assertEquals(3, page.getTotalSize()); + assertEquals(0, page.getData().size()); + assertFalse(page.hasData()); + + } } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java index 7fc6afb825f..378b5f1206f 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java @@ -29,6 +29,8 @@ @Help(parameter = "[lines]", summary = "Clear screen.", detail = "Clear screen.") public class ClearTelnetHandler implements TelnetHandler { + private static final int MAX_LINES = 1000; + @Override public String telnet(Channel channel, String message) { int lines = 100; @@ -36,7 +38,7 @@ public String telnet(Channel channel, String message) { if (!StringUtils.isInteger(message)) { return "Illegal lines " + message + ", must be integer."; } - lines = Integer.parseInt(message); + lines = Math.min(MAX_LINES,Integer.parseInt(message)); } StringBuilder buf = new StringBuilder(); for (int i = 0; i < lines; i++) { diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java index b22cd1ac667..23390eb7328 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; /** * HelpTelnetHandler @@ -36,38 +38,50 @@ public class HelpTelnetHandler implements TelnetHandler { private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(TelnetHandler.class); + private static final String MAIN_HELP = "mainHelp"; + + private static Map processedTable = new WeakHashMap<>(); + @Override public String telnet(Channel channel, String message) { if (message.length() > 0) { - if (!extensionLoader.hasExtension(message)) { - return "No such command " + message; - } - TelnetHandler handler = extensionLoader.getExtension(message); - Help help = handler.getClass().getAnnotation(Help.class); - StringBuilder buf = new StringBuilder(); - buf.append("Command:\r\n "); - buf.append(message + " " + help.parameter().replace("\r\n", " ").replace("\n", " ")); - buf.append("\r\nSummary:\r\n "); - buf.append(help.summary().replace("\r\n", " ").replace("\n", " ")); - buf.append("\r\nDetail:\r\n "); - buf.append(help.detail().replace("\r\n", " \r\n").replace("\n", " \n")); - return buf.toString(); + return processedTable.computeIfAbsent(message, commandName -> generateForOneCommand(commandName)); } else { - List> table = new ArrayList>(); - List handlers = extensionLoader.getActivateExtension(channel.getUrl(), "telnet"); - if (CollectionUtils.isNotEmpty(handlers)) { - for (TelnetHandler handler : handlers) { - Help help = handler.getClass().getAnnotation(Help.class); - List row = new ArrayList(); - String parameter = " " + extensionLoader.getExtensionName(handler) + " " + (help != null ? help.parameter().replace("\r\n", " ").replace("\n", " ") : ""); - row.add(parameter.length() > 55 ? parameter.substring(0, 55) + "..." : parameter); - String summary = help != null ? help.summary().replace("\r\n", " ").replace("\n", " ") : ""; - row.add(summary.length() > 55 ? summary.substring(0, 55) + "..." : summary); - table.add(row); - } + return processedTable.computeIfAbsent(MAIN_HELP, commandName -> generateForAllCommand(channel)); + } + } + + private String generateForOneCommand(String message) { + if (!extensionLoader.hasExtension(message)) { + return "No such command " + message; + } + TelnetHandler handler = extensionLoader.getExtension(message); + Help help = handler.getClass().getAnnotation(Help.class); + StringBuilder buf = new StringBuilder(); + buf.append("Command:\r\n "); + buf.append(message + " " + help.parameter().replace("\r\n", " ").replace("\n", " ")); + buf.append("\r\nSummary:\r\n "); + buf.append(help.summary().replace("\r\n", " ").replace("\n", " ")); + buf.append("\r\nDetail:\r\n "); + buf.append(help.detail().replace("\r\n", " \r\n").replace("\n", " \n")); + return buf.toString(); + } + + private String generateForAllCommand(Channel channel) { + List> table = new ArrayList>(); + List handlers = extensionLoader.getActivateExtension(channel.getUrl(), "telnet"); + if (CollectionUtils.isNotEmpty(handlers)) { + for (TelnetHandler handler : handlers) { + Help help = handler.getClass().getAnnotation(Help.class); + List row = new ArrayList(); + String parameter = " " + extensionLoader.getExtensionName(handler) + " " + (help != null ? help.parameter().replace("\r\n", " ").replace("\n", " ") : ""); + row.add(parameter.length() > 55 ? parameter.substring(0, 55) + "..." : parameter); + String summary = help != null ? help.summary().replace("\r\n", " ").replace("\n", " ") : ""; + row.add(summary.length() > 55 ? summary.substring(0, 55) + "..." : summary); + table.add(row); } - return "Please input \"help [command]\" show detail.\r\n" + TelnetUtils.toList(table); } + return "Please input \"help [command]\" show detail.\r\n" + TelnetUtils.toList(table); } } diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ThreadNameTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ThreadNameTest.java index 77d833d6763..bdb70d0335c 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ThreadNameTest.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ThreadNameTest.java @@ -106,6 +106,9 @@ private void checkThreadName() { if (!success) { success = Thread.currentThread().getName().matches(message); } + if (success) { + latch.countDown(); + } } private void output(String method) { @@ -129,14 +132,12 @@ public void disconnected(Channel channel) throws RemotingException { public void sent(Channel channel, Object message) throws RemotingException { output("sent"); checkThreadName(); - latch.countDown(); } @Override public void received(Channel channel, Object message) throws RemotingException { output("received"); checkThreadName(); - latch.countDown(); } @Override diff --git a/dubbo-remoting/dubbo-remoting-netty4/pom.xml b/dubbo-remoting/dubbo-remoting-netty4/pom.xml index 99dd1449963..41da6bc4f68 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/pom.xml +++ b/dubbo-remoting/dubbo-remoting-netty4/pom.xml @@ -50,5 +50,10 @@ ${project.parent.version} test + + io.netty + netty-tcnative-boringssl-static + test + diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/SslContexts.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/SslContexts.java index 94feda64c9b..c4d3598168d 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/SslContexts.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/SslContexts.java @@ -57,6 +57,13 @@ public static SslContext buildServerSslContext(URL url) { sslClientContextBuilder.trustManager(sslConfig.getServerTrustCertCollectionPathStream()); sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE); } + if (sslConfig.getCiphers() != null) { + sslClientContextBuilder.ciphers(sslConfig.getCiphers()); + } + if (sslConfig.getProtocols() != null) { + sslClientContextBuilder.protocols(sslConfig.getProtocols()); + } + } catch (Exception e) { throw new IllegalArgumentException("Could not find certificate file or the certificate is invalid.", e); } @@ -87,6 +94,12 @@ public static SslContext buildClientSslContext(URL url) { builder.keyManager(clientCertChainFilePath, clientPrivateKeyFilePath); } } + if (sslConfig.getCiphers() != null) { + builder.ciphers(sslConfig.getCiphers()); + } + if (sslConfig.getProtocols() != null) { + builder.protocols(sslConfig.getProtocols()); + } } catch (Exception e) { throw new IllegalArgumentException("Could not find certificate file or find invalid certificate.", e); } diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java index 120d454cd0d..982218713ac 100755 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java @@ -29,7 +29,7 @@ */ public class RpcMessageHandler implements Replier { - private final static ServiceProvider DEFAULT_PROVIDER = new ServiceProvider() { + private static final ServiceProvider DEFAULT_PROVIDER = new ServiceProvider() { public Object getImplementation(String service) { String impl = service + "Impl"; try { diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/SslContextsTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/SslContextsTest.java new file mode 100644 index 00000000000..496fd664b5f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/SslContextsTest.java @@ -0,0 +1,83 @@ +/* + * 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.remoting.transport.netty4; + +import io.netty.handler.ssl.JdkSslContext; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.OpenSslContext; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.ReferenceCountedOpenSslContext; +import org.apache.dubbo.config.SslConfig; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +/** + * ssl contexts test + */ +public class SslContextsTest { + @Test + public void testSslContexts() throws NoSuchFieldException, IllegalAccessException { + //test openssl + testSslContextsItem(); + + MockedStatic openSslMockedStatic = Mockito.mockStatic(OpenSsl.class); + openSslMockedStatic.when(OpenSsl::isAvailable).thenReturn(false); + + //test jdk + testSslContextsItem(); + } + + protected void testSslContextsItem() throws NoSuchFieldException, IllegalAccessException { + String cipher = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + String protocol = "TLSv1.3"; + + ConfigManager globalConfigManager = ApplicationModel.getConfigManager(); + SslConfig sslConfig = new SslConfig(); + sslConfig.setCiphers(Arrays.asList(cipher)); + sslConfig.setProtocols(Arrays.asList(protocol)); + globalConfigManager.setSsl(sslConfig); + + SslContext sslContext = SslContexts.buildClientSslContext(null); + if(sslContext instanceof JdkSslContext){ + JdkSslContext jdkSslContext = (JdkSslContext) sslContext; + List cipherSuites = jdkSslContext.cipherSuites(); + Assertions.assertTrue(cipherSuites.size() == 1 && cipherSuites.get(0).equals(cipher)); + Field protocols = JdkSslContext.class.getDeclaredField("protocols"); + protocols.setAccessible(true); + String[] item = (String[])protocols.get(jdkSslContext); + Assertions.assertTrue(item.length == 1 && item[0].equals(protocol)); + } + else if(sslContext instanceof OpenSslContext){ + OpenSslContext openSslContext = (OpenSslContext) sslContext; + Assertions.assertTrue(openSslContext instanceof ReferenceCountedOpenSslContext); + List cipherSuites = openSslContext.cipherSuites(); + Assertions.assertTrue(cipherSuites.size() == 1 && cipherSuites.get(0).equals(cipher)); + Field protocols = ReferenceCountedOpenSslContext.class.getDeclaredField("protocols"); + protocols.setAccessible(true); + final String[] item = (String[]) protocols.get(openSslContext); + Assertions.assertTrue(item.length == 1 && item[0].equals(protocol)); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/TimeoutCountDown.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/TimeoutCountDown.java index 91b561d723f..e5d1f00c87f 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/TimeoutCountDown.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/TimeoutCountDown.java @@ -60,7 +60,7 @@ public long elapsedMillis() { if (isExpired()) { return timeoutInMillis + TimeUnit.MILLISECONDS.convert(System.nanoTime() - deadlineInNanos, TimeUnit.NANOSECONDS); } else { - return TimeUnit.MILLISECONDS.convert(deadlineInNanos - System.nanoTime(), TimeUnit.NANOSECONDS); + return timeoutInMillis - TimeUnit.MILLISECONDS.convert(deadlineInNanos - System.nanoTime(), TimeUnit.NANOSECONDS); } } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java index 2c451c6ff52..ea836e199d0 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java @@ -19,7 +19,6 @@ import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ConcurrentHashSet; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.NamedThreadFactory; import org.apache.dubbo.rpc.Filter; @@ -37,8 +36,9 @@ import java.util.Date; import java.util.Iterator; import java.util.Map; -import java.util.Set; +import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -67,6 +67,8 @@ public class AccessLogFilter implements Filter { private static final String LOG_KEY = "dubbo.accesslog"; + private static final String LINE_SEPARATOR = "line.separator"; + private static final int LOG_MAX_BUFFER = 5000; private static final long LOG_OUTPUT_INTERVAL = 5000; @@ -76,7 +78,7 @@ public class AccessLogFilter implements Filter { // It's safe to declare it as singleton since it runs on single thread only private static final DateFormat FILE_NAME_FORMATTER = new SimpleDateFormat(FILE_DATE_FORMAT); - private static final Map> LOG_ENTRIES = new ConcurrentHashMap<>(); + private static final Map> LOG_ENTRIES = new ConcurrentHashMap<>(); private static final ScheduledExecutorService LOG_SCHEDULED = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-Access-Log", true)); @@ -112,23 +114,23 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { } private void log(String accessLog, AccessLogData accessLogData) { - Set logSet = LOG_ENTRIES.computeIfAbsent(accessLog, k -> new ConcurrentHashSet<>()); + Queue logQueue = LOG_ENTRIES.computeIfAbsent(accessLog, k -> new ConcurrentLinkedQueue<>()); - if (logSet.size() < LOG_MAX_BUFFER) { - logSet.add(accessLogData); + if (logQueue.size() < LOG_MAX_BUFFER) { + logQueue.add(accessLogData); } else { logger.warn("AccessLog buffer is full. Do a force writing to file to clear buffer."); - //just write current logSet to file. - writeLogSetToFile(accessLog, logSet); - //after force writing, add accessLogData to current logSet - logSet.add(accessLogData); + //just write current logQueue to file. + writeLogQueueToFile(accessLog, logQueue); + //after force writing, add accessLogData to current logQueue + logQueue.add(accessLogData); } } - private void writeLogSetToFile(String accessLog, Set logSet) { + private void writeLogQueueToFile(String accessLog, Queue logQueue) { try { if (ConfigUtils.isDefault(accessLog)) { - processWithServiceLogger(logSet); + processWithServiceLogger(logQueue); } else { File file = new File(accessLog); createIfLogDirAbsent(file); @@ -136,7 +138,7 @@ private void writeLogSetToFile(String accessLog, Set logSet) { logger.debug("Append log to " + accessLog); } renameFile(file); - processWithAccessKeyLogger(logSet, file); + processWithAccessKeyLogger(logQueue, file); } } catch (Exception e) { logger.error(e.getMessage(), e); @@ -145,28 +147,28 @@ private void writeLogSetToFile(String accessLog, Set logSet) { private void writeLogToFile() { if (!LOG_ENTRIES.isEmpty()) { - for (Map.Entry> entry : LOG_ENTRIES.entrySet()) { + for (Map.Entry> entry : LOG_ENTRIES.entrySet()) { String accessLog = entry.getKey(); - Set logSet = entry.getValue(); - writeLogSetToFile(accessLog, logSet); + Queue logQueue = entry.getValue(); + writeLogQueueToFile(accessLog, logQueue); } } } - private void processWithAccessKeyLogger(Set logSet, File file) throws IOException { + private void processWithAccessKeyLogger(Queue logQueue, File file) throws IOException { try (FileWriter writer = new FileWriter(file, true)) { - for (Iterator iterator = logSet.iterator(); + for (Iterator iterator = logQueue.iterator(); iterator.hasNext(); iterator.remove()) { writer.write(iterator.next().getLogMessage()); - writer.write(System.getProperty("line.separator")); + writer.write(System.getProperty(LINE_SEPARATOR)); } writer.flush(); } } - private void processWithServiceLogger(Set logSet) { - for (Iterator iterator = logSet.iterator(); + private void processWithServiceLogger(Queue logQueue) { + for (Iterator iterator = logQueue.iterator(); iterator.hasNext(); iterator.remove()) { AccessLogData logData = iterator.next(); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java index 4b826bb49c1..da1895bf3c8 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java @@ -48,9 +48,9 @@ import static org.apache.dubbo.rpc.Constants.THROW_PREFIX; final public class MockInvoker implements Invoker { - private final static ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - private final static Map> MOCK_MAP = new ConcurrentHashMap>(); - private final static Map THROWABLE_MAP = new ConcurrentHashMap(); + private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + private static final Map> MOCK_MAP = new ConcurrentHashMap>(); + private static final Map THROWABLE_MAP = new ConcurrentHashMap(); private final URL url; private final Class type; diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java index 97184cd3ce7..0ee47a2966a 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java @@ -26,12 +26,11 @@ import org.apache.dubbo.rpc.support.AccessLogData; import org.apache.dubbo.rpc.support.MockInvocation; import org.apache.dubbo.rpc.support.MyInvoker; - import org.junit.jupiter.api.Test; import java.lang.reflect.Field; import java.util.Map; -import java.util.Set; +import java.util.Queue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -70,7 +69,7 @@ public void testDefault() throws NoSuchFieldException, IllegalAccessException { accessLogFilter.invoke(invoker, invocation); - Map> logs = (Map>) field.get(AccessLogFilter.class); + Map> logs = (Map>) field.get(AccessLogFilter.class); assertFalse(logs.isEmpty()); assertFalse(logs.get("true").isEmpty()); AccessLogData log = logs.get("true").iterator().next(); diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/listener/InvokerListenerTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/listener/InvokerListenerTest.java new file mode 100644 index 00000000000..c93db873de6 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/listener/InvokerListenerTest.java @@ -0,0 +1,38 @@ +/* + * 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.rpc.listener; + + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.rpc.InvokerListener; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class InvokerListenerTest { + + @Test + public void testReferred(){ + InvokerListener mapInvokerListener = ExtensionLoader.getExtensionLoader(InvokerListener.class).getExtension("mapinvokerlistener"); + mapInvokerListener.referred(null); + mapInvokerListener.destroyed(null); + + MapInvokerListener listener = (MapInvokerListener) mapInvokerListener; + Assertions.assertEquals("referred", listener.getReferred()); + Assertions.assertEquals("destroyed", listener.getDestroyed()); + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/listener/MapInvokerListener.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/listener/MapInvokerListener.java new file mode 100644 index 00000000000..376b9422591 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/listener/MapInvokerListener.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dubbo.rpc.listener; + +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.InvokerListener; +import org.apache.dubbo.rpc.RpcException; + +import java.util.HashMap; +import java.util.Map; + +public class MapInvokerListener implements InvokerListener { + private Map storeMap = new HashMap<>(2); + + @Override + public void referred(Invoker invoker) throws RpcException { + storeMap.put("referred", "referred"); + } + + @Override + public void destroyed(Invoker invoker) { + storeMap.put("destroyed", "destroyed"); + } + + public String getReferred() { + return storeMap.get("referred"); + } + + public String getDestroyed() { + return storeMap.get("destroyed"); + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.InvokerListener b/dubbo-rpc/dubbo-rpc-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.InvokerListener new file mode 100644 index 00000000000..11400c0a2ee --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.InvokerListener @@ -0,0 +1 @@ +mapinvokerlistener=org.apache.dubbo.rpc.listener.MapInvokerListener \ No newline at end of file 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 85b7d388526..35cd19ebe19 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 @@ -95,7 +95,8 @@ public class DubboProtocol extends AbstractProtocol { public static final int DEFAULT_PORT = 20880; private static final String IS_CALLBACK_SERVICE_INVOKE = "_isCallBackServiceInvoke"; - private static DubboProtocol INSTANCE; + private static volatile DubboProtocol INSTANCE; + private static Object MONITOR = new Object(); /** * @@ -209,15 +210,16 @@ private Invocation createInvocation(Channel channel, URL url, String methodKey) }; public DubboProtocol() { - INSTANCE = this; } public static DubboProtocol getDubboProtocol() { - if (INSTANCE == null) { - // load - ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(DubboProtocol.NAME); + if (null == INSTANCE) { + synchronized (MONITOR) { + if (null == INSTANCE) { + INSTANCE = (DubboProtocol) ExtensionLoader.getExtensionLoader(Protocol.class).getOriginalInstance(DubboProtocol.NAME); + } + } } - return INSTANCE; } @@ -262,8 +264,10 @@ Invoker getInvoker(Channel channel, Invocation inv) throws RemotingException DubboExporter exporter = (DubboExporter) exporterMap.get(serviceKey); if (exporter == null) { - throw new RemotingException(channel, "Not found exported service: " + serviceKey + " in " + exporterMap.keySet() + ", may be version or group mismatch " + - ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress() + ", message:" + getInvocationWithoutData(inv)); + throw new RemotingException(channel, + "Not found exported service: " + serviceKey + " in " + exporterMap.keySet() + ", may be version or group mismatch " + + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress() + + ", message:" + getInvocationWithoutData(inv)); } return exporter.getInvoker(); @@ -371,7 +375,8 @@ private void optimizeSerialization(URL url) throws RpcException { try { Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className); if (!SerializationOptimizer.class.isAssignableFrom(clazz)) { - throw new RpcException("The serialization optimizer " + className + " isn't an instance of " + SerializationOptimizer.class.getName()); + throw new RpcException( + "The serialization optimizer " + className + " isn't an instance of " + SerializationOptimizer.class.getName()); } SerializationOptimizer optimizer = (SerializationOptimizer) clazz.newInstance(); @@ -408,35 +413,24 @@ public Invoker protocolBindingRefer(Class serviceType, URL url) throws private ExchangeClient[] getClients(URL url) { // whether to share connection - - boolean useShareConnect = false; - int connections = url.getParameter(CONNECTIONS_KEY, 0); - List shareClients = null; // if not configured, connection is shared, otherwise, one connection for one service if (connections == 0) { - useShareConnect = true; - /* * The xml configuration should have a higher priority than properties. */ String shareConnectionsStr = url.getParameter(SHARE_CONNECTIONS_KEY, (String) null); connections = Integer.parseInt(StringUtils.isBlank(shareConnectionsStr) ? ConfigUtils.getProperty(SHARE_CONNECTIONS_KEY, DEFAULT_SHARE_CONNECTIONS) : shareConnectionsStr); - shareClients = getSharedClient(url, connections); - } - - ExchangeClient[] clients = new ExchangeClient[connections]; - for (int i = 0; i < clients.length; i++) { - if (useShareConnect) { - clients[i] = shareClients.get(i); - - } else { + return getSharedClient(url, connections).toArray(new ExchangeClient[0]); + } else { + ExchangeClient[] clients = new ExchangeClient[connections]; + for (int i = 0; i < clients.length; i++) { clients[i] = initClient(url); } + return clients; } - return clients; } /** @@ -530,7 +524,8 @@ private boolean checkClientCanUse(List referenceCo for (ReferenceCountExchangeClient referenceCountExchangeClient : referenceCountExchangeClients) { // As long as one client is not available, you need to replace the unavailable client with the available one. - if (referenceCountExchangeClient == null || referenceCountExchangeClient.getCount() <= 0 || referenceCountExchangeClient.isClosed()) { + if (referenceCountExchangeClient == null || referenceCountExchangeClient.getCount() <= 0 || + referenceCountExchangeClient.isClosed()) { return false; } } @@ -601,7 +596,8 @@ private ExchangeClient initClient(URL url) { // BIO is not allowed since it has severe performance issue. if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) { throw new RpcException("Unsupported client type: " + str + "," + - " supported client type is " + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), " ")); + " supported client type is " + + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), " ")); } ExchangeClient client; diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java index 2947e7ef04b..681915a8892 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java @@ -48,7 +48,7 @@ final class LazyConnectExchangeClient implements ExchangeClient { * when this warning rises from invocation, program probably have bug. */ protected static final String REQUEST_WITH_WARNING_KEY = "lazyclient_request_with_warning"; - private final static Logger logger = LoggerFactory.getLogger(LazyConnectExchangeClient.class); + private static final Logger logger = LoggerFactory.getLogger(LazyConnectExchangeClient.class); protected final boolean requestWithWarning; private final URL url; private final ExchangeHandler requestHandler; 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 0eac851f3e4..98e079f6f0c 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 @@ -40,7 +40,7 @@ @SuppressWarnings("deprecation") final class ReferenceCountExchangeClient implements ExchangeClient { - private final static Logger logger = LoggerFactory.getLogger(ReferenceCountExchangeClient.class); + private static final Logger logger = LoggerFactory.getLogger(ReferenceCountExchangeClient.class); private final URL url; private final AtomicInteger referenceCount = new AtomicInteger(0); private final AtomicInteger disconnectCount = new AtomicInteger(0); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvailableTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvailableTest.java index dd296ccfe86..4f8dcb28ecb 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvailableTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvailableTest.java @@ -53,7 +53,7 @@ public static void setUpBeforeClass() throws Exception { @BeforeEach public void setUp() throws Exception { - protocol = new DubboProtocol(); + protocol = DubboProtocol.getDubboProtocol(); } @AfterAll diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java index 3377eeb59cf..6fc5002c915 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java @@ -75,6 +75,14 @@ public void testDemoProtocol() throws Exception { assertEquals(service.getSize(new String[]{"", "", ""}), 3); } + @Test + public void testGetDubboProtocol(){ + DemoService service = new DemoServiceImpl(); + int port = NetUtils.getAvailablePort(); + protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName()))); + Assertions.assertTrue(DubboProtocol.getDubboProtocol().getServers().size() > 0); + } + @Test public void testDubboProtocol() throws Exception { DemoService service = new DemoServiceImpl(); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/filter/MockChannel.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/filter/MockChannel.java new file mode 100644 index 00000000000..f8df7e4749d --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/filter/MockChannel.java @@ -0,0 +1,121 @@ +/* + * 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.rpc.protocol.dubbo.filter; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class MockChannel implements Channel { + + private Map attributes = new HashMap<>(); + private List receivedObjects = new LinkedList<>(); + private URL url; + + public MockChannel() { + } + + public MockChannel(URL url) { + this.url = url; + } + + @Override + public InetSocketAddress getRemoteAddress() { + return null; + } + + @Override + public boolean isConnected() { + return true; + } + + @Override + public boolean hasAttribute(String key) { + return attributes.containsKey(key); + } + + @Override + public Object getAttribute(String key) { + return attributes.getOrDefault(key, null); + } + + @Override + public void setAttribute(String key, Object value) { + attributes.put(key, value); + } + + @Override + public void removeAttribute(String key) { + attributes.remove(key); + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public ChannelHandler getChannelHandler() { + return null; + } + + @Override + public InetSocketAddress getLocalAddress() { + return null; + } + + @Override + public void send(Object message) throws RemotingException { + receivedObjects.add(message); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + receivedObjects.add(message); + } + + @Override + public void close() { + + } + + @Override + public void close(int timeout) { + + } + + @Override + public void startClose() { + + } + + @Override + public boolean isClosed() { + return false; + } + + public List getReceivedObjects() { + return receivedObjects; + } +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilterTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilterTest.java new file mode 100644 index 00000000000..f8a30f28630 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilterTest.java @@ -0,0 +1,137 @@ +/* + * 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.rpc.protocol.dubbo.filter; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService; +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 java.lang.reflect.Field; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +public class TraceFilterTest { + + private MockChannel mockChannel; + private static final String TRACE_MAX = "trace.max"; + private static final String TRACE_COUNT = "trace.count"; + private static final String TRACERS_FIELD_NAME = "TRACERS"; + + @BeforeEach + public void setUp() { + URL url = URL.valueOf("dubbo://127.0.0.1:20884/demo"); + mockChannel = new MockChannel(url); + } + + @AfterEach + public void tearDown() { + mockChannel.close(); + } + + @Test + public void testAddAndRemoveTracer() throws Exception { + String method = "sayHello"; + Class type = DemoService.class; + String key = type.getName() + "." + method; + + // add tracer + TraceFilter.addTracer(type, method, mockChannel, 100); + + Assertions.assertEquals(100, mockChannel.getAttribute(TRACE_MAX)); + Assertions.assertTrue(mockChannel.getAttribute(TRACE_COUNT) instanceof AtomicInteger); + + Field tracers = TraceFilter.class.getDeclaredField(TRACERS_FIELD_NAME); + tracers.setAccessible(true); + ConcurrentHashMap> o = (ConcurrentHashMap>) tracers.get(new ConcurrentHashMap>()); + + Assertions.assertTrue(o.containsKey(key)); + Set channels = o.get(key); + Assertions.assertNotNull(channels); + Assertions.assertTrue(channels.contains(mockChannel)); + + // remove tracer + TraceFilter.removeTracer(type, method, mockChannel); + Assertions.assertNull(mockChannel.getAttribute(TRACE_MAX)); + Assertions.assertNull(mockChannel.getAttribute(TRACE_COUNT)); + Assertions.assertFalse(channels.contains(mockChannel)); + } + + @Test + public void testInvoke() throws Exception { + String method = "sayHello"; + Class type = DemoService.class; + String key = type.getName() + "." + method; + // add tracer + TraceFilter.addTracer(type, method, mockChannel, 2); + + Invoker mockInvoker = mock(Invoker.class); + Invocation mockInvocation = mock(Invocation.class); + Result mockResult = mock(Result.class); + TraceFilter filter = new TraceFilter(); + + given(mockInvoker.getInterface()).willReturn(DemoService.class); + given(mockInvocation.getMethodName()).willReturn(method); + given(mockInvocation.getArguments()).willReturn(new Object[0]); + given(mockInvoker.invoke(mockInvocation)).willReturn(mockResult); + given(mockResult.getValue()).willReturn("result"); + + // test invoke + filter.invoke(mockInvoker, mockInvocation); + String message = listToString(mockChannel.getReceivedObjects()); + String expectMessage = "org.apache.dubbo.rpc.protocol.dubbo.support.DemoService.sayHello([]) -> \"result\""; + System.out.println("actual message: " + message); + Assertions.assertTrue(message.contains(expectMessage)); + Assertions.assertTrue(message.contains("elapsed:")); + AtomicInteger traceCount = (AtomicInteger) mockChannel.getAttribute(TRACE_COUNT); + Assertions.assertEquals(1, traceCount.get()); + + // test remove channel when count >= max - 1 + filter.invoke(mockInvoker, mockInvocation); + Field tracers = TraceFilter.class.getDeclaredField(TRACERS_FIELD_NAME); + tracers.setAccessible(true); + ConcurrentHashMap> o = (ConcurrentHashMap>) tracers.get(new ConcurrentHashMap>()); + Assertions.assertTrue(o.containsKey(key)); + Set channels = o.get(key); + Assertions.assertNotNull(channels); + Assertions.assertFalse(channels.contains(mockChannel)); + } + + private static String listToString(List objectList) { + StringBuilder sb = new StringBuilder(); + if (CollectionUtils.isEmpty(objectList)) { + return ""; + } + + objectList.forEach(o -> { + sb.append(o.toString()); + }); + return sb.toString(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusCheckerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusCheckerTest.java new file mode 100644 index 00000000000..548e8446199 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusCheckerTest.java @@ -0,0 +1,65 @@ +/* + * 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.rpc.protocol.dubbo.status; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.status.StatusChecker; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol; +import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService; +import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl; +import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class ServerStatusCheckerTest { + private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + + @AfterAll + public static void after() { + ApplicationModel.getServiceRepository().unregisterService(DemoService.class); + } + + @BeforeAll + public static void setup() { + ApplicationModel.getServiceRepository().registerService(DemoService.class); + } + + @Test + public void testServerStatusChecker() throws Exception { + int port = NetUtils.getAvailablePort(7000); + URL url = URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName()); + DemoService service = new DemoServiceImpl(); + + DubboProtocol.getDubboProtocol().export(proxy.getInvoker(service, DemoService.class, url)); + + StatusChecker server = ExtensionLoader.getExtensionLoader(StatusChecker.class).getExtension("server"); + Assertions.assertEquals(ServerStatusChecker.class, server.getClass()); + + Status status = server.check(); + Assertions.assertEquals(Status.Level.OK, status.getLevel()); + + ProtocolUtils.closeAll(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusCheckerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusCheckerTest.java new file mode 100644 index 00000000000..540b17892dc --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusCheckerTest.java @@ -0,0 +1,84 @@ +/* + * 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.rpc.protocol.dubbo.status; + +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.store.DataStore; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.concurrent.ThreadPoolExecutor; + + +public class ThreadPoolStatusCheckerTest { + + private ThreadPoolStatusChecker threadPoolStatusChecker; + private Status status; + + @BeforeEach + public void setUp() { + threadPoolStatusChecker = new ThreadPoolStatusChecker(); + status = threadPoolStatusChecker.check(); + } + + @Test + public void statusUnknownTest() { + Assertions.assertEquals(status.getLevel(), Status.Level.UNKNOWN); + } + + @Test + public void statusOkTest() { + int activeCount = 1; + int maximumPoolSize = 3; + String portKey = "8888"; + mockThreadPoolExecutor(activeCount, maximumPoolSize, portKey); + + Status status = threadPoolStatusChecker.check(); + + Assertions.assertEquals(status.getLevel(), Status.Level.OK); + Assertions.assertEquals(status.getMessage(), "Pool status:OK, max:" + maximumPoolSize + ", core:0, largest:0, active:" + activeCount + ", task:0, service port: " + portKey); + } + + + @Test + public void statusWarnTest() { + int activeCount = 1; + int maximumPoolSize = 2; + String portKey = "8888"; + mockThreadPoolExecutor(activeCount, maximumPoolSize, portKey); + + Status status = threadPoolStatusChecker.check(); + + Assertions.assertEquals(status.getLevel(), Status.Level.WARN); + Assertions.assertEquals(status.getMessage(), "Pool status:WARN, max:" + maximumPoolSize + ", core:0, largest:0, active:" + activeCount + ", task:0, service port: 8888"); + } + + private void mockThreadPoolExecutor(int activeCount, int maximumPoolSize, String portKey) { + DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension(); + + ThreadPoolExecutor executor = Mockito.mock(ThreadPoolExecutor.class); + Mockito.when(executor.getActiveCount()).thenReturn(activeCount); + Mockito.when(executor.getMaximumPoolSize()).thenReturn(maximumPoolSize); + + dataStore.put(CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY, portKey, executor); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java index 42c311505cb..c6ea600ae73 100644 --- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java +++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java @@ -44,7 +44,7 @@ */ public class GrpcProtocol extends AbstractProxyProtocol { - public final static int DEFAULT_PORT = 50051; + public static final int DEFAULT_PORT = 50051; /* */ private final ConcurrentMap channelMap = new ConcurrentHashMap<>(); diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocolTest.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocolTest.java index 8efe2a63c4f..0370c6b72e9 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocolTest.java @@ -51,10 +51,6 @@ public class InjvmProtocolTest { - static { - InjvmProtocol injvm = InjvmProtocol.getInjvmProtocol(); - } - private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); private List> exporters = new ArrayList>(); diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/ProtocolTest.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/ProtocolTest.java index 12de553d195..f0dc5a412cf 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/ProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/ProtocolTest.java @@ -36,10 +36,6 @@ public String echo(String e) { } }; - static { - InjvmProtocol injvm = InjvmProtocol.getInjvmProtocol(); - } - ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension("javassist"); URL url = URL.valueOf("injvm://localhost:0/org.apache.dubbo.rpc.support.IEcho?interface=org.apache.dubbo.rpc.support.IEcho"); diff --git a/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/DemoService.thrift b/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/DemoService.thrift index 12154f8dcf9..dbd3ec94aa0 100644 --- a/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/DemoService.thrift +++ b/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/DemoService.thrift @@ -1,3 +1,19 @@ +/* + * 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. + */ namespace java org.apache.dubbo.rpc.protocol.nativethrift namespace go demo /*Demo service define file,can be generated to interface files*/ diff --git a/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/UserService.thrift b/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/UserService.thrift index c2f18e429a8..9178c6a2406 100644 --- a/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/UserService.thrift +++ b/dubbo-rpc/dubbo-rpc-native-thrift/src/test/idls/UserService.thrift @@ -1,3 +1,19 @@ +/* + * 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. + */ namespace java org.apache.dubbo.rpc.protocol.nativethrift namespace go demo diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestDubbo.thrift b/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestDubbo.thrift index 3e2023a9e17..f0b4df17b77 100644 --- a/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestDubbo.thrift +++ b/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestDubbo.thrift @@ -1,3 +1,19 @@ +/* + * 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. + */ service ClassNameTestDubbo { string echo(1:required string arg); } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestThrift.thrift b/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestThrift.thrift index ccac7a1e0a4..294010bdfb6 100644 --- a/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestThrift.thrift +++ b/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/ClassNameTestThrift.thrift @@ -1,3 +1,19 @@ +/* + * 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. + */ service ClassNameTestThrift { string echo(1:required string arg); } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/Demo.thrift b/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/Demo.thrift index 8e66074a1d1..c7843383e42 100644 --- a/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/Demo.thrift +++ b/dubbo-rpc/dubbo-rpc-thrift/src/test/thrift/Demo.thrift @@ -1,3 +1,19 @@ +/* + * 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. + */ namespace dubbo_java org.apache.dubbo.rpc.gen.dubbo namespace dubbo_cpp org.apache.dubbo.rpc.gen.dubbo diff --git a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/JavaObjectInput.java b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/JavaObjectInput.java index 936ab265063..b7a32942c7b 100644 --- a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/JavaObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/JavaObjectInput.java @@ -27,7 +27,7 @@ * Java object input implementation */ public class JavaObjectInput extends NativeJavaObjectInput { - public final static int MAX_BYTE_ARRAY_LENGTH = 8 * 1024 * 1024; + public static final int MAX_BYTE_ARRAY_LENGTH = 8 * 1024 * 1024; public JavaObjectInput(InputStream is) throws IOException { super(new ObjectInputStream(is)); diff --git a/pom.xml b/pom.xml index 3fd0bf7eb05..407b226bd84 100644 --- a/pom.xml +++ b/pom.xml @@ -191,6 +191,12 @@ ${mockito_version} test + + org.mockito + mockito-inline + ${mockito_version} + test + cglib cglib-nodep @@ -535,17 +541,16 @@ **/*.versionsBackup **/.idea/ + **/.mvn/ **/*.iml **/*.txt **/*.load **/*.flex **/*.fc - **/*.javascript - **/*.properties - **/*.thrift **/*.sh **/*.bat **/*.md + **/*.properties .git/ .gitignore