diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java index cbcb3a2f4e1..6ac9dd0d141 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java @@ -18,7 +18,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration; -import org.apache.dubbo.common.utils.PathUtils; import org.apache.dubbo.common.utils.StringUtils; import java.util.Collection; @@ -31,6 +30,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty; import static org.apache.dubbo.common.utils.PathUtils.buildPath; +import static org.apache.dubbo.common.utils.PathUtils.normalize; /** * An abstract implementation of {@link DynamicConfiguration} is like "tree-structure" path : @@ -46,6 +46,11 @@ */ public abstract class TreePathDynamicConfiguration extends AbstractDynamicConfiguration { + /** + * The parameter name of URL for the config root path + */ + public static final String CONFIG_ROOT_PATH_PARAM_NAME = PARAM_NAME_PREFIX + "root-path"; + /** * The parameter name of URL for the config base path */ @@ -137,14 +142,24 @@ protected String buildPathKey(String group, String key) { * @return non-null */ protected String getRootPath(URL url) { - String rootPath = PATH_SEPARATOR + getConfigNamespace(url) + getConfigBasePath(url); - rootPath = PathUtils.normalize(rootPath); - if (rootPath.endsWith(PATH_SEPARATOR)) { - rootPath = rootPath.substring(0, rootPath.length() - 1); + + String rootPath = url.getParameter(CONFIG_ROOT_PATH_PARAM_NAME, buildRootPath(url)); + + rootPath = normalize(rootPath); + + int rootPathLength = rootPath.length(); + + if (rootPathLength > 1 && rootPath.endsWith(PATH_SEPARATOR)) { + rootPath = rootPath.substring(0, rootPathLength - 1); } + return rootPath; } + private String buildRootPath(URL url) { + return PATH_SEPARATOR + getConfigNamespace(url) + getConfigBasePath(url); + } + /** * Get the namespace from the specified {@link URL connection URl} * 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 7bcc6eaca84..da9059771cc 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 @@ -36,6 +36,7 @@ import org.apache.dubbo.config.utils.ConfigValidationUtils; import org.apache.dubbo.event.Event; import org.apache.dubbo.event.EventDispatcher; +import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; import org.apache.dubbo.rpc.ProxyFactory; @@ -65,11 +66,14 @@ import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROXY_CLASS_REF; +import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE; import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; @@ -77,6 +81,7 @@ import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost; import static org.apache.dubbo.common.utils.StringUtils.splitToSet; import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY; +import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL; import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY; import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL; import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY; @@ -263,6 +268,10 @@ public synchronized void init() { // appendParameters(map, consumer, Constants.DEFAULT_KEY); AbstractConfig.appendParameters(map, consumer); AbstractConfig.appendParameters(map, this); + MetadataReportConfig metadataReportConfig = getMetadataReportConfig(); + if (metadataReportConfig != null && metadataReportConfig.isValid()) { + map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE); + } Map attributes = null; if (CollectionUtils.isNotEmpty(getMethods())) { attributes = new HashMap<>(); @@ -382,6 +391,16 @@ private T createProxy(Map map) { if (logger.isInfoEnabled()) { logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl()); } + /** + * @since 2.7.0 + * ServiceData Store + */ + String metadata = map.get(METADATA_KEY); + WritableMetadataService metadataService = WritableMetadataService.getExtension(metadata == null ? DEFAULT_METADATA_STORAGE_TYPE : metadata); + if (metadataService != null) { + URL consumerURL = new URL(CONSUMER_PROTOCOL, map.remove(REGISTER_IP_KEY), 0, map.get(INTERFACE_KEY), map); + metadataService.publishServiceDefinition(consumerURL); + } // create service proxy return (T) PROXY_FACTORY.getProxy(invoker, ProtocolUtils.isGeneric(generic)); } 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 5173bf71ced..cf5af44383e 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 @@ -37,6 +37,7 @@ import org.apache.dubbo.config.utils.ConfigValidationUtils; import org.apache.dubbo.event.Event; import org.apache.dubbo.event.EventDispatcher; +import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; @@ -67,13 +68,16 @@ import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND; import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; import static org.apache.dubbo.common.constants.CommonConstants.REGISTER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE; import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; @@ -340,6 +344,10 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List r AbstractConfig.appendParameters(map, provider); AbstractConfig.appendParameters(map, protocolConfig); AbstractConfig.appendParameters(map, this); + MetadataReportConfig metadataReportConfig = getMetadataReportConfig(); + if (metadataReportConfig != null && metadataReportConfig.isValid()) { + map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE); + } if (CollectionUtils.isNotEmpty(getMethods())) { for (MethodConfig method : getMethods()) { AbstractConfig.appendParameters(map, method, method.getName()); @@ -494,6 +502,14 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List r Exporter exporter = PROTOCOL.export(wrapperInvoker); exporters.add(exporter); } + /** + * @since 2.7.0 + * ServiceData Store + */ + WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, DEFAULT_METADATA_STORAGE_TYPE)); + if (metadataService != null) { + metadataService.publishServiceDefinition(url); + } } } this.urls.add(url); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListener.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListener.java deleted file mode 100644 index 9731034c70a..00000000000 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListener.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.config.event.listener; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.config.AbstractInterfaceConfig; -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.MetadataReportConfig; -import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent; -import org.apache.dubbo.config.event.ServiceConfigExportedEvent; -import org.apache.dubbo.event.EventListener; -import org.apache.dubbo.event.GenericEventListener; -import org.apache.dubbo.metadata.WritableMetadataService; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE; -import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE; -import static org.apache.dubbo.metadata.WritableMetadataService.getExtension; - -/** - * An {@link EventListener} {@link WritableMetadataService#publishServiceDefinition(URL) publishs the service definition} - * when {@link ServiceConfigExportedEvent the event of the exported Dubbo service} and - * {@link ReferenceConfigInitializedEvent the event of the referenced Dubbo service} is raised. - * - * @see GenericEventListener - * @see ServiceConfigExportedEvent - * @see ReferenceConfigInitializedEvent - * @since 2.7.8 - */ -public class PublishingServiceDefinitionListener extends GenericEventListener { - - public void onEvent(ReferenceConfigInitializedEvent event) { - handleEvent(event.getReferenceConfig()); - } - - public void onEvent(ServiceConfigExportedEvent event) { - handleEvent(event.getServiceConfig()); - } - - private void handleEvent(AbstractInterfaceConfig config) { - String metadataType = getMetadataType(config); - for (URL exportedURL : config.getExportedUrls()) { - WritableMetadataService metadataService = getExtension(metadataType); - if (metadataService != null) { - metadataService.publishServiceDefinition(exportedURL); - } - } - } - - private String getMetadataType(AbstractInterfaceConfig config) { - ApplicationConfig applicationConfig = config.getApplication(); - String metadataType = applicationConfig.getMetadataType(); - if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) { - MetadataReportConfig metadataReportConfig = config.getMetadataReportConfig(); - if (metadataReportConfig == null || !metadataReportConfig.isValid()) { - metadataType = DEFAULT_METADATA_STORAGE_TYPE; - } - } - return metadataType; - } -} diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener index b1946c09f30..db73041bd43 100644 --- a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener +++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener @@ -1,4 +1,2 @@ service-mapping=org.apache.dubbo.config.event.listener.ServiceNameMappingListener -config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener -# since 2.7.8 -publishing-service-definition=org.apache.dubbo.config.event.listener.PublishingServiceDefinitionListener \ No newline at end of file +config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener \ No newline at end of file diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseServiceMetadataIdentifier.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseServiceMetadataIdentifier.java index 16616ef2f4c..37b53ae3463 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseServiceMetadataIdentifier.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseServiceMetadataIdentifier.java @@ -79,7 +79,7 @@ private String getFilePathKey(String pathTag, String... params) { + joinParams(PATH_SEPARATOR, params); } - private String toServicePath() { + public String toServicePath() { if (ANY_VALUE.equals(serviceInterface)) { return ""; } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java index 5b0f780ff4e..b445febbf2d 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java @@ -25,8 +25,10 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import static org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration.CONFIG_BASE_PATH_PARAM_NAME; -import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_PATH_TAG; +import static org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration.CONFIG_ROOT_PATH_PARAM_NAME; +import static org.apache.dubbo.common.utils.StringUtils.SLASH; +import static org.apache.dubbo.common.utils.StringUtils.isBlank; +import static org.apache.dubbo.metadata.report.identifier.KeyTypeEnum.PATH; import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY; import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY; @@ -60,21 +62,23 @@ public ConfigCenterBasedMetadataReportFactory(KeyTypeEnum keyType) { @Override public ConfigCenterBasedMetadataReport getMetadataReport(URL url) { - - url = url.setPath(URL_PATH).removeParameters(EXPORT_KEY, REFER_KEY); - - final URL actualURL; - if (url.getParameter(CONFIG_BASE_PATH_PARAM_NAME) == null) { - actualURL = url.addParameter(CONFIG_BASE_PATH_PARAM_NAME, DEFAULT_PATH_TAG); - } else { - actualURL = url; - } - + url = url.setPath(URL_PATH); + final URL actualURL = resolveURLParameters(url); String key = actualURL.toServiceString(); // Lock the metadata access process to ensure a single instance of the metadata instance return metadataReportCache.computeIfAbsent(key, k -> new ConfigCenterBasedMetadataReport(actualURL, keyType)); } + private URL resolveURLParameters(URL url) { + URL resolvedURL = url.removeParameters(EXPORT_KEY, REFER_KEY); + if (PATH.equals(getKeyType())) { // Only handles for "PATH" type + if (isBlank(resolvedURL.getParameter(CONFIG_ROOT_PATH_PARAM_NAME))) { + resolvedURL = resolvedURL.addParameter(CONFIG_ROOT_PATH_PARAM_NAME, SLASH); + } + } + return resolvedURL; + } + /** * Get {@link KeyTypeEnum the key type} *