diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml index 6fba3f2da..0d75b9659 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml @@ -1,9 +1,10 @@ - - + + com.alibaba.cloud spring-cloud-alibaba-starters ${revision} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java index 5b1cddf7f..f8946fa7c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java @@ -17,18 +17,18 @@ package com.alibaba.cloud.dubbo.autoconfigure; import java.util.Collection; -import java.util.Optional; import java.util.function.Supplier; import com.alibaba.cloud.dubbo.metadata.DubboProtocolConfigSupplier; import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; -import com.alibaba.cloud.dubbo.metadata.repository.MetadataServiceInstanceSelector; +import com.alibaba.cloud.dubbo.metadata.repository.RandomServiceInstanceSelector; +import com.alibaba.cloud.dubbo.metadata.repository.ServiceInstanceSelector; import com.alibaba.cloud.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver; import com.alibaba.cloud.dubbo.metadata.resolver.MetadataResolver; -import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceExporter; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; import com.alibaba.cloud.dubbo.service.IntrospectiveDubboMetadataService; +import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; import com.alibaba.cloud.dubbo.util.JSONUtils; import feign.Contract; import org.apache.dubbo.config.ProtocolConfig; @@ -44,7 +44,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.EventListener; -import org.springframework.util.CollectionUtils; /** * Spring Boot Auto-Configuration class for Dubbo Metadata. @@ -53,7 +52,8 @@ import org.springframework.util.CollectionUtils; */ @Configuration @Import({ DubboServiceMetadataRepository.class, IntrospectiveDubboMetadataService.class, - DubboMetadataServiceExporter.class, JSONUtils.class }) + DubboMetadataServiceExporter.class, JSONUtils.class, + DubboMetadataServiceProxy.class, DubboMetadataUtils.class }) public class DubboMetadataAutoConfiguration { @Autowired @@ -73,9 +73,8 @@ public class DubboMetadataAutoConfiguration { @Bean @ConditionalOnMissingBean - public MetadataServiceInstanceSelector metadataServiceInstanceSelector() { - return serviceInstances -> CollectionUtils.isEmpty(serviceInstances) - ? Optional.empty() : serviceInstances.stream().findAny(); + public ServiceInstanceSelector metadataServiceInstanceSelector() { + return new RandomServiceInstanceSelector(); } @Bean @@ -84,15 +83,7 @@ public class DubboMetadataAutoConfiguration { return new DubboProtocolConfigSupplier(protocols); } - @Bean - @ConditionalOnMissingBean - public DubboMetadataServiceProxy dubboMetadataConfigServiceProxy( - DubboGenericServiceFactory factory) { - return new DubboMetadataServiceProxy(factory); - } - // Event-Handling - @EventListener(ServiceBeanExportedEvent.class) public void onServiceBeanExported(ServiceBeanExportedEvent event) { ServiceBean serviceBean = event.getServiceBean(); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java index ea9f397e8..b4b84c37c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java @@ -56,6 +56,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -134,6 +135,9 @@ public class DubboServiceDiscoveryAutoConfiguration { */ private final ObjectProvider> heartbeatEventChangedPredicate; + @Value("${spring.application.name:${dubbo.application.name:application}}") + private String currentApplicationName; + public DubboServiceDiscoveryAutoConfiguration( DubboServiceMetadataRepository dubboServiceMetadataRepository, ApplicationEventPublisher applicationEventPublisher, @@ -153,10 +157,12 @@ public class DubboServiceDiscoveryAutoConfiguration { * NotifyListener) */ private void dispatchServiceInstancesChangedEvent(String serviceName, - Collection serviceInstances) { - if (!hasText(serviceName) || serviceInstances == null) { + List serviceInstances) { + if (!hasText(serviceName) || Objects.equals(currentApplicationName, serviceName) + || serviceInstances == null) { return; } + ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent(serviceName, serviceInstances); if (logger.isInfoEnabled()) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java index 80a0a072d..577d19e59 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java @@ -22,6 +22,8 @@ import java.util.Set; import org.springframework.boot.context.properties.ConfigurationProperties; +import static com.alibaba.cloud.dubbo.util.DubboCloudConstants.CONFIG_PROPERTY_PREFIX; +import static com.alibaba.cloud.dubbo.util.DubboCloudConstants.DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE; import static org.springframework.util.StringUtils.commaDelimitedListToStringArray; import static org.springframework.util.StringUtils.hasText; import static org.springframework.util.StringUtils.trimAllWhitespace; @@ -31,7 +33,7 @@ import static org.springframework.util.StringUtils.trimAllWhitespace; * * @author Mercy */ -@ConfigurationProperties(prefix = "dubbo.cloud") +@ConfigurationProperties(prefix = CONFIG_PROPERTY_PREFIX) public class DubboCloudProperties { /** @@ -47,6 +49,8 @@ public class DubboCloudProperties { */ private String subscribedServices = ALL_DUBBO_SERVICES; + private String registryType = DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE; + public String getSubscribedServices() { return subscribedServices; } @@ -79,4 +83,12 @@ public class DubboCloudProperties { return Collections.unmodifiableSet(subscribedServices); } + public String getRegistryType() { + return registryType; + } + + public void setRegistryType(String registryType) { + this.registryType = registryType; + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java index c13dcef27..faf9ef8ba 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java @@ -84,7 +84,7 @@ public class DubboNonWebApplicationEnvironmentPostProcessor @Override public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { + SpringApplication application) { WebApplicationType webApplicationType = application.getWebApplicationType(); if (!WebApplicationType.NONE.equals(webApplicationType)) { // Just works in @@ -117,7 +117,7 @@ public class DubboNonWebApplicationEnvironmentPostProcessor * @param defaultProperties defaultProperties */ private void resetServerPort(ConfigurableEnvironment environment, - Map defaultProperties) { + Map defaultProperties) { String serverPort = environment.getProperty(SERVER_PORT_PROPERTY_NAME, environment.getProperty(PORT_PROPERTY_NAME)); @@ -181,7 +181,7 @@ public class DubboNonWebApplicationEnvironmentPostProcessor } private void setServerPort(ConfigurableEnvironment environment, String serverPort, - Map defaultProperties) { + Map defaultProperties) { if (serverPort == null) { return; } @@ -196,7 +196,7 @@ public class DubboNonWebApplicationEnvironmentPostProcessor * @param map Default Dubbo Properties */ private void addOrReplace(MutablePropertySources propertySources, - Map map) { + Map map) { MapPropertySource target = null; if (propertySources.contains(PROPERTY_SOURCE_NAME)) { PropertySource source = propertySources.get(PROPERTY_SOURCE_NAME); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 65ada71e5..a5be34df8 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -22,9 +22,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.PostConstruct; @@ -38,6 +36,7 @@ import com.alibaba.cloud.dubbo.registry.event.SubscribedServicesChangedEvent; import com.alibaba.cloud.dubbo.service.DubboMetadataService; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceExporter; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; +import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; import com.alibaba.cloud.dubbo.util.JSONUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; @@ -61,15 +60,15 @@ import org.springframework.util.MultiValueMap; import static com.alibaba.cloud.dubbo.env.DubboCloudProperties.ALL_DUBBO_SERVICES; import static com.alibaba.cloud.dubbo.http.DefaultHttpRequest.builder; -import static java.lang.String.format; import static java.lang.String.valueOf; -import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; -import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_PREFIX; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME; import static org.springframework.util.CollectionUtils.isEmpty; import static org.springframework.util.StringUtils.hasText; @@ -85,14 +84,15 @@ public class DubboServiceMetadataRepository /** * The prefix of {@link DubboMetadataService} : "dubbo.metadata-service.". */ - public static final String DUBBO_METADATA_SERVICE_PREFIX = "dubbo.metadata-service."; + @Deprecated + public static final String DUBBO_METADATA_SERVICE_PREFIX = METADATA_SERVICE_PREFIX; /** * The {@link URL URLs} property name of {@link DubboMetadataService} : * "dubbo.metadata-service.urls". */ - public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = DUBBO_METADATA_SERVICE_PREFIX - + "urls"; + @Deprecated + public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = METADATA_SERVICE_URLS_PROPERTY_NAME; /** * The {@link String#format(String, Object...) pattern} of dubbo protocols port. @@ -108,11 +108,6 @@ public class DubboServiceMetadataRepository */ private final Object monitor = new Object(); - /** - * A {@link Set} of service names that had been initialized. - */ - private final Set initializedServices = new LinkedHashSet<>(); - /** * All exported {@link URL urls} {@link Map} whose key is the return value of * {@link URL#getServiceKey()} method and value is the {@link List} of {@link URL @@ -122,12 +117,6 @@ public class DubboServiceMetadataRepository // =================================== Registration // =================================== // - /** - * The subscribed {@link URL urls} {@link Map} of {@link DubboMetadataService}, whose - * key is the return value of {@link URL#getServiceKey()} method and value is the - * {@link List} of {@link URL URLs}. - */ - private final MultiValueMap subscribedDubboMetadataServiceURLs = new LinkedMultiValueMap<>(); // ==================================================================================== // // @@ -172,7 +161,7 @@ public class DubboServiceMetadataRepository private DiscoveryClient discoveryClient; @Autowired - private MetadataServiceInstanceSelector metadataServiceInstanceSelector; + private ServiceInstanceSelector serviceInstanceSelector; @Autowired private JSONUtils jsonUtils; @@ -180,6 +169,9 @@ public class DubboServiceMetadataRepository @Autowired private InetUtils inetUtils; + @Autowired + private DubboMetadataUtils dubboMetadataUtils; + @Value("${spring.application.name}") private String currentApplicationName; @@ -190,7 +182,7 @@ public class DubboServiceMetadataRepository // // private static Map getMap(Map> repository, - String key) { + String key) { return getOrDefault(repository, key, newHashMap()); } @@ -275,28 +267,11 @@ public class DubboServiceMetadataRepository * @param serviceName service of name */ public void initializeMetadata(String serviceName) { - synchronized (monitor) { - if (initializedServices.contains(serviceName)) { - if (logger.isDebugEnabled()) { - logger.debug( - "The metadata of Dubbo service[name : {}] has been initialized", - serviceName); - } - } - else { - if (logger.isInfoEnabled()) { - logger.info( - "The metadata of Dubbo service[name : {}] is about to be initialized", - serviceName); - } - - if (initSubscribedDubboMetadataService(serviceName)) { - // mark this service name having been initialized - initializedServices.add(serviceName); - } + initDubboRestServiceMetadataRepository(serviceName); + } - } - } + private DubboMetadataService getProxy(String serviceName) { + return dubboMetadataConfigServiceProxy.getProxy(serviceName); } /** @@ -307,15 +282,8 @@ public class DubboServiceMetadataRepository */ public void removeMetadataAndInitializedService(String serviceName, URL url) { synchronized (monitor) { - initializedServices.remove(serviceName); + dubboMetadataConfigServiceProxy.removeProxy(serviceName); dubboRestServiceMetadataRepository.remove(serviceName); - // fix #1260 if the subscribedDubboMetadataServiceURLs removed fail,old meta - // information will be retained - if (DubboMetadataService.class.getName().equals(url.getServiceInterface())) { - String serviceKey = url.getServiceKey(); - subscribedDubboMetadataServiceURLs.remove(serviceKey); - } - } } @@ -343,10 +311,9 @@ public class DubboServiceMetadataRepository } private void addDubboMetadataServiceURLsMetadata(Map metadata, - List dubboMetadataServiceURLs) { + List dubboMetadataServiceURLs) { String dubboMetadataServiceURLsJSON = jsonUtils.toJSON(dubboMetadataServiceURLs); - metadata.put(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME, - dubboMetadataServiceURLsJSON); + metadata.put(METADATA_SERVICE_URLS_PROPERTY_NAME, dubboMetadataServiceURLsJSON); } private void addDubboProtocolsPortMetadata(Map metadata) { @@ -359,15 +326,6 @@ public class DubboServiceMetadataRepository }); } - /** - * Get the property name of Dubbo Protocol. - * @param protocol Dubbo Protocol - * @return non-null - */ - public String getDubboProtocolPropertyName(String protocol) { - return format(DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN, protocol); - } - /** * Publish the {@link Set} of {@link ServiceRestMetadata}. * @param serviceRestMetadataSet the {@link Set} of {@link ServiceRestMetadata} @@ -389,27 +347,6 @@ public class DubboServiceMetadataRepository return unmodifiableSet(serviceRestMetadata); } - public List findSubscribedDubboMetadataServiceURLs(String serviceName, - String group, String version, String protocol) { - String serviceKey = URL.buildKey(serviceName, group, version); - - List urls = null; - - synchronized (monitor) { - urls = subscribedDubboMetadataServiceURLs.get(serviceKey); - } - - if (isEmpty(urls)) { - return emptyList(); - } - - return hasText(protocol) - ? urls.stream() - .filter(url -> url.getProtocol().equalsIgnoreCase(protocol)) - .collect(Collectors.toList()) - : unmodifiableList(urls); - } - /** * The specified service is subscribe or not. * @param serviceName the service name @@ -459,28 +396,17 @@ public class DubboServiceMetadataRepository return allExportedURLs.keySet(); } - /** - * Get the {@link URL urls} that {@link DubboMetadataService} exported by the - * specified {@link ServiceInstance}. - * @param serviceInstance {@link ServiceInstance} - * @return the mutable {@link URL urls} - */ - public List getDubboMetadataServiceURLs(ServiceInstance serviceInstance) { - Map metadata = serviceInstance.getMetadata(); - String dubboURLsJSON = metadata.get(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME); - return jsonUtils.toURLs(dubboURLsJSON); + public Integer getDubboProtocolPort(ServiceInstance serviceInstance, + String protocol) { + return dubboMetadataUtils.getDubboProtocolPort(serviceInstance, protocol); } - public Integer getDubboProtocolPort(ServiceInstance serviceInstance, - String protocol) { - String protocolProperty = getDubboProtocolPropertyName(protocol); - Map metadata = serviceInstance.getMetadata(); - String protocolPort = metadata.get(protocolProperty); - return hasText(protocolPort) ? Integer.valueOf(protocolPort) : null; + private String getDubboProtocolPropertyName(String protocol) { + return dubboMetadataUtils.getDubboProtocolPropertyName(protocol); } public List getExportedURLs(String serviceInterface, String group, - String version) { + String version) { String serviceKey = URL.buildKey(serviceInterface, group, version); return allExportedURLs.getOrDefault(serviceKey, Collections.emptyList()); } @@ -492,6 +418,11 @@ public class DubboServiceMetadataRepository protected void initDubboRestServiceMetadataRepository(String serviceName) { if (dubboRestServiceMetadataRepository.containsKey(serviceName)) { + if (logger.isDebugEnabled()) { + logger.debug( + "The metadata of Dubbo service[name : {}] has been initialized", + serviceName); + } return; } @@ -537,7 +468,7 @@ public class DubboServiceMetadataRepository * @return {@link DubboRestServiceMetadata} if matched, or null */ public DubboRestServiceMetadata get(String serviceName, - RequestMetadata requestMetadata) { + RequestMetadata requestMetadata) { return match(dubboRestServiceMetadataRepository, serviceName, requestMetadata); } @@ -554,7 +485,7 @@ public class DubboServiceMetadataRepository } private T match(Map> repository, - String serviceName, RequestMetadata requestMetadata) { + String serviceName, RequestMetadata requestMetadata) { Map map = repository.get(serviceName); @@ -600,8 +531,7 @@ public class DubboServiceMetadataRepository Set metadata = emptySet(); - DubboMetadataService dubboMetadataService = dubboMetadataConfigServiceProxy - .getProxy(serviceName); + DubboMetadataService dubboMetadataService = getProxy(serviceName); if (dubboMetadataService != null) { try { @@ -626,67 +556,29 @@ public class DubboServiceMetadataRepository subscribedServices.remove(currentApplicationName); } - protected Boolean initSubscribedDubboMetadataService(String serviceName) { - // this need to judge whether the initialization is successful or not. The failed - // initialization will not change the initializedServices - Optional optionalServiceInstance = metadataServiceInstanceSelector - .choose(discoveryClient.getInstances(serviceName)); - if (!((Optional) optionalServiceInstance).isPresent()) { - return false; - } - ServiceInstance serviceInstance = optionalServiceInstance.get(); - if (null == serviceInstance) { - return false; - } - List dubboMetadataServiceURLs = getDubboMetadataServiceURLs(serviceInstance); - if (dubboMetadataServiceURLs.isEmpty()) { - return false; - } - for (URL dubboMetadataServiceURL : dubboMetadataServiceURLs) { - try { - initSubscribedDubboMetadataServiceURL(dubboMetadataServiceURL); - DubboMetadataService dubboMetadataService = dubboMetadataConfigServiceProxy - .getProxy(serviceName); - if (dubboMetadataService == null) { - dubboMetadataService = initDubboMetadataServiceProxy( - dubboMetadataServiceURL); - } - - if (dubboMetadataService == null) { - removeMetadataAndInitializedService(serviceName, - dubboMetadataServiceURL); - return false; - } - } - catch (Throwable e) { - if (logger.isErrorEnabled()) { - logger.error(e.getMessage(), e); - } - return false; - } - } - initDubboRestServiceMetadataRepository(serviceName); - return true; + @Override + public void setApplicationEventPublisher( + ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; } - private void initSubscribedDubboMetadataServiceURL(URL dubboMetadataServiceURL) { - // add subscriptions - String serviceKey = dubboMetadataServiceURL.getServiceKey(); - subscribedDubboMetadataServiceURLs.add(serviceKey, dubboMetadataServiceURL); - } + public List findSubscribedDubboMetadataServiceURLs(URL subscribedURL) { + // The parameter of "group" as the service name + String serviceInterface = subscribedURL.getServiceInterface(); + String group = subscribedURL.getParameter(GROUP_KEY); + String version = subscribedURL.getParameter(VERSION_KEY); + String protocol = subscribedURL.getParameter(PROTOCOL_KEY); + List serviceInstances = discoveryClient.getInstances(group); + List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, + serviceInterface, version, protocol); - private DubboMetadataService initDubboMetadataServiceProxy( - URL dubboMetadataServiceURL) { - String serviceName = dubboMetadataServiceURL.getParameter(APPLICATION_KEY); - String version = dubboMetadataServiceURL.getParameter(VERSION_KEY); - // Initialize DubboMetadataService with right version - return dubboMetadataConfigServiceProxy.initProxy(serviceName, version); + if (logger.isInfoEnabled()) { + logger.info( + "The DubboMetadataService of service [name : {} , instances : {}] URLs[protocol : {} , size : {}] has been subscribed.", + group, serviceInstances.size(), protocol, urls.size()); + } + return urls; } - @Override - public void setApplicationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { - this.applicationEventPublisher = applicationEventPublisher; - } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/RandomServiceInstanceSelector.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/RandomServiceInstanceSelector.java new file mode 100644 index 000000000..3cc911c4b --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/RandomServiceInstanceSelector.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed 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 + * + * https://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 com.alibaba.cloud.dubbo.metadata.repository; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; + +import org.springframework.cloud.client.ServiceInstance; + +import static java.util.Optional.of; +import static org.springframework.util.CollectionUtils.isEmpty; + +/** + * Random {@link ServiceInstanceSelector}. + * + * @author Mercy + */ +public class RandomServiceInstanceSelector implements ServiceInstanceSelector { + + @Override + public Optional select(List serviceInstances) { + if (isEmpty(serviceInstances)) { + return Optional.empty(); + } + ThreadLocalRandom random = ThreadLocalRandom.current(); + return of(serviceInstances.get(random.nextInt(serviceInstances.size()))); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/MetadataServiceInstanceSelector.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/ServiceInstanceSelector.java similarity index 90% rename from spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/MetadataServiceInstanceSelector.java rename to spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/ServiceInstanceSelector.java index 821e3043b..7f0579652 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/MetadataServiceInstanceSelector.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/ServiceInstanceSelector.java @@ -26,13 +26,13 @@ import org.springframework.cloud.client.ServiceInstance; * * @author liuxx */ -public interface MetadataServiceInstanceSelector { +public interface ServiceInstanceSelector { /** * choose a service instance to get metadata. * @param serviceInstances all service instance * @return the service instance to get metadata */ - Optional choose(List serviceInstances); + Optional select(List serviceInstances); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractSpringCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractSpringCloudRegistry.java index 2be28205b..f6434f3c7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractSpringCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractSpringCloudRegistry.java @@ -63,6 +63,7 @@ import static org.springframework.util.StringUtils.hasText; * * @author Mercy */ +@Deprecated public abstract class AbstractSpringCloudRegistry extends FailbackRegistry { /** @@ -98,10 +99,10 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry { private final ConfigurableApplicationContext applicationContext; public AbstractSpringCloudRegistry(URL url, DiscoveryClient discoveryClient, - DubboServiceMetadataRepository dubboServiceMetadataRepository, - DubboMetadataServiceProxy dubboMetadataConfigServiceProxy, - JSONUtils jsonUtils, DubboGenericServiceFactory dubboGenericServiceFactory, - ConfigurableApplicationContext applicationContext) { + DubboServiceMetadataRepository dubboServiceMetadataRepository, + DubboMetadataServiceProxy dubboMetadataConfigServiceProxy, + JSONUtils jsonUtils, DubboGenericServiceFactory dubboGenericServiceFactory, + ConfigurableApplicationContext applicationContext) { super(url); this.servicesLookupInterval = url .getParameter(SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 60L); @@ -190,7 +191,7 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry { * @param listener {@link NotifyListener} */ private void registerServiceInstancesChangedEventListener(URL url, - NotifyListener listener) { + NotifyListener listener) { String listenerId = generateId(url); if (registerListeners.add(listenerId)) { applicationContext.addApplicationListener( @@ -217,8 +218,8 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry { } protected void subscribeDubboServiceURL(URL url, NotifyListener listener, - String serviceName, - Function> serviceInstancesFunction) { + String serviceName, + Function> serviceInstancesFunction) { if (logger.isInfoEnabled()) { logger.info( @@ -355,7 +356,7 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry { } private List getExportedURLs(DubboMetadataService dubboMetadataService, - URL url) { + URL url) { String serviceInterface = url.getServiceInterface(); String group = url.getParameter(GROUP_KEY); String version = url.getParameter(VERSION_KEY); @@ -370,12 +371,7 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry { } private void subscribeDubboMetadataServiceURLs(URL url, NotifyListener listener) { - String serviceInterface = url.getServiceInterface(); - String group = url.getParameter(GROUP_KEY); - String version = url.getParameter(VERSION_KEY); - String protocol = url.getParameter(PROTOCOL_KEY); - List urls = repository.findSubscribedDubboMetadataServiceURLs( - serviceInterface, group, version, protocol); + List urls = repository.findSubscribedDubboMetadataServiceURLs(url); listener.notify(urls); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java new file mode 100644 index 000000000..dbede6986 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -0,0 +1,511 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed 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 + * + * https://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 com.alibaba.cloud.dubbo.registry; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; +import com.alibaba.cloud.dubbo.registry.event.ServiceInstancesChangedEvent; +import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory; +import com.alibaba.cloud.dubbo.service.DubboMetadataService; +import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; +import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; +import com.alibaba.cloud.dubbo.util.JSONUtils; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.support.FailbackRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.util.CollectionUtils; + +import static java.lang.String.format; +import static java.util.Collections.emptyList; +import static java.util.stream.StreamSupport.stream; +import static org.apache.dubbo.common.URLBuilder.from; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; +import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; +import static org.apache.dubbo.common.constants.CommonConstants.SIDE_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.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty; +import static org.apache.dubbo.registry.Constants.ADMIN_PROTOCOL; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME; +import static org.springframework.util.StringUtils.hasText; + +/** + * Dubbo Cloud {@link FailbackRegistry} is based on Spring Cloud {@link DiscoveryClient}. + * + * @author Mercy + */ +public class DubboCloudRegistry extends FailbackRegistry { + + /** + * The parameter name of {@link #servicesLookupInterval}. + */ + public static final String SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.services.lookup.interval"; + + protected static final String DUBBO_METADATA_SERVICE_CLASS_NAME = DubboMetadataService.class + .getName(); + + /** + * Caches the IDs of {@link ApplicationListener}. + */ + private static final Set registerListeners = new HashSet<>(); + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private final DiscoveryClient discoveryClient; + + private final DubboServiceMetadataRepository repository; + + private final DubboMetadataServiceProxy dubboMetadataConfigServiceProxy; + + private final JSONUtils jsonUtils; + + private final DubboGenericServiceFactory dubboGenericServiceFactory; + + private final DubboMetadataUtils dubboMetadataUtils; + + /** + * The interval in second of lookup service names(only for Dubbo-OPS). + */ + private final long servicesLookupInterval; + + private final ConfigurableApplicationContext applicationContext; + + private final String currentApplicationName; + + public DubboCloudRegistry(URL url, DiscoveryClient discoveryClient, + DubboServiceMetadataRepository repository, + DubboMetadataServiceProxy dubboMetadataConfigServiceProxy, + JSONUtils jsonUtils, DubboGenericServiceFactory dubboGenericServiceFactory, + ConfigurableApplicationContext applicationContext) { + + super(url); + this.servicesLookupInterval = url + .getParameter(SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 60L); + this.discoveryClient = discoveryClient; + this.repository = repository; + this.dubboMetadataConfigServiceProxy = dubboMetadataConfigServiceProxy; + this.jsonUtils = jsonUtils; + this.dubboGenericServiceFactory = dubboGenericServiceFactory; + this.applicationContext = applicationContext; + this.dubboMetadataUtils = getBean(DubboMetadataUtils.class); + this.currentApplicationName = dubboMetadataUtils.getCurrentApplicationName(); + } + + private T getBean(Class beanClass) { + return this.applicationContext.getBean(beanClass); + } + + protected boolean shouldRegister(URL url) { + String side = url.getParameter(SIDE_KEY); + + boolean should = PROVIDER_SIDE.equals(side); // Only register the Provider. + + if (!should) { + if (logger.isDebugEnabled()) { + logger.debug("The URL[{}] should not be registered.", url.toString()); + } + } + + return should; + } + + @Override + public final void doRegister(URL url) { + if (!shouldRegister(url)) { + return; + } + repository.exportURL(url); + } + + @Override + public final void doUnregister(URL url) { + if (!shouldRegister(url)) { + return; + } + repository.unexportURL(url); + } + + @Override + public final void doSubscribe(URL url, NotifyListener listener) { + + if (isAdminURL(url)) { + // TODO in future + if (logger.isWarnEnabled()) { + logger.warn("This feature about admin will be supported in the future."); + } + } + else if (isDubboMetadataServiceURL(url)) { // for DubboMetadataService + subscribeDubboMetadataServiceURLs(url, listener); + } + else { // for general Dubbo Services + subscribeURLs(url, listener); + } + } + + private void subscribeURLs(URL url, NotifyListener listener) { + + // Sync subscription + subscribeURLs(url, getServices(url), listener); + + // Async subscription + registerServiceInstancesChangedListener(url, event -> { + + Set serviceNames = getServices(url); + + String serviceName = event.getServiceName(); + + if (serviceNames.contains(serviceName)) { + subscribeURLs(url, serviceNames, listener); + } + }); + } + + private void subscribeURLs(URL url, Set serviceNames, + NotifyListener listener) { + + List subscribedURLs = new LinkedList<>(); + + serviceNames.forEach(serviceName -> { + + subscribeURLs(url, subscribedURLs, serviceName, + () -> getServiceInstances(serviceName)); + + }); + + // Notify all + notifyAllSubscribedURLs(url, subscribedURLs, listener); + } + + private void registerServiceInstancesChangedListener(URL url, + ApplicationListener listener) { + String listenerId = generateId(url); + if (registerListeners.add(listenerId)) { + applicationContext.addApplicationListener(listener); + } + } + + private void subscribeURLs(URL subscribedURL, List subscribedURLs, + String serviceName, + Supplier> serviceInstancesSupplier) { + List serviceInstances = serviceInstancesSupplier.get(); + subscribeURLs(subscribedURL, subscribedURLs, serviceName, serviceInstances); + } + + private void subscribeURLs(URL subscribedURL, List subscribedURLs, + String serviceName, List serviceInstances) { + + if (CollectionUtils.isEmpty(serviceInstances)) { + if (logger.isWarnEnabled()) { + logger.warn(format("There is no instance in service[name : %s]", + serviceName)); + } + } + + List exportedURLs = getExportedURLs(subscribedURL, serviceName, + serviceInstances); + + /** + * Add the exported URLs from {@link MetadataService} + */ + subscribedURLs.addAll(exportedURLs); + } + + private List getExportedURLs(URL subscribedURL, String serviceName, + List serviceInstances) { + + List validServiceInstances = filter(serviceInstances); + + // If there is no valid ServiceInstance, return empty result + if (isEmpty(validServiceInstances)) { + if (logger.isWarnEnabled()) { + logger.warn( + "There is no instance from service[name : {}], and then Dubbo Service[key : {}] will not be " + + "available , please make sure the further impact", + serviceName, subscribedURL.getServiceKey()); + } + return emptyList(); + } + + List subscribedURLs = cloneExportedURLs(subscribedURL, serviceInstances); + + // clear local service instances, help GC + validServiceInstances.clear(); + + return subscribedURLs; + } + + /** + * Clone the subscribed URLs based on the template URLs. + * @param subscribedURL the URL to be subscribed + * @param serviceInstances the list of {@link ServiceInstance service instances} + * @return non-null + */ + private List cloneExportedURLs(URL subscribedURL, + List serviceInstances) { + + List clonedExportedURLs = new LinkedList<>(); + + serviceInstances.forEach(serviceInstance -> { + + String host = serviceInstance.getHost(); + + getTemplateExportedURLs(subscribedURL, serviceInstances).stream() + .map(templateURL -> templateURL.removeParameter(TIMESTAMP_KEY)) + .map(templateURL -> templateURL.removeParameter(PID_KEY)) + .map(templateURL -> { + String protocol = templateURL.getProtocol(); + int port = repository.getDubboProtocolPort(serviceInstance, + protocol); + if (Objects.equals(templateURL.getHost(), host) + && Objects.equals(templateURL.getPort(), port)) { // use + // templateURL + // if + // equals + return templateURL; + } + + URLBuilder clonedURLBuilder = from(templateURL) // remove the + // parameters from + // the template + // URL + .setHost(host) // reset the host + .setPort(port); // reset the port + + return clonedURLBuilder.build(); + }).forEach(clonedExportedURLs::add); + }); + return clonedExportedURLs; + } + + private List getTemplateExportedURLs(URL subscribedURL, + List serviceInstances) { + + DubboMetadataService dubboMetadataService = getProxy(serviceInstances); + + List templateExportedURLs = emptyList(); + + if (dubboMetadataService != null) { + templateExportedURLs = getExportedURLs(dubboMetadataService, subscribedURL); + } + else { + if (logger.isWarnEnabled()) { + logger.warn( + "The metadata of Dubbo service[key : {}] still can't be found, it could effect the further " + + "Dubbo service invocation", + subscribedURL.getServiceKey()); + } + + } + + return templateExportedURLs; + } + + private DubboMetadataService getProxy(List serviceInstances) { + return dubboMetadataConfigServiceProxy.getProxy(serviceInstances); + } + + private List filter(Collection serviceInstances) { + return serviceInstances.stream().filter(this::isDubboServiceInstance) + .collect(Collectors.toList()); + } + + private boolean isDubboServiceInstance(ServiceInstance serviceInstance) { + Map metadata = serviceInstance.getMetadata(); + return metadata.containsKey(METADATA_SERVICE_URLS_PROPERTY_NAME); + } + + private Set getServices(URL url) { + Set subscribedServices = repository.getSubscribedServices(); + // TODO Add the filter feature + return subscribedServices; + } + + private void notifyAllSubscribedURLs(URL url, List subscribedURLs, + NotifyListener listener) { + + if (isEmpty(subscribedURLs)) { + // Add the EMPTY_PROTOCOL URL + subscribedURLs.add(emptyURL(url)); + + if (isDubboMetadataServiceURL(url)) { + // if meta service change, and serviceInstances is zero, will clean up + // information about this client + String serviceName = url.getParameter(GROUP_KEY); + repository.removeMetadataAndInitializedService(serviceName, url); + } + } + + if (logger.isDebugEnabled()) { + logger.debug("The subscribed URL[{}] will notify all URLs : {}", url, + subscribedURLs); + } + + // Notify all + listener.notify(subscribedURLs); + } + + private List getServiceInstances(Iterable serviceNames) { + return stream(serviceNames.spliterator(), false).map(this::getServiceInstances) + .flatMap(Collection::stream).collect(Collectors.toList()); + } + + private List getServiceInstances(String serviceName) { + return hasText(serviceName) ? doGetServiceInstances(serviceName) : emptyList(); + } + + private List doGetServiceInstances(String serviceName) { + List serviceInstances = emptyList(); + try { + serviceInstances = discoveryClient.getInstances(serviceName); + } + catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } + return serviceInstances; + } + + private String generateId(URL url) { + return url.getServiceKey(); + } + + private URL emptyURL(URL url) { + // issue : When the last service provider is closed, the client still periodically + // connects to the last provider.n + // fix https://github.com/alibaba/spring-cloud-alibaba/issues/1259 + return from(url).setProtocol(EMPTY_PROTOCOL).removeParameter(CATEGORY_KEY) + .build(); + } + + private List getExportedURLs(DubboMetadataService dubboMetadataService, + URL subscribedURL) { + String serviceInterface = subscribedURL.getServiceInterface(); + String group = subscribedURL.getParameter(GROUP_KEY); + String version = subscribedURL.getParameter(VERSION_KEY); + // The subscribed protocol may be null + String subscribedProtocol = subscribedURL.getParameter(PROTOCOL_KEY); + String exportedURLsJSON = dubboMetadataService.getExportedURLs(serviceInterface, + group, version); + return jsonUtils.toURLs(exportedURLsJSON).stream() + .filter(exportedURL -> subscribedProtocol == null + || subscribedProtocol.equalsIgnoreCase(exportedURL.getProtocol())) + .collect(Collectors.toList()); + } + + private void subscribeDubboMetadataServiceURLs(URL subscribedURL, + NotifyListener listener) { + + // Sync subscription + subscribeDubboMetadataServiceURLs(subscribedURL, listener, + getServiceName(subscribedURL)); + + // Sync subscription + if (containsProviderCategory(subscribedURL)) { + registerServiceInstancesChangedListener(subscribedURL, event -> { + + String sourceServiceName = event.getServiceName(); + String serviceName = getServiceName(subscribedURL); + + if (Objects.equals(sourceServiceName, serviceName)) { + subscribeDubboMetadataServiceURLs(subscribedURL, listener, + sourceServiceName); + } + }); + } + } + + private String getServiceName(URL subscribedURL) { + return subscribedURL.getParameter(GROUP_KEY); + } + + private void subscribeDubboMetadataServiceURLs(URL subscribedURL, + NotifyListener listener, String serviceName) { + + String serviceInterface = subscribedURL.getServiceInterface(); + String version = subscribedURL.getParameter(VERSION_KEY); + String protocol = subscribedURL.getParameter(PROTOCOL_KEY); + + List serviceInstances = getServiceInstances(serviceName); + + List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, + serviceInterface, version, protocol); + + notifyAllSubscribedURLs(subscribedURL, urls, listener); + } + + // private void subscribeDubboMetadataServiceURLs(URL subscribedURL, + // NotifyListener listener, Set serviceNames) { + // + // String serviceInterface = subscribedURL.getServiceInterface(); + // String version = subscribedURL.getParameter(VERSION_KEY); + // String protocol = subscribedURL.getParameter(PROTOCOL_KEY); + // + // List serviceInstances = getServiceInstances(serviceNames); + // + // List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, + // serviceInterface, version, protocol); + // + // notifyAllSubscribedURLs(subscribedURL, urls, listener); + // } + + private boolean containsProviderCategory(URL subscribedURL) { + String category = subscribedURL.getParameter(CATEGORY_KEY); + return category == null ? false : category.contains(PROVIDER); + } + + @Override + public final void doUnsubscribe(URL url, NotifyListener listener) { + // TODO + } + + @Override + public boolean isAvailable() { + return !discoveryClient.getServices().isEmpty(); + } + + protected boolean isAdminURL(URL url) { + return ADMIN_PROTOCOL.equals(url.getProtocol()); + } + + protected boolean isDubboMetadataServiceURL(URL url) { + return DUBBO_METADATA_SERVICE_CLASS_NAME.equals(url.getServiceInterface()); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistry.java index 3e4a1a5c2..07afb6fc1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistry.java @@ -31,7 +31,10 @@ import org.springframework.context.ConfigurableApplicationContext; * protocol is "spring-cloud". * * @author Mercy + * @deprecated It's a legacy and not recommended implementation, being replacing to be + * {@link DubboCloudRegistry} */ +@Deprecated public class SpringCloudRegistry extends AbstractSpringCloudRegistry { private final DubboServiceMetadataRepository dubboServiceMetadataRepository; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java index be13cb911..f8b7896dc 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.dubbo.registry; +import com.alibaba.cloud.dubbo.env.DubboCloudProperties; import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; @@ -23,11 +24,12 @@ import com.alibaba.cloud.dubbo.util.JSONUtils; import org.apache.dubbo.common.URL; import org.apache.dubbo.registry.Registry; import org.apache.dubbo.registry.RegistryFactory; +import org.apache.dubbo.registry.support.AbstractRegistryFactory; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.ConfigurableApplicationContext; -import static java.lang.System.getProperty; +import static com.alibaba.cloud.dubbo.util.DubboCloudConstants.SPRING_CLOUD_REGISTRY_PROPERTY_VALUE; /** * Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose @@ -37,7 +39,7 @@ import static java.lang.System.getProperty; * @see RegistryFactory * @see SpringCloudRegistry */ -public class SpringCloudRegistryFactory implements RegistryFactory { +public class SpringCloudRegistryFactory extends AbstractRegistryFactory { /** * Spring Cloud Protocol. @@ -49,10 +51,6 @@ public class SpringCloudRegistryFactory implements RegistryFactory { */ public static String ADDRESS = "localhost"; - private static String SERVICES_LOOKUP_SCHEDULER_THREAD_NAME_PREFIX = getProperty( - "dubbo.services.lookup.scheduler.thread.name.prefix ", - "dubbo-services-lookup-"); - private static ConfigurableApplicationContext applicationContext; private DiscoveryClient discoveryClient; @@ -65,8 +63,6 @@ public class SpringCloudRegistryFactory implements RegistryFactory { private DubboGenericServiceFactory dubboGenericServiceFactory; - private volatile boolean initialized = false; - public SpringCloudRegistryFactory() { } @@ -76,9 +72,6 @@ public class SpringCloudRegistryFactory implements RegistryFactory { } protected void init() { - if (initialized || applicationContext == null) { - return; - } this.discoveryClient = applicationContext.getBean(DiscoveryClient.class); this.dubboServiceMetadataRepository = applicationContext .getBean(DubboServiceMetadataRepository.class); @@ -90,11 +83,28 @@ public class SpringCloudRegistryFactory implements RegistryFactory { } @Override - public Registry getRegistry(URL url) { + public Registry createRegistry(URL url) { init(); - return new SpringCloudRegistry(url, discoveryClient, - dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy, - jsonUtils, dubboGenericServiceFactory, applicationContext); + + DubboCloudProperties dubboCloudProperties = applicationContext + .getBean(DubboCloudProperties.class); + + Registry registry = null; + + switch (dubboCloudProperties.getRegistryType()) { + case SPRING_CLOUD_REGISTRY_PROPERTY_VALUE: + registry = new SpringCloudRegistry(url, discoveryClient, + dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy, + jsonUtils, dubboGenericServiceFactory, applicationContext); + break; + default: + registry = new DubboCloudRegistry(url, discoveryClient, + dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy, + jsonUtils, dubboGenericServiceFactory, applicationContext); + break; + } + + return registry; } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java index 9ddee6b3b..47265ad50 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java @@ -95,10 +95,9 @@ public class DubboGenericServiceFactory { private ReferenceBean build(String interfaceName, String version, String group, Map dubboTranslatedAttributes) { - Integer key = Objects.hash(interfaceName, version, group, - dubboTranslatedAttributes); + String key = createKey(interfaceName, version, group, dubboTranslatedAttributes); - return cache.computeIfAbsent(group + key, k -> { + return cache.computeIfAbsent(key, k -> { ReferenceBean referenceBean = new ReferenceBean<>(); referenceBean.setGeneric(true); referenceBean.setInterface(interfaceName); @@ -110,6 +109,12 @@ public class DubboGenericServiceFactory { }); } + private String createKey(String interfaceName, String version, String group, + Map dubboTranslatedAttributes) { + return group + "#" + + Objects.hash(interfaceName, version, group, dubboTranslatedAttributes); + } + private void bindReferenceBean(ReferenceBean referenceBean, Map dubboTranslatedAttributes) { DataBinder dataBinder = new DataBinder(referenceBean); @@ -127,7 +132,7 @@ public class DubboGenericServiceFactory { // Trim all whitespace String content = StringUtils.trimAllWhitespace(text); if (!StringUtils.hasText(content)) { // No content , ignore - // directly + // directly return; } // replace "=" to "," @@ -155,7 +160,7 @@ public class DubboGenericServiceFactory { cache.clear(); } - public synchronized void destroy(String serviceName) { + public void destroy(String serviceName) { Set removeGroups = new HashSet<>(cache.keySet()); for (String key : removeGroups) { if (key.contains(serviceName)) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java index 359ee5e07..ff70950d6 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java @@ -16,13 +16,25 @@ package com.alibaba.cloud.dubbo.service; +import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import com.alibaba.cloud.dubbo.metadata.repository.ServiceInstanceSelector; +import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; +import org.apache.dubbo.common.URL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.DisposableBean; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; import static java.lang.reflect.Proxy.newProxyInstance; +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; /** * The proxy of {@link DubboMetadataService}. @@ -31,34 +43,110 @@ import static java.lang.reflect.Proxy.newProxyInstance; */ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, DisposableBean { + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final DubboGenericServiceFactory dubboGenericServiceFactory; + private final DubboMetadataUtils dubboMetadataUtils; + + private final ServiceInstanceSelector serviceInstanceSelector; + + private final DiscoveryClient discoveryClient; + private final Map dubboMetadataServiceCache = new ConcurrentHashMap<>(); private ClassLoader classLoader; public DubboMetadataServiceProxy( - DubboGenericServiceFactory dubboGenericServiceFactory) { + DubboGenericServiceFactory dubboGenericServiceFactory, + DubboMetadataUtils dubboMetadataUtils, + ServiceInstanceSelector serviceInstanceSelector, + DiscoveryClient discoveryClient) { this.dubboGenericServiceFactory = dubboGenericServiceFactory; + this.dubboMetadataUtils = dubboMetadataUtils; + this.serviceInstanceSelector = serviceInstanceSelector; + this.discoveryClient = discoveryClient; } /** - * Initializes {@link DubboMetadataService}'s Proxy. + * Remove {@link DubboMetadataService}'s Proxy by service name. * @param serviceName the service name - * @param version the service version + */ + public void removeProxy(String serviceName) { + dubboMetadataServiceCache.remove(serviceName); + dubboGenericServiceFactory.destroy(serviceName); + } + + /** + * Get the proxy of {@link DubboMetadataService} if possible. + * @param serviceInstances the instances of {@link DubboMetadataService} + * @return null if initialization can't be done + */ + public DubboMetadataService getProxy(List serviceInstances) { + + DubboMetadataService dubboMetadataService = null; + + // attempt to get the proxy of DubboMetadataService in maximum times + int attempts = serviceInstances.size(); + + for (int i = 0; i < attempts; i++) { + Optional serviceInstance = select(serviceInstances); + + if (serviceInstance.isPresent()) { + + List dubboMetadataServiceURLs = getDubboMetadataServiceURLs( + serviceInstance.get()); + + for (URL dubboMetadataServiceURL : dubboMetadataServiceURLs) { + dubboMetadataService = createProxyIfAbsent(dubboMetadataServiceURL); + if (dubboMetadataService != null) { + return dubboMetadataService; + } + } + } + } + + return dubboMetadataService; + } + + /** + * Is the {@link DubboMetadataService}'s Proxy initialized or not. + * @param serviceName the service name + * @return true if initialized , or return false + */ + public boolean isInitialized(String serviceName) { + return dubboMetadataServiceCache.containsKey(serviceName); + } + + /** + * Create a {@link DubboMetadataService}'s Proxy If abstract. + * @param dubboMetadataServiceURL the {@link URL} of {@link DubboMetadataService} * @return a {@link DubboMetadataService} proxy */ - public DubboMetadataService initProxy(String serviceName, String version) { - return dubboMetadataServiceCache.computeIfAbsent(serviceName, - name -> newProxy(name, version)); + private DubboMetadataService createProxyIfAbsent(URL dubboMetadataServiceURL) { + String serviceName = dubboMetadataServiceURL.getParameter(APPLICATION_KEY); + String version = dubboMetadataServiceURL.getParameter(VERSION_KEY); + // Initialize DubboMetadataService with right version + return createProxyIfAbsent(serviceName, version); } /** - * Remove {@link DubboMetadataService}'s Proxy by service name. + * Initializes {@link DubboMetadataService}'s Proxy. * @param serviceName the service name + * @param version the service version + * @return a {@link DubboMetadataService} proxy */ - public void removeProxy(String serviceName) { - dubboMetadataServiceCache.remove(serviceName); + private DubboMetadataService createProxyIfAbsent(String serviceName, String version) { + return dubboMetadataServiceCache.computeIfAbsent(serviceName, + name -> createProxy(name, version)); + } + + private Optional select(List serviceInstances) { + return serviceInstanceSelector.select(serviceInstances); + } + + private List getDubboMetadataServiceURLs(ServiceInstance serviceInstance) { + return dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstance); } /** @@ -68,7 +156,12 @@ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, Disposab * @return a {@link DubboMetadataService} proxy */ public DubboMetadataService getProxy(String serviceName) { - return dubboMetadataServiceCache.get(serviceName); + return dubboMetadataServiceCache.getOrDefault(serviceName, + getProxy0(serviceName)); + } + + private DubboMetadataService getProxy0(String serviceName) { + return getProxy(discoveryClient.getInstances(serviceName)); } @Override @@ -88,7 +181,14 @@ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, Disposab * @param version the service version * @return a {@link DubboMetadataService} proxy */ - protected DubboMetadataService newProxy(String serviceName, String version) { + protected DubboMetadataService createProxy(String serviceName, String version) { + + if (logger.isInfoEnabled()) { + logger.info( + "The metadata of Dubbo service[name : {}] is about to be initialized", + serviceName); + } + return (DubboMetadataService) newProxyInstance(classLoader, new Class[] { DubboMetadataService.class }, new DubboMetadataServiceInvocationHandler(serviceName, version, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboCloudConstants.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboCloudConstants.java new file mode 100644 index 000000000..346416976 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboCloudConstants.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed 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 + * + * https://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 com.alibaba.cloud.dubbo.util; + +/** + * The constants for Dubbo Spring Cloud. + * + * @author Mercy + */ +public final class DubboCloudConstants { + + /** + * The property prefix of Configuration. + */ + public static final String CONFIG_PROPERTY_PREFIX = "dubbo.cloud"; + + /** + * The property name of Registry type. + */ + public static final String REGISTRY_TYPE_PROPERTY_NAME = CONFIG_PROPERTY_PREFIX + + ".registry-type"; + + /** + * The property value of Spring Cloud Registry. + */ + public static final String SPRING_CLOUD_REGISTRY_PROPERTY_VALUE = "spring-cloud"; + + /** + * The property value of Dubbo Cloud Registry. + */ + public static final String DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE = "dubbo-cloud"; + + private DubboCloudConstants() { + throw new AssertionError("Must not instantiate constant utility class"); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java new file mode 100644 index 000000000..af3c59460 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java @@ -0,0 +1,118 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed 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 + * + * https://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 com.alibaba.cloud.dubbo.util; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.alibaba.cloud.dubbo.service.DubboMetadataService; +import org.apache.dubbo.common.URL; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.core.env.Environment; + +import static java.lang.String.format; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME; +import static org.springframework.util.StringUtils.hasText; + +/** + * The utilities class of Dubbo Metadata. + * + * @author Mercy + */ +public class DubboMetadataUtils { + + /** + * The {@link String#format(String, Object...) pattern} of dubbo protocols port. + */ + public static final String DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN = "dubbo.protocols.%s.port"; + + private final JSONUtils jsonUtils; + + private final Environment environment; + + private final String currentApplicationName; + + public DubboMetadataUtils(JSONUtils jsonUtils, Environment environment) { + this.jsonUtils = jsonUtils; + this.environment = environment; + this.currentApplicationName = environment.getProperty("spring.application.name", + environment.getProperty("dubbo.application.name", "application")); + } + + /** + * Get the current application name. + * @return non-null + */ + public String getCurrentApplicationName() { + return currentApplicationName; + } + + /** + * Get the {@link URL urls} that {@link DubboMetadataService} exported by the + * specified {@link ServiceInstance}. + * @param serviceInstance {@link ServiceInstance} + * @return the mutable {@link URL urls} + */ + public List getDubboMetadataServiceURLs(ServiceInstance serviceInstance) { + Map metadata = serviceInstance.getMetadata(); + String dubboURLsJSON = metadata.get(METADATA_SERVICE_URLS_PROPERTY_NAME); + return jsonUtils.toURLs(dubboURLsJSON); + } + + /** + * Get the {@link URL urls} that {@link DubboMetadataService} exported by the + * specified {@link ServiceInstance ServiceInstances}. + * @param serviceInstances the list of {@link ServiceInstance ServiceInstances} + * @param serviceInterface the interface name of Dubbo service + * @param version the version of Dubbo service + * @param protocol the protocol that Dubbo Service exports + * @return the mutable {@link URL urls} + */ + public List getDubboMetadataServiceURLs(List serviceInstances, + String serviceInterface, String version, String protocol) { + return serviceInstances.stream().map(this::getDubboMetadataServiceURLs) + .flatMap(List::stream) + .filter(url -> protocol == null + || Objects.equals(protocol, url.getProtocol())) + .filter(url -> Objects.equals(serviceInterface, + url.getServiceInterface())) + .filter(url -> Objects.equals(version, url.getParameter(VERSION_KEY))) + .collect(Collectors.toList()); + } + + /** + * Get the property name of Dubbo Protocol. + * @param protocol Dubbo Protocol + * @return non-null + */ + public String getDubboProtocolPropertyName(String protocol) { + return format(DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN, protocol); + } + + public Integer getDubboProtocolPort(ServiceInstance serviceInstance, + String protocol) { + String protocolProperty = getDubboProtocolPropertyName(protocol); + Map metadata = serviceInstance.getMetadata(); + String protocolPort = metadata.get(protocolProperty); + return hasText(protocolPort) ? Integer.valueOf(protocolPort) : null; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/default/actuator-endpoints.properties b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/default/actuator-endpoints.properties index 19c4bb448..04d894e73 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/default/actuator-endpoints.properties +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/default/actuator-endpoints.properties @@ -1,7 +1,6 @@ # Dubbo Endpoints Default Properties is loaded by @PropertySource with low order, # Set enabled for Dubbo Endpoints -management.endpoint.dubborestmetadata.enabled = true - +management.endpoint.dubborestmetadata.enabled=true # "management.endpoints.web.base-path" should not be configured in this file # Re-defines path-mapping of Dubbo Web Endpoints -management.endpoints.web.path-mapping.dubborestmetadata = dubbo/rest/metadata +management.endpoints.web.path-mapping.dubborestmetadata=dubbo/rest/metadata diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/spring.factories index 5969971e8..06c5b5921 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/spring.factories @@ -6,12 +6,9 @@ com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationNonWebApplicationA com.alibaba.cloud.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\ com.alibaba.cloud.dubbo.autoconfigure.DubboServiceAutoConfiguration,\ com.alibaba.cloud.dubbo.autoconfigure.DubboServiceDiscoveryAutoConfiguration - org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\ com.alibaba.cloud.dubbo.actuate.DubboMetadataEndpointAutoConfiguration - org.springframework.context.ApplicationContextInitializer=\ com.alibaba.cloud.dubbo.context.DubboServiceRegistrationApplicationContextInitializer - org.springframework.boot.env.EnvironmentPostProcessor=\ com.alibaba.cloud.dubbo.env.DubboNonWebApplicationEnvironmentPostProcessor \ No newline at end of file