mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge pull request #514 from mercyblitz/master
Refactor Dubbo Service registration
This commit is contained in:
commit
5df1d76945
@ -14,7 +14,8 @@
|
|||||||
<name>Spring Cloud Alibaba Dubbo</name>
|
<name>Spring Cloud Alibaba Dubbo</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<dubbo.version>2.7.0</dubbo.version>
|
<dubbo.version>2.7.1</dubbo.version>
|
||||||
|
<dubbo-spring-boot.version>2.7.0</dubbo-spring-boot.version>
|
||||||
<spring-cloud-zookeeper.version>2.1.0.RELEASE</spring-cloud-zookeeper.version>
|
<spring-cloud-zookeeper.version>2.1.0.RELEASE</spring-cloud-zookeeper.version>
|
||||||
<spring-cloud-consul.version>2.1.0.RELEASE</spring-cloud-consul.version>
|
<spring-cloud-consul.version>2.1.0.RELEASE</spring-cloud-consul.version>
|
||||||
<curator.version>4.0.1</curator.version>
|
<curator.version>4.0.1</curator.version>
|
||||||
@ -178,7 +179,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||||
<version>${dubbo.version}</version>
|
<version>${dubbo-spring-boot.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Netty -->
|
<!-- Netty -->
|
||||||
|
@ -17,20 +17,28 @@
|
|||||||
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
|
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
|
||||||
|
|
||||||
import org.apache.dubbo.config.ProtocolConfig;
|
import org.apache.dubbo.config.ProtocolConfig;
|
||||||
|
import org.apache.dubbo.config.spring.ServiceBean;
|
||||||
|
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
|
||||||
|
|
||||||
import feign.Contract;
|
import feign.Contract;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.DubboProtocolConfigSupplier;
|
import org.springframework.cloud.alibaba.dubbo.metadata.DubboProtocolConfigSupplier;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver;
|
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
|
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceExporter;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
|
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.util.JSONUtils;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@ -41,9 +49,21 @@ import java.util.function.Supplier;
|
|||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import({DubboServiceMetadataRepository.class, PublishingDubboMetadataConfigService.class})
|
@Import({DubboServiceMetadataRepository.class,
|
||||||
|
PublishingDubboMetadataConfigService.class,
|
||||||
|
DubboMetadataConfigServiceExporter.class,
|
||||||
|
JSONUtils.class})
|
||||||
public class DubboMetadataAutoConfiguration {
|
public class DubboMetadataAutoConfiguration {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MetadataResolver metadataResolver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DubboMetadataConfigServiceExporter dubboMetadataConfigServiceExporter;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public MetadataResolver metadataJsonResolver(ObjectProvider<Contract> contract) {
|
public MetadataResolver metadataJsonResolver(ObjectProvider<Contract> contract) {
|
||||||
@ -51,7 +71,7 @@ public class DubboMetadataAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Supplier<ProtocolConfig> dubboProtocolConfigSupplier(Collection<ProtocolConfig> protocols) {
|
public Supplier<ProtocolConfig> dubboProtocolConfigSupplier(ObjectProvider<Collection<ProtocolConfig>> protocols) {
|
||||||
return new DubboProtocolConfigSupplier(protocols);
|
return new DubboProtocolConfigSupplier(protocols);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,4 +80,35 @@ public class DubboMetadataAutoConfiguration {
|
|||||||
public DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy(DubboGenericServiceFactory factory) {
|
public DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy(DubboGenericServiceFactory factory) {
|
||||||
return new DubboMetadataConfigServiceProxy(factory);
|
return new DubboMetadataConfigServiceProxy(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Event-Handling
|
||||||
|
|
||||||
|
@EventListener(ServiceBeanExportedEvent.class)
|
||||||
|
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
|
||||||
|
ServiceBean serviceBean = event.getServiceBean();
|
||||||
|
publishServiceRestMetadata(serviceBean);
|
||||||
|
exportDubboMetadataConfigService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener(ApplicationFailedEvent.class)
|
||||||
|
public void onApplicationFailed() {
|
||||||
|
unExportDubboMetadataConfigService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener(ContextClosedEvent.class)
|
||||||
|
public void onContextClosed() {
|
||||||
|
dubboMetadataConfigServiceExporter.unexport();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void publishServiceRestMetadata(ServiceBean serviceBean) {
|
||||||
|
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportDubboMetadataConfigService() {
|
||||||
|
dubboMetadataConfigServiceExporter.export();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unExportDubboMetadataConfigService() {
|
||||||
|
dubboMetadataConfigServiceExporter.unexport();
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,212 +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.springframework.cloud.alibaba.dubbo.autoconfigure;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.config.ApplicationConfig;
|
|
||||||
import org.apache.dubbo.config.ProtocolConfig;
|
|
||||||
import org.apache.dubbo.config.ServiceConfig;
|
|
||||||
import org.apache.dubbo.config.spring.ServiceBean;
|
|
||||||
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.ApplicationRunner;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
|
|
||||||
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigService;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
|
|
||||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.event.ContextClosedEvent;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Auto-Configuration class for Dubbo metadata {@link EventListener event handling}.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
@AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class})
|
|
||||||
@Configuration
|
|
||||||
public class DubboMetadataEventHandlingAutoConfiguration {
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MetadataResolver metadataResolver;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ApplicationConfig applicationConfig;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private Supplier<ProtocolConfig> protocolConfigSupplier;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigurableApplicationContext context;
|
|
||||||
|
|
||||||
@Value("${spring.application.name:application}")
|
|
||||||
private String currentApplicationName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ServiceConfig of DubboMetadataConfigService to be exported, can be nullable.
|
|
||||||
*/
|
|
||||||
private ServiceConfig<DubboMetadataConfigService> serviceConfig;
|
|
||||||
|
|
||||||
private ServiceInstance restServiceInstance;
|
|
||||||
|
|
||||||
@EventListener(ServiceBeanExportedEvent.class)
|
|
||||||
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
|
|
||||||
ServiceBean serviceBean = event.getServiceBean();
|
|
||||||
publishServiceRestMetadata(serviceBean);
|
|
||||||
setRestServiceInstance(serviceBean);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setRestServiceInstance(ServiceBean serviceBean) {
|
|
||||||
List<URL> urls = serviceBean.getExportedUrls();
|
|
||||||
urls.stream()
|
|
||||||
.filter(url -> "rest".equalsIgnoreCase(url.getProtocol()))
|
|
||||||
.forEach(url -> {
|
|
||||||
String host = url.getIp();
|
|
||||||
int port = url.getPort();
|
|
||||||
|
|
||||||
if (restServiceInstance == null) {
|
|
||||||
String instanceId = currentApplicationName + "-" + host + ":" + port;
|
|
||||||
this.restServiceInstance = new DefaultServiceInstance(instanceId, currentApplicationName,
|
|
||||||
host, port, false, new HashMap<>());
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!host.equals(restServiceInstance.getHost())) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logger.warn("Current application[{}] host is not consistent, expected: {}, actual: {}",
|
|
||||||
currentApplicationName, restServiceInstance.getHost(), host);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port != restServiceInstance.getPort()) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logger.warn("Current application[{}] port is not consistent, expected: {}, actual: {}",
|
|
||||||
currentApplicationName, restServiceInstance.getPort(), port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener(ApplicationReadyEvent.class)
|
|
||||||
public void onApplicationReady() {
|
|
||||||
exportDubboMetadataConfigService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener(ApplicationFailedEvent.class)
|
|
||||||
public void onApplicationFailed() {
|
|
||||||
unexportDubboMetadataConfigService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener(ContextClosedEvent.class)
|
|
||||||
public void onContextClosed() {
|
|
||||||
unexportDubboMetadataConfigService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ConditionalOnNotWebApplication
|
|
||||||
@Bean
|
|
||||||
public ApplicationRunner applicationRunner() {
|
|
||||||
return args -> {
|
|
||||||
|
|
||||||
if (restServiceInstance == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// From RegistrationFactoryProvider
|
|
||||||
RegistrationFactory registrationFactory = context.getBean(RegistrationFactory.class);
|
|
||||||
|
|
||||||
ServiceRegistry<Registration> serviceRegistry = context.getBean(ServiceRegistry.class);
|
|
||||||
|
|
||||||
Registration registration = context.getBean(Registration.class);
|
|
||||||
|
|
||||||
restServiceInstance.getMetadata().putAll(registration.getMetadata());
|
|
||||||
|
|
||||||
serviceRegistry.register(registrationFactory.create(restServiceInstance, context));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void publishServiceRestMetadata(ServiceBean serviceBean) {
|
|
||||||
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void exportDubboMetadataConfigService() {
|
|
||||||
|
|
||||||
if (serviceConfig != null && serviceConfig.isExported()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(dubboMetadataConfigService.getServiceRestMetadata())) {
|
|
||||||
// If there is no REST metadata, DubboMetadataConfigService will not be exported.
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("There is no REST metadata, the Dubbo service[{}] will not be exported.",
|
|
||||||
dubboMetadataConfigService.getClass().getName());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceConfig = new ServiceConfig<>();
|
|
||||||
|
|
||||||
serviceConfig.setInterface(DubboMetadataConfigService.class);
|
|
||||||
// Use current Spring application name as the Dubbo Service version
|
|
||||||
serviceConfig.setVersion(currentApplicationName);
|
|
||||||
serviceConfig.setRef(dubboMetadataConfigService);
|
|
||||||
serviceConfig.setApplication(applicationConfig);
|
|
||||||
serviceConfig.setProtocol(protocolConfigSupplier.get());
|
|
||||||
|
|
||||||
serviceConfig.export();
|
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("The Dubbo service[{}] has been exported.", serviceConfig.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unexportDubboMetadataConfigService() {
|
|
||||||
|
|
||||||
if (serviceConfig == null || serviceConfig.isUnexported()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceConfig.unexport();
|
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("The Dubbo service[{}] has been unexported.", serviceConfig.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,18 +18,15 @@ package org.springframework.cloud.alibaba.dubbo.autoconfigure;
|
|||||||
|
|
||||||
import org.apache.dubbo.common.utils.Assert;
|
import org.apache.dubbo.common.utils.Assert;
|
||||||
import org.apache.dubbo.config.spring.util.PropertySourcesUtils;
|
import org.apache.dubbo.config.spring.util.PropertySourcesUtils;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactoryProvider;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.handler.StandardDubboRegistryServiceIdHandler;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.parameter.PathVariableServiceParameterResolver;
|
import org.springframework.cloud.alibaba.dubbo.service.parameter.PathVariableServiceParameterResolver;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestBodyServiceParameterResolver;
|
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestBodyServiceParameterResolver;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestHeaderServiceParameterResolver;
|
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestHeaderServiceParameterResolver;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestParamServiceParameterResolver;
|
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestParamServiceParameterResolver;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
@ -71,17 +68,6 @@ public class DubboServiceAutoConfiguration {
|
|||||||
static class ParameterResolversConfiguration {
|
static class ParameterResolversConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public DubboRegistryServiceIdHandler dubboRegistryServiceIdHandler(ConfigurableApplicationContext context) {
|
|
||||||
return new StandardDubboRegistryServiceIdHandler(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RegistrationFactoryProvider registrationFactoryProvider() {
|
|
||||||
return new RegistrationFactoryProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bugfix code for an issue : https://github.com/apache/incubator-dubbo-spring-boot-project/issues/459
|
* Bugfix code for an issue : https://github.com/apache/incubator-dubbo-spring-boot-project/issues/459
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* 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.springframework.cloud.alibaba.dubbo.autoconfigure;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.config.spring.ServiceBean;
|
||||||
|
|
||||||
|
import com.ecwid.consul.v1.agent.model.NewService;
|
||||||
|
import com.netflix.appinfo.InstanceInfo;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.registry.DubboServiceRegistrationEventPublishingAspect;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstancePreRegisteredEvent;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.util.JSONUtils;
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
|
||||||
|
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration;
|
||||||
|
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
|
||||||
|
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry;
|
||||||
|
import org.springframework.context.SmartLifecycle;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_CONFIGURATION_CLASS_NAME;
|
||||||
|
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_AUTO_CONFIGURATION_CLASS_NAME;
|
||||||
|
import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.DUBBO_URLS_METADATA_PROPERTY_NAME;
|
||||||
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dubbo Service Registration Auto-{@link Configuration}
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Import({DubboServiceRegistrationEventPublishingAspect.class})
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||||
|
@AutoConfigureAfter(name = {
|
||||||
|
EUREKA_AUTO_CONFIGURATION_CLASS_NAME,
|
||||||
|
CONSUL_AUTO_CONFIGURATION_CLASS_NAME,
|
||||||
|
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration"
|
||||||
|
}, value = {
|
||||||
|
DubboMetadataAutoConfiguration.class
|
||||||
|
})
|
||||||
|
public class DubboServiceRegistrationAutoConfiguration {
|
||||||
|
|
||||||
|
public static final String EUREKA_AUTO_CONFIGURATION_CLASS_NAME =
|
||||||
|
"org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration";
|
||||||
|
|
||||||
|
public static final String CONSUL_AUTO_CONFIGURATION_CLASS_NAME =
|
||||||
|
"org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration";
|
||||||
|
|
||||||
|
public static final String CONSUL_AUTO_REGISTRATION_CLASS_NAME =
|
||||||
|
"org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration";
|
||||||
|
|
||||||
|
public static final String ZOOKEEPER_AUTO_CONFIGURATION_CLASS_NAME =
|
||||||
|
"org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistrationAutoConfiguration";
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(DubboServiceRegistrationAutoConfiguration.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DubboServiceMetadataRepository dubboServiceMetadataRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JSONUtils jsonUtils;
|
||||||
|
|
||||||
|
@EventListener(ServiceInstancePreRegisteredEvent.class)
|
||||||
|
public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
|
||||||
|
Registration registration = event.getSource();
|
||||||
|
attachURLsIntoMetadata(registration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBean(name = EUREKA_AUTO_CONFIGURATION_CLASS_NAME)
|
||||||
|
@Aspect
|
||||||
|
class EurekaConfiguration implements SmartInitializingSingleton {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectProvider<Collection<ServiceBean>> serviceBeans;
|
||||||
|
|
||||||
|
@EventListener(ServiceInstancePreRegisteredEvent.class)
|
||||||
|
public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
|
||||||
|
Registration registration = event.getSource();
|
||||||
|
EurekaRegistration eurekaRegistration = EurekaRegistration.class.cast(registration);
|
||||||
|
InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager().getInfo();
|
||||||
|
attachURLsIntoMetadata(instanceInfo.getMetadata());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link EurekaServiceRegistry} will register current {@link ServiceInstance service instance} on
|
||||||
|
* {@link EurekaAutoServiceRegistration#start()} execution(in {@link SmartLifecycle#start() start phase}),
|
||||||
|
* thus this method must {@link ServiceBean#export() export} all {@link ServiceBean ServiceBeans} in advance.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterSingletonsInstantiated() {
|
||||||
|
Collection<ServiceBean> serviceBeans = this.serviceBeans.getIfAvailable();
|
||||||
|
if (!isEmpty(serviceBeans)) {
|
||||||
|
serviceBeans.forEach(ServiceBean::export);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBean(name = CONSUL_AUTO_CONFIGURATION_CLASS_NAME)
|
||||||
|
@AutoConfigureOrder
|
||||||
|
class ConsulConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the pre-registered event of {@link ServiceInstance} for Consul
|
||||||
|
*
|
||||||
|
* @param event {@link ServiceInstancePreRegisteredEvent}
|
||||||
|
*/
|
||||||
|
@EventListener(ServiceInstancePreRegisteredEvent.class)
|
||||||
|
public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
|
||||||
|
Registration registration = event.getSource();
|
||||||
|
Class<?> registrationClass = AopUtils.getTargetClass(registration);
|
||||||
|
String registrationClassName = registrationClass.getName();
|
||||||
|
if (CONSUL_AUTO_REGISTRATION_CLASS_NAME.equalsIgnoreCase(registrationClassName)) {
|
||||||
|
ConsulRegistration consulRegistration = (ConsulRegistration) registration;
|
||||||
|
attachURLsIntoMetadata(consulRegistration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) {
|
||||||
|
NewService newService = consulRegistration.getService();
|
||||||
|
String dubboURLsJson = getDubboURLsJSON();
|
||||||
|
if (StringUtils.hasText(dubboURLsJson)) {
|
||||||
|
List<String> tags = newService.getTags();
|
||||||
|
tags.add(DUBBO_URLS_METADATA_PROPERTY_NAME + "=" + dubboURLsJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachURLsIntoMetadata(Registration registration) {
|
||||||
|
if (registration == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (registration) {
|
||||||
|
Map<String, String> metadata = registration.getMetadata();
|
||||||
|
attachURLsIntoMetadata(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachURLsIntoMetadata(Map<String, String> metadata) {
|
||||||
|
String dubboURLsJson = getDubboURLsJSON();
|
||||||
|
if (StringUtils.hasText(dubboURLsJson)) {
|
||||||
|
metadata.put(DUBBO_URLS_METADATA_PROPERTY_NAME, dubboURLsJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDubboURLsJSON() {
|
||||||
|
Collection<URL> urls = dubboServiceMetadataRepository.getRegisteredUrls();
|
||||||
|
if (CollectionUtils.isEmpty(urls)) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("There is no registered URL to attach into metadata.");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return jsonUtils.toJSON(urls.stream().map(URL::toFullString).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* 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.springframework.cloud.alibaba.dubbo.autoconfigure;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.config.spring.ServiceBean;
|
||||||
|
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
|
||||||
|
|
||||||
|
import com.ecwid.consul.v1.agent.model.NewService;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstancePreRegisteredEvent;
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
|
||||||
|
import org.springframework.cloud.zookeeper.serviceregistry.ServiceInstanceRegistration;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_CONFIGURATION_CLASS_NAME;
|
||||||
|
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.ZOOKEEPER_AUTO_CONFIGURATION_CLASS_NAME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dubbo Service Registration Auto-{@link Configuration} for Non-Web application
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnNotWebApplication
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||||
|
@AutoConfigureAfter(DubboServiceRegistrationAutoConfiguration.class)
|
||||||
|
@Aspect
|
||||||
|
public class DubboServiceRegistrationNonWebApplicationAutoConfiguration {
|
||||||
|
|
||||||
|
private static final String REST_PROTOCOL = "rest";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ServiceRegistry serviceRegistry;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Registration registration;
|
||||||
|
|
||||||
|
private volatile Integer webPort = null;
|
||||||
|
|
||||||
|
private volatile boolean registered = false;
|
||||||
|
|
||||||
|
@Around("execution(* org.springframework.cloud.client.serviceregistry.Registration.getPort())")
|
||||||
|
public Object getPort(ProceedingJoinPoint pjp) throws Throwable {
|
||||||
|
return webPort != null ? webPort : pjp.proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener(ServiceBeanExportedEvent.class)
|
||||||
|
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
|
||||||
|
setWebPort(event.getServiceBean());
|
||||||
|
register();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register() {
|
||||||
|
if (registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
serviceRegistry.register(registration);
|
||||||
|
registered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set web port from {@link ServiceBean#getExportedUrls() exported URLs} if "rest" protocol is present.
|
||||||
|
*
|
||||||
|
* @param serviceBean {@link ServiceBean}
|
||||||
|
*/
|
||||||
|
private void setWebPort(ServiceBean serviceBean) {
|
||||||
|
if (webPort == null) {
|
||||||
|
List<URL> urls = serviceBean.getExportedUrls();
|
||||||
|
urls.stream()
|
||||||
|
.filter(url -> REST_PROTOCOL.equalsIgnoreCase(url.getProtocol()))
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(url -> {
|
||||||
|
webPort = url.getPort();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBean(name = ZOOKEEPER_AUTO_CONFIGURATION_CLASS_NAME)
|
||||||
|
class ZookeeperConfiguration implements SmartInitializingSingleton {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ServiceInstanceRegistration registration;
|
||||||
|
|
||||||
|
@EventListener(ServiceInstancePreRegisteredEvent.class)
|
||||||
|
public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
|
||||||
|
registration.setPort(webPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterSingletonsInstantiated() {
|
||||||
|
// invoke getServiceInstance() method to trigger the ServiceInstance building before register
|
||||||
|
registration.getServiceInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBean(name = CONSUL_AUTO_CONFIGURATION_CLASS_NAME)
|
||||||
|
class ConsulConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the pre-registered event of {@link ServiceInstance} for Consul
|
||||||
|
*
|
||||||
|
* @param event {@link ServiceInstancePreRegisteredEvent}
|
||||||
|
*/
|
||||||
|
@EventListener(ServiceInstancePreRegisteredEvent.class)
|
||||||
|
public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
|
||||||
|
Registration registration = event.getSource();
|
||||||
|
ConsulAutoRegistration consulRegistration = (ConsulAutoRegistration) registration;
|
||||||
|
setPort(consulRegistration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set port on Non-Web Application
|
||||||
|
*
|
||||||
|
* @param consulRegistration {@link ConsulRegistration}
|
||||||
|
*/
|
||||||
|
private void setPort(ConsulAutoRegistration consulRegistration) {
|
||||||
|
int port = consulRegistration.getPort();
|
||||||
|
NewService newService = consulRegistration.getService();
|
||||||
|
if (newService.getPort() == null) {
|
||||||
|
newService.setPort(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,7 @@ import org.apache.dubbo.rpc.service.GenericException;
|
|||||||
import org.apache.dubbo.rpc.service.GenericService;
|
import org.apache.dubbo.rpc.service.GenericService;
|
||||||
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.http.MutableHttpServerRequest;
|
import org.springframework.cloud.alibaba.dubbo.http.MutableHttpServerRequest;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.DubboRestServiceMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||||
@ -87,16 +87,16 @@ public class DubboTransporterInterceptor implements ClientHttpRequestInterceptor
|
|||||||
|
|
||||||
RequestMetadata clientMetadata = buildRequestMetadata(request);
|
RequestMetadata clientMetadata = buildRequestMetadata(request);
|
||||||
|
|
||||||
DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, clientMetadata);
|
DubboRestServiceMetadata metadata = repository.get(serviceName, clientMetadata);
|
||||||
|
|
||||||
if (dubboServiceMetadata == null) {
|
if (metadata == null) {
|
||||||
// if DubboServiceMetadata is not found, executes next
|
// if DubboServiceMetadata is not found, executes next
|
||||||
return execution.execute(request, body);
|
return execution.execute(request, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
RestMethodMetadata dubboRestMethodMetadata = dubboServiceMetadata.getRestMethodMetadata();
|
RestMethodMetadata dubboRestMethodMetadata = metadata.getRestMethodMetadata();
|
||||||
|
|
||||||
GenericService genericService = serviceFactory.create(dubboServiceMetadata, dubboTranslatedAttributes);
|
GenericService genericService = serviceFactory.create(metadata, dubboTranslatedAttributes);
|
||||||
|
|
||||||
MutableHttpServerRequest httpServerRequest = new MutableHttpServerRequest(request, body);
|
MutableHttpServerRequest httpServerRequest = new MutableHttpServerRequest(request, body);
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ package org.springframework.cloud.alibaba.dubbo.metadata;
|
|||||||
|
|
||||||
import org.apache.dubbo.config.ProtocolConfig;
|
import org.apache.dubbo.config.ProtocolConfig;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@ -31,15 +33,16 @@ import static org.apache.dubbo.common.Constants.DEFAULT_PROTOCOL;
|
|||||||
*/
|
*/
|
||||||
public class DubboProtocolConfigSupplier implements Supplier<ProtocolConfig> {
|
public class DubboProtocolConfigSupplier implements Supplier<ProtocolConfig> {
|
||||||
|
|
||||||
private final Collection<ProtocolConfig> protocols;
|
private final ObjectProvider<Collection<ProtocolConfig>> protocols;
|
||||||
|
|
||||||
public DubboProtocolConfigSupplier(Collection<ProtocolConfig> protocols) {
|
public DubboProtocolConfigSupplier(ObjectProvider<Collection<ProtocolConfig>> protocols) {
|
||||||
this.protocols = protocols;
|
this.protocols = protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProtocolConfig get() {
|
public ProtocolConfig get() {
|
||||||
ProtocolConfig protocolConfig = null;
|
ProtocolConfig protocolConfig = null;
|
||||||
|
Collection<ProtocolConfig> protocols = this.protocols.getIfAvailable();
|
||||||
for (ProtocolConfig protocol : protocols) {
|
for (ProtocolConfig protocol : protocols) {
|
||||||
String protocolName = protocol.getName();
|
String protocolName = protocol.getName();
|
||||||
if (DEFAULT_PROTOCOL.equals(protocolName)) {
|
if (DEFAULT_PROTOCOL.equals(protocolName)) {
|
||||||
|
@ -19,17 +19,17 @@ package org.springframework.cloud.alibaba.dubbo.metadata;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dubbo Service Metadata
|
* Dubbo Rest Service Metadata
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
*/
|
*/
|
||||||
public class DubboServiceMetadata {
|
public class DubboRestServiceMetadata {
|
||||||
|
|
||||||
private final ServiceRestMetadata serviceRestMetadata;
|
private final ServiceRestMetadata serviceRestMetadata;
|
||||||
|
|
||||||
private final RestMethodMetadata restMethodMetadata;
|
private final RestMethodMetadata restMethodMetadata;
|
||||||
|
|
||||||
public DubboServiceMetadata(ServiceRestMetadata serviceRestMetadata, RestMethodMetadata restMethodMetadata) {
|
public DubboRestServiceMetadata(ServiceRestMetadata serviceRestMetadata, RestMethodMetadata restMethodMetadata) {
|
||||||
this.serviceRestMetadata = serviceRestMetadata;
|
this.serviceRestMetadata = serviceRestMetadata;
|
||||||
this.restMethodMetadata = restMethodMetadata;
|
this.restMethodMetadata = restMethodMetadata;
|
||||||
}
|
}
|
||||||
@ -45,8 +45,8 @@ public class DubboServiceMetadata {
|
|||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (!(o instanceof DubboServiceMetadata)) return false;
|
if (!(o instanceof DubboRestServiceMetadata)) return false;
|
||||||
DubboServiceMetadata that = (DubboServiceMetadata) o;
|
DubboRestServiceMetadata that = (DubboRestServiceMetadata) o;
|
||||||
return Objects.equals(serviceRestMetadata, that.serviceRestMetadata) &&
|
return Objects.equals(serviceRestMetadata, that.serviceRestMetadata) &&
|
||||||
Objects.equals(restMethodMetadata, that.restMethodMetadata);
|
Objects.equals(restMethodMetadata, that.restMethodMetadata);
|
||||||
}
|
}
|
@ -16,13 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.metadata.repository;
|
package org.springframework.cloud.alibaba.dubbo.metadata.repository;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.URL;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cloud.alibaba.dubbo.http.matcher.RequestMetadataMatcher;
|
import org.springframework.cloud.alibaba.dubbo.http.matcher.RequestMetadataMatcher;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.DubboRestServiceMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigService;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigService;
|
||||||
@ -30,6 +32,7 @@ import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServic
|
|||||||
import org.springframework.http.HttpRequest;
|
import org.springframework.http.HttpRequest;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
@ -51,17 +54,31 @@ public class DubboServiceMetadataRepository {
|
|||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
private final Set<URL> registeredURLs = new LinkedHashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key is application name
|
* Key is application name
|
||||||
* Value is Map<RequestMetadata, DubboServiceMetadata>
|
* Value is Map<RequestMetadata, DubboRestServiceMetadata>
|
||||||
*/
|
*/
|
||||||
private Map<String, Map<RequestMetadataMatcher, DubboServiceMetadata>> repository = newHashMap();
|
private Map<String, Map<RequestMetadataMatcher, DubboRestServiceMetadata>> repository = newHashMap();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy;
|
private DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy;
|
||||||
|
|
||||||
|
public void registerURL(URL url) {
|
||||||
|
this.registeredURLs.add(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregisterURL(URL url) {
|
||||||
|
this.registeredURLs.remove(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<URL> getRegisteredUrls() {
|
||||||
|
return Collections.unmodifiableSet(registeredURLs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the specified service's Dubbo Service Metadata
|
* Initialize the specified service's {@link ServiceRestMetadata}
|
||||||
*
|
*
|
||||||
* @param serviceName the service name
|
* @param serviceName the service name
|
||||||
*/
|
*/
|
||||||
@ -81,14 +98,14 @@ public class DubboServiceMetadataRepository {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<RequestMetadataMatcher, DubboServiceMetadata> metadataMap = getMetadataMap(serviceName);
|
Map<RequestMetadataMatcher, DubboRestServiceMetadata> metadataMap = getMetadataMap(serviceName);
|
||||||
|
|
||||||
for (ServiceRestMetadata serviceRestMetadata : serviceRestMetadataSet) {
|
for (ServiceRestMetadata serviceRestMetadata : serviceRestMetadataSet) {
|
||||||
|
|
||||||
serviceRestMetadata.getMeta().forEach(restMethodMetadata -> {
|
serviceRestMetadata.getMeta().forEach(restMethodMetadata -> {
|
||||||
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
|
RequestMetadata requestMetadata = restMethodMetadata.getRequest();
|
||||||
RequestMetadataMatcher matcher = new RequestMetadataMatcher(requestMetadata);
|
RequestMetadataMatcher matcher = new RequestMetadataMatcher(requestMetadata);
|
||||||
DubboServiceMetadata metadata = new DubboServiceMetadata(serviceRestMetadata, restMethodMetadata);
|
DubboRestServiceMetadata metadata = new DubboRestServiceMetadata(serviceRestMetadata, restMethodMetadata);
|
||||||
metadataMap.put(matcher, metadata);
|
metadataMap.put(matcher, metadata);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -99,13 +116,13 @@ public class DubboServiceMetadataRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a {@link DubboServiceMetadata} by the specified service name if {@link RequestMetadata} matched
|
* Get a {@link DubboRestServiceMetadata} by the specified service name if {@link RequestMetadata} matched
|
||||||
*
|
*
|
||||||
* @param serviceName service name
|
* @param serviceName service name
|
||||||
* @param requestMetadata {@link RequestMetadata} to be matched
|
* @param requestMetadata {@link RequestMetadata} to be matched
|
||||||
* @return {@link DubboServiceMetadata} if matched, or <code>null</code>
|
* @return {@link DubboRestServiceMetadata} if matched, or <code>null</code>
|
||||||
*/
|
*/
|
||||||
public DubboServiceMetadata get(String serviceName, RequestMetadata requestMetadata) {
|
public DubboRestServiceMetadata get(String serviceName, RequestMetadata requestMetadata) {
|
||||||
return match(repository, serviceName, requestMetadata);
|
return match(repository, serviceName, requestMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +165,7 @@ public class DubboServiceMetadataRepository {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<RequestMetadataMatcher, DubboServiceMetadata> getMetadataMap(String serviceName) {
|
private Map<RequestMetadataMatcher, DubboRestServiceMetadata> getMetadataMap(String serviceName) {
|
||||||
return getMap(repository, serviceName);
|
return getMap(repository, serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import feign.Target;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported;
|
import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.DubboRestServiceMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMethodMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMethodMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||||
@ -147,13 +147,13 @@ class TargeterInvocationHandler implements InvocationHandler {
|
|||||||
for (Map.Entry<DubboTransportedMethodMetadata, RestMethodMetadata> entry : feignRestMethodMetadataMap.entrySet()) {
|
for (Map.Entry<DubboTransportedMethodMetadata, RestMethodMetadata> entry : feignRestMethodMetadataMap.entrySet()) {
|
||||||
RestMethodMetadata feignRestMethodMetadata = entry.getValue();
|
RestMethodMetadata feignRestMethodMetadata = entry.getValue();
|
||||||
RequestMetadata feignRequestMetadata = feignRestMethodMetadata.getRequest();
|
RequestMetadata feignRequestMetadata = feignRestMethodMetadata.getRequest();
|
||||||
DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, feignRequestMetadata);
|
DubboRestServiceMetadata metadata = repository.get(serviceName, feignRequestMetadata);
|
||||||
if (dubboServiceMetadata != null) {
|
if (metadata != null) {
|
||||||
DubboTransportedMethodMetadata dubboTransportedMethodMetadata = entry.getKey();
|
DubboTransportedMethodMetadata dubboTransportedMethodMetadata = entry.getKey();
|
||||||
Map<String, Object> dubboTranslatedAttributes = dubboTransportedMethodMetadata.getAttributes();
|
Map<String, Object> dubboTranslatedAttributes = dubboTransportedMethodMetadata.getAttributes();
|
||||||
Method method = dubboTransportedMethodMetadata.getMethod();
|
Method method = dubboTransportedMethodMetadata.getMethod();
|
||||||
GenericService dubboGenericService = dubboGenericServiceFactory.create(dubboServiceMetadata, dubboTranslatedAttributes);
|
GenericService dubboGenericService = dubboGenericServiceFactory.create(metadata, dubboTranslatedAttributes);
|
||||||
RestMethodMetadata dubboRestMethodMetadata = dubboServiceMetadata.getRestMethodMetadata();
|
RestMethodMetadata dubboRestMethodMetadata = metadata.getRestMethodMetadata();
|
||||||
MethodMetadata methodMetadata = dubboTransportedMethodMetadata.getMethodMetadata();
|
MethodMetadata methodMetadata = dubboTransportedMethodMetadata.getMethodMetadata();
|
||||||
FeignMethodMetadata feignMethodMetadata = new FeignMethodMetadata(dubboGenericService,
|
FeignMethodMetadata feignMethodMetadata = new FeignMethodMetadata(dubboGenericService,
|
||||||
dubboRestMethodMetadata, feignRestMethodMetadata);
|
dubboRestMethodMetadata, feignRestMethodMetadata);
|
||||||
|
@ -1,68 +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.springframework.cloud.alibaba.dubbo.registry;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.Constants;
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
|
|
||||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract {@link RegistrationFactory} implementation
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @param <R> The subclass of {@link Registration}
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractRegistrationFactory<R extends Registration> implements RegistrationFactory<R> {
|
|
||||||
|
|
||||||
public final R create(URL url, ConfigurableApplicationContext applicationContext) {
|
|
||||||
ServiceInstance serviceInstance = createServiceInstance(url, applicationContext);
|
|
||||||
return create(serviceInstance, applicationContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance {@link ServiceInstance}. This method maybe override by sub-class.
|
|
||||||
*
|
|
||||||
* @param url The Dubbo's {@link URL}
|
|
||||||
* @param applicationContext {@link ConfigurableApplicationContext}
|
|
||||||
* @return an instance {@link ServiceInstance}
|
|
||||||
*/
|
|
||||||
protected ServiceInstance createServiceInstance(URL url, ConfigurableApplicationContext applicationContext) {
|
|
||||||
String serviceId = createServiceId(url, applicationContext);
|
|
||||||
// Append default category if absent
|
|
||||||
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
|
|
||||||
URL newURL = url.addParameter(Constants.CATEGORY_KEY, category);
|
|
||||||
newURL = newURL.addParameter(Constants.PROTOCOL_KEY, url.getProtocol());
|
|
||||||
String ip = url.getIp();
|
|
||||||
int port = newURL.getParameter(Constants.BIND_PORT_KEY, url.getPort());
|
|
||||||
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(url.toIdentityString(), serviceId, ip, port, false);
|
|
||||||
serviceInstance.getMetadata().putAll(new LinkedHashMap<>(newURL.getParameters()));
|
|
||||||
return serviceInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String createServiceId(URL url, ConfigurableApplicationContext applicationContext) {
|
|
||||||
DubboRegistryServiceIdHandler handler = applicationContext.getBean(DubboRegistryServiceIdHandler.class);
|
|
||||||
return handler.createServiceId(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
* 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.springframework.cloud.alibaba.dubbo.registry;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.Constants;
|
||||||
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.common.utils.UrlUtils;
|
||||||
|
import org.apache.dubbo.registry.NotifyListener;
|
||||||
|
import org.apache.dubbo.registry.RegistryFactory;
|
||||||
|
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 java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static java.util.Collections.singleton;
|
||||||
|
import static org.apache.dubbo.common.Constants.PROVIDER_SIDE;
|
||||||
|
import static org.apache.dubbo.common.Constants.SIDE_KEY;
|
||||||
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud"
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSpringCloudRegistry extends FailbackRegistry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameter name of {@link #servicesLookupInterval}
|
||||||
|
*/
|
||||||
|
public static final String SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.services.lookup.interval";
|
||||||
|
|
||||||
|
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval in second of lookup service names(only for Dubbo-OPS)
|
||||||
|
*/
|
||||||
|
private final long servicesLookupInterval;
|
||||||
|
|
||||||
|
private final DiscoveryClient discoveryClient;
|
||||||
|
|
||||||
|
protected final ScheduledExecutorService servicesLookupScheduler;
|
||||||
|
|
||||||
|
public AbstractSpringCloudRegistry(URL url,
|
||||||
|
DiscoveryClient discoveryClient,
|
||||||
|
ScheduledExecutorService servicesLookupScheduler) {
|
||||||
|
super(url);
|
||||||
|
this.servicesLookupInterval = url.getParameter(SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 60L);
|
||||||
|
this.discoveryClient = discoveryClient;
|
||||||
|
this.servicesLookupScheduler = servicesLookupScheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
doRegister0(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sub-type should implement to register
|
||||||
|
*
|
||||||
|
* @param url {@link URL}
|
||||||
|
*/
|
||||||
|
protected abstract void doRegister0(URL url);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void doUnregister(URL url) {
|
||||||
|
if (!shouldRegister(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doUnregister0(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sub-type should implement to unregister
|
||||||
|
*
|
||||||
|
* @param url {@link URL}
|
||||||
|
*/
|
||||||
|
protected abstract void doUnregister0(URL url);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void doSubscribe(URL url, NotifyListener listener) {
|
||||||
|
Set<String> serviceNames = getServiceNames(url);
|
||||||
|
doSubscribe(url, listener, serviceNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void doUnsubscribe(URL url, NotifyListener listener) {
|
||||||
|
if (isAdminProtocol(url)) {
|
||||||
|
shutdownServiceNamesLookup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return !discoveryClient.getServices().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void shutdownServiceNamesLookup() {
|
||||||
|
if (servicesLookupScheduler != null) {
|
||||||
|
servicesLookupScheduler.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterServiceNames(Collection<String> serviceNames) {
|
||||||
|
filter(serviceNames, new Filter<String>() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(String serviceName) {
|
||||||
|
return supports(serviceName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean supports(String serviceName);
|
||||||
|
|
||||||
|
protected final Set<String> getAllServiceNames() {
|
||||||
|
return new LinkedHashSet<>(discoveryClient.getServices());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the service names from the specified {@link URL url}
|
||||||
|
*
|
||||||
|
* @param url {@link URL}
|
||||||
|
* @return non-null
|
||||||
|
*/
|
||||||
|
private Set<String> getServiceNames(URL url) {
|
||||||
|
if (isAdminProtocol(url)) {
|
||||||
|
return getServiceNamesForOps(url);
|
||||||
|
} else {
|
||||||
|
return singleton(getServiceName(url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isAdminProtocol(URL url) {
|
||||||
|
return Constants.ADMIN_PROTOCOL.equals(url.getProtocol());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the service names for Dubbo OPS
|
||||||
|
*
|
||||||
|
* @param url {@link URL}
|
||||||
|
* @return non-null
|
||||||
|
*/
|
||||||
|
protected Set<String> getServiceNamesForOps(URL url) {
|
||||||
|
Set<String> serviceNames = getAllServiceNames();
|
||||||
|
filterServiceNames(serviceNames);
|
||||||
|
return serviceNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String getServiceName(URL url);
|
||||||
|
|
||||||
|
private void doSubscribe(final URL url, final NotifyListener listener, final Collection<String> serviceNames) {
|
||||||
|
|
||||||
|
subscribe(url, listener, serviceNames);
|
||||||
|
|
||||||
|
schedule(() -> {
|
||||||
|
subscribe(url, listener, serviceNames);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ScheduledFuture<?> schedule(Runnable runnable) {
|
||||||
|
return this.servicesLookupScheduler.scheduleAtFixedRate(runnable, servicesLookupInterval,
|
||||||
|
servicesLookupInterval, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<ServiceInstance> getServiceInstances(String serviceName) {
|
||||||
|
return discoveryClient.getInstances(serviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void subscribe(final URL url, final NotifyListener listener, final Collection<String> serviceNames) {
|
||||||
|
for (String serviceName : serviceNames) {
|
||||||
|
List<ServiceInstance> serviceInstances = getServiceInstances(serviceName);
|
||||||
|
if (!isEmpty(serviceInstances)) {
|
||||||
|
notifySubscriber(url, listener, serviceInstances);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the Healthy {@link ServiceInstance service instance} to subscriber.
|
||||||
|
*
|
||||||
|
* @param url {@link URL}
|
||||||
|
* @param listener {@link NotifyListener}
|
||||||
|
* @param serviceInstances all {@link ServiceInstance instances}
|
||||||
|
*/
|
||||||
|
protected abstract void notifySubscriber(URL url, NotifyListener listener, List<ServiceInstance> serviceInstances);
|
||||||
|
|
||||||
|
protected void filterHealthyInstances(Collection<ServiceInstance> instances) {
|
||||||
|
filter(instances, new Filter<ServiceInstance>() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(ServiceInstance data) {
|
||||||
|
// TODO check the details of status
|
||||||
|
// return serviceRegistry.getStatus(new DubboRegistration(data)) != null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<URL> buildURLs(URL consumerURL, Collection<ServiceInstance> serviceInstances) {
|
||||||
|
if (serviceInstances.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<URL> urls = new LinkedList<URL>();
|
||||||
|
for (ServiceInstance serviceInstance : serviceInstances) {
|
||||||
|
URL url = buildURL(serviceInstance);
|
||||||
|
if (UrlUtils.isMatch(consumerURL, url)) {
|
||||||
|
urls.add(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
private URL buildURL(ServiceInstance serviceInstance) {
|
||||||
|
URL url = new URL(serviceInstance.getMetadata().get(Constants.PROTOCOL_KEY),
|
||||||
|
serviceInstance.getHost(),
|
||||||
|
serviceInstance.getPort(),
|
||||||
|
serviceInstance.getMetadata());
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void filter(Collection<T> collection, Filter<T> filter) {
|
||||||
|
Iterator<T> iterator = collection.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
T data = iterator.next();
|
||||||
|
if (!filter.accept(data)) { // remove if not accept
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T[] of(T... values) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A filter
|
||||||
|
*/
|
||||||
|
public interface Filter<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not the specified data should be accepted.
|
||||||
|
*
|
||||||
|
* @param data The data to be tested
|
||||||
|
* @return <code>true</code> if and only if <code>data</code>
|
||||||
|
* should be accepted
|
||||||
|
*/
|
||||||
|
boolean accept(T data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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.springframework.cloud.alibaba.dubbo.registry;
|
||||||
|
|
||||||
|
import org.aspectj.lang.annotation.After;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstancePreRegisteredEvent;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstanceRegisteredEvent;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.context.ApplicationEventPublisherAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dubbo Service Registration Event-Publishing Aspect
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
* @see ServiceInstancePreRegisteredEvent
|
||||||
|
* @see ServiceInstanceRegisteredEvent
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
public class DubboServiceRegistrationEventPublishingAspect implements ApplicationEventPublisherAware {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pointcut expression for {@link ServiceRegistry#register(Registration)}
|
||||||
|
*/
|
||||||
|
public static final String REGISTER_POINTCUT_EXPRESSION =
|
||||||
|
"execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && args(registration)";
|
||||||
|
|
||||||
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
|
@Before(REGISTER_POINTCUT_EXPRESSION)
|
||||||
|
public void beforeRegister(Registration registration) {
|
||||||
|
applicationEventPublisher.publishEvent(new ServiceInstancePreRegisteredEvent(registration));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After(REGISTER_POINTCUT_EXPRESSION)
|
||||||
|
public void afterRegister(Registration registration) {
|
||||||
|
applicationEventPublisher.publishEvent(new ServiceInstanceRegisteredEvent(registration));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||||
|
this.applicationEventPublisher = applicationEventPublisher;
|
||||||
|
}
|
||||||
|
}
|
@ -1,50 +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.springframework.cloud.alibaba.dubbo.registry;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Registration} Factory to createServiceInstance a instance of {@link Registration}
|
|
||||||
*
|
|
||||||
* @param <R> The subclass of {@link Registration}
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public interface RegistrationFactory<R extends Registration> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a instance of {@link R}
|
|
||||||
*
|
|
||||||
* @param url The Dubbo's {@link URL}
|
|
||||||
* @param applicationContext {@link ConfigurableApplicationContext}
|
|
||||||
* @return a instance of {@link R}, if null, it indicates the registration will not be executed.
|
|
||||||
*/
|
|
||||||
R create(URL url, ConfigurableApplicationContext applicationContext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a instance of {@link R}
|
|
||||||
*
|
|
||||||
* @param serviceInstance {@link ServiceInstance}
|
|
||||||
* @param applicationContext {@link ConfigurableApplicationContext}
|
|
||||||
* @return a instance of {@link R}, if null, it indicates the registration will not be executed.
|
|
||||||
*/
|
|
||||||
R create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext);
|
|
||||||
}
|
|
@ -1,144 +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.springframework.cloud.alibaba.dubbo.registry;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
import org.springframework.core.ResolvableType;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.springframework.beans.BeanUtils.instantiateClass;
|
|
||||||
import static org.springframework.core.ResolvableType.forInstance;
|
|
||||||
import static org.springframework.core.ResolvableType.forType;
|
|
||||||
import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames;
|
|
||||||
import static org.springframework.util.ClassUtils.isPresent;
|
|
||||||
import static org.springframework.util.ClassUtils.resolveClassName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link RegistrationFactory} Provider
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public class RegistrationFactoryProvider implements FactoryBean<RegistrationFactory>, ApplicationContextAware {
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
private RegistrationFactory registrationFactory;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RegistrationFactory getObject() throws BeansException {
|
|
||||||
return registrationFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return RegistrationFactory.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSingleton() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
ServiceRegistry<Registration> serviceRegistry = applicationContext.getBean(ServiceRegistry.class);
|
|
||||||
ClassLoader classLoader = applicationContext.getClassLoader();
|
|
||||||
this.registrationFactory = buildRegistrationFactory(serviceRegistry, classLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RegistrationFactory buildRegistrationFactory(ServiceRegistry<Registration> serviceRegistry,
|
|
||||||
ClassLoader classLoader) {
|
|
||||||
RegistrationFactory registrationFactory = null;
|
|
||||||
List<String> factoryClassNames = loadFactoryNames(RegistrationFactory.class, classLoader);
|
|
||||||
|
|
||||||
ResolvableType serviceRegistryType = forInstance(serviceRegistry);
|
|
||||||
// Get first generic Class
|
|
||||||
Class<?> registrationClass = resolveGenericClass(serviceRegistryType, ServiceRegistry.class, 0);
|
|
||||||
|
|
||||||
for (String factoryClassName : factoryClassNames) {
|
|
||||||
if (isPresent(factoryClassName, classLoader)) { // ignore compilation issue
|
|
||||||
Class<?> factoryClass = resolveClassName(factoryClassName, classLoader);
|
|
||||||
ResolvableType registrationFactoryType = forType(factoryClass);
|
|
||||||
Class<?> actualRegistrationClass = resolveGenericClass(registrationFactoryType, RegistrationFactory.class, 0);
|
|
||||||
if (registrationClass.equals(actualRegistrationClass)) {
|
|
||||||
registrationFactory = (RegistrationFactory) instantiateClass(registrationFactoryType.getRawClass());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (registrationFactory == null) {
|
|
||||||
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logger.warn("{} implementation can't be resolved by ServiceRegistry[{}]",
|
|
||||||
registrationClass.getSimpleName(), serviceRegistry.getClass().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
registrationFactory = new DefaultRegistrationFactory();
|
|
||||||
} else {
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("{} has been resolved by ServiceRegistry[{}]",
|
|
||||||
registrationFactory.getClass().getName(), serviceRegistry.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return registrationFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> resolveGenericClass(ResolvableType implementedType, Class<?> interfaceClass, int index) {
|
|
||||||
|
|
||||||
ResolvableType resolvableType = implementedType;
|
|
||||||
|
|
||||||
try {
|
|
||||||
OUTER:
|
|
||||||
while (true) {
|
|
||||||
|
|
||||||
ResolvableType[] interfaceTypes = resolvableType.getInterfaces();
|
|
||||||
|
|
||||||
for (ResolvableType interfaceType : interfaceTypes) {
|
|
||||||
if (interfaceType.resolve().equals(interfaceClass)) {
|
|
||||||
resolvableType = interfaceType;
|
|
||||||
break OUTER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvableType superType = resolvableType.getSuperType();
|
|
||||||
|
|
||||||
Class<?> superClass = superType.resolve();
|
|
||||||
|
|
||||||
if (Object.class.equals(superClass)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvableType = superType;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Throwable e) {
|
|
||||||
resolvableType = ResolvableType.forType(void.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvableType.resolveGeneric(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -16,299 +16,138 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.registry;
|
package org.springframework.cloud.alibaba.dubbo.registry;
|
||||||
|
|
||||||
import org.apache.dubbo.common.Constants;
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.utils.UrlUtils;
|
|
||||||
import org.apache.dubbo.registry.NotifyListener;
|
import org.apache.dubbo.registry.NotifyListener;
|
||||||
import org.apache.dubbo.registry.RegistryFactory;
|
import org.apache.dubbo.registry.RegistryFactory;
|
||||||
import org.apache.dubbo.registry.support.FailbackRegistry;
|
|
||||||
import org.slf4j.Logger;
|
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.springframework.cloud.alibaba.dubbo.util.JSONUtils;
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.emptyMap;
|
||||||
import static org.apache.dubbo.common.Constants.CONFIGURATORS_CATEGORY;
|
import static org.apache.dubbo.common.Constants.APPLICATION_KEY;
|
||||||
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
|
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||||
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
|
|
||||||
import static org.apache.dubbo.common.Constants.PROVIDER_SIDE;
|
|
||||||
import static org.apache.dubbo.common.Constants.ROUTERS_CATEGORY;
|
|
||||||
import static org.apache.dubbo.common.Constants.SIDE_KEY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud"
|
* Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud"
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
*/
|
*/
|
||||||
public class SpringCloudRegistry extends FailbackRegistry {
|
public class SpringCloudRegistry extends AbstractSpringCloudRegistry {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parameter name of {@link #allServicesLookupInterval}
|
* The property name of Dubbo {@link URL URLs} metadata
|
||||||
*/
|
*/
|
||||||
public static final String ALL_SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.all.services.lookup.interval";
|
public static final String DUBBO_URLS_METADATA_PROPERTY_NAME = "dubbo.urls";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parameter name of {@link #registeredServicesLookupInterval}
|
* The parameter name of the services of Dubbo Provider
|
||||||
*/
|
*/
|
||||||
public static final String REGISTERED_SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.registered.services.lookup.interval";
|
public static final String DUBBO_PROVIDER_SERVICES_PARAM_NAME = "dubbo.provider-services";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All supported categories
|
* All services of Dubbo Provider
|
||||||
*/
|
*/
|
||||||
public static final String[] ALL_SUPPORTED_CATEGORIES = of(
|
public static final String ALL_DUBBO_PROVIDER_SERVICES = "*";
|
||||||
PROVIDERS_CATEGORY,
|
|
||||||
CONSUMERS_CATEGORY,
|
|
||||||
ROUTERS_CATEGORY,
|
|
||||||
CONFIGURATORS_CATEGORY
|
|
||||||
);
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
private final DubboServiceMetadataRepository dubboServiceMetadataRepository;
|
||||||
|
|
||||||
/**
|
private final JSONUtils jsonUtils;
|
||||||
* The interval in second of lookup service names(only for Dubbo-OPS)
|
|
||||||
*/
|
|
||||||
private final long allServicesLookupInterval;
|
|
||||||
|
|
||||||
private final long registeredServicesLookupInterval;
|
private final Set<String> dubboProviderServices;
|
||||||
|
|
||||||
private final ServiceRegistry<Registration> serviceRegistry;
|
private final Map<String, String> dubboServiceKeysCache;
|
||||||
|
|
||||||
private final RegistrationFactory registrationFactory;
|
public SpringCloudRegistry(URL url, DiscoveryClient discoveryClient,
|
||||||
|
|
||||||
private final DiscoveryClient discoveryClient;
|
|
||||||
|
|
||||||
private final DubboRegistryServiceIdHandler dubboRegistryServiceIdHandler;
|
|
||||||
|
|
||||||
private final ScheduledExecutorService servicesLookupScheduler;
|
|
||||||
|
|
||||||
private final ConfigurableApplicationContext applicationContext;
|
|
||||||
|
|
||||||
public SpringCloudRegistry(URL url,
|
|
||||||
ServiceRegistry<Registration> serviceRegistry,
|
|
||||||
RegistrationFactory registrationFactory,
|
|
||||||
DiscoveryClient discoveryClient,
|
|
||||||
ScheduledExecutorService servicesLookupScheduler,
|
ScheduledExecutorService servicesLookupScheduler,
|
||||||
|
DubboServiceMetadataRepository dubboServiceMetadataRepository,
|
||||||
ConfigurableApplicationContext applicationContext) {
|
ConfigurableApplicationContext applicationContext) {
|
||||||
super(url);
|
super(url, discoveryClient, servicesLookupScheduler);
|
||||||
this.allServicesLookupInterval = url.getParameter(ALL_SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 30L);
|
this.dubboServiceMetadataRepository = dubboServiceMetadataRepository;
|
||||||
this.registeredServicesLookupInterval = url.getParameter(REGISTERED_SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 300L);
|
this.jsonUtils = applicationContext.getBean(JSONUtils.class);
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.dubboProviderServices = getDubboProviderServices();
|
||||||
this.registrationFactory = registrationFactory;
|
this.dubboServiceKeysCache = this.initDubboServiceKeysCache();
|
||||||
this.discoveryClient = discoveryClient;
|
|
||||||
this.dubboRegistryServiceIdHandler = applicationContext.getBean(DubboRegistryServiceIdHandler.class);
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
this.servicesLookupScheduler = servicesLookupScheduler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldRegister(Registration registration) {
|
private Map<String, String> initDubboServiceKeysCache() {
|
||||||
Map<String, String> metadata = registration.getMetadata();
|
|
||||||
String side = metadata.get(SIDE_KEY);
|
if (isEmpty(dubboProviderServices)) {
|
||||||
return PROVIDER_SIDE.equals(side); // Only register the Provider.
|
return emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> newCache = new HashMap<>();
|
||||||
|
|
||||||
|
dubboProviderServices.stream()
|
||||||
|
.map(this::getServiceInstances)
|
||||||
|
.filter(this::isNotEmpty)
|
||||||
|
.forEach(serviceInstances -> {
|
||||||
|
ServiceInstance serviceInstance = serviceInstances.get(0);
|
||||||
|
getURLs(serviceInstance).forEach(url -> {
|
||||||
|
String serviceKey = url.getServiceKey();
|
||||||
|
String serviceName = url.getParameter(APPLICATION_KEY);
|
||||||
|
newCache.put(serviceKey, serviceName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return newCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNotEmpty(Collection collection) {
|
||||||
|
return !CollectionUtils.isEmpty(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<URL> getURLs(ServiceInstance serviceInstance) {
|
||||||
|
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||||
|
String dubboURLsJSON = metadata.get(DUBBO_URLS_METADATA_PROPERTY_NAME);
|
||||||
|
List<String> urlValues = jsonUtils.toList(dubboURLsJSON);
|
||||||
|
return urlValues.stream().map(URL::valueOf).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getDubboProviderServices() {
|
||||||
|
URL registryURL = getUrl();
|
||||||
|
String services = registryURL.getParameter(DUBBO_PROVIDER_SERVICES_PARAM_NAME, ALL_DUBBO_PROVIDER_SERVICES);
|
||||||
|
return ALL_DUBBO_PROVIDER_SERVICES.equalsIgnoreCase(services) ?
|
||||||
|
getAllServiceNames() : StringUtils.commaDelimitedListToSet(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doRegister(URL url) {
|
protected void doRegister0(URL url) {
|
||||||
final Registration registration = createRegistration(url);
|
dubboServiceMetadataRepository.registerURL(url);
|
||||||
if (shouldRegister(registration)) {
|
|
||||||
serviceRegistry.register(registration);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doUnregister(URL url) {
|
protected void doUnregister0(URL url) {
|
||||||
final Registration registration = createRegistration(url);
|
dubboServiceMetadataRepository.unregisterURL(url);
|
||||||
if (shouldRegister(registration)) {
|
|
||||||
this.serviceRegistry.deregister(registration);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSubscribe(URL url, NotifyListener listener) {
|
protected boolean supports(String serviceName) {
|
||||||
List<String> serviceNames = getServiceNames(url, listener);
|
return dubboProviderServices.contains(serviceName);
|
||||||
doSubscribe(url, listener, serviceNames);
|
|
||||||
this.servicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
doSubscribe(url, listener, serviceNames);
|
|
||||||
}
|
|
||||||
}, registeredServicesLookupInterval, registeredServicesLookupInterval, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doUnsubscribe(URL url, NotifyListener listener) {
|
protected String getServiceName(URL url) {
|
||||||
if (isAdminProtocol(url)) {
|
String serviceKey = url.getServiceKey();
|
||||||
shutdownServiceNamesLookup();
|
return dubboServiceKeysCache.get(serviceKey);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAvailable() {
|
protected void notifySubscriber(URL url, NotifyListener listener, List<ServiceInstance> serviceInstances) {
|
||||||
return !discoveryClient.getServices().isEmpty();
|
List<URL> urls = serviceInstances.stream().map(this::getURLs)
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
notify(url, listener, urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shutdownServiceNamesLookup() {
|
|
||||||
if (servicesLookupScheduler != null) {
|
|
||||||
servicesLookupScheduler.shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Registration createRegistration(URL url) {
|
|
||||||
return registrationFactory.create(url, applicationContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void filterServiceNames(List<String> serviceNames) {
|
|
||||||
filter(serviceNames, new Filter<String>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(String serviceName) {
|
|
||||||
return dubboRegistryServiceIdHandler.supports(serviceName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getAllServiceNames() {
|
|
||||||
return new LinkedList<>(discoveryClient.getServices());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the service names from the specified {@link URL url}
|
|
||||||
*
|
|
||||||
* @param url {@link URL}
|
|
||||||
* @param listener {@link NotifyListener}
|
|
||||||
* @return non-null
|
|
||||||
*/
|
|
||||||
private List<String> getServiceNames(URL url, NotifyListener listener) {
|
|
||||||
if (isAdminProtocol(url)) {
|
|
||||||
initAllServicesLookupScheduler(url, listener);
|
|
||||||
return getServiceNamesForOps(url);
|
|
||||||
} else {
|
|
||||||
return singletonList(dubboRegistryServiceIdHandler.createServiceId(url));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isAdminProtocol(URL url) {
|
|
||||||
return Constants.ADMIN_PROTOCOL.equals(url.getProtocol());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initAllServicesLookupScheduler(final URL url, final NotifyListener listener) {
|
|
||||||
servicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
List<String> serviceNames = getAllServiceNames();
|
|
||||||
filterServiceNames(serviceNames);
|
|
||||||
doSubscribe(url, listener, serviceNames);
|
|
||||||
}
|
|
||||||
}, allServicesLookupInterval, allServicesLookupInterval, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doSubscribe(final URL url, final NotifyListener listener, final List<String> serviceNames) {
|
|
||||||
for (String serviceName : serviceNames) {
|
|
||||||
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
|
|
||||||
notifySubscriber(url, listener, serviceInstances);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the Healthy {@link ServiceInstance service instance} to subscriber.
|
|
||||||
*
|
|
||||||
* @param url {@link URL}
|
|
||||||
* @param listener {@link NotifyListener}
|
|
||||||
* @param serviceInstances all {@link ServiceInstance instances}
|
|
||||||
*/
|
|
||||||
private void notifySubscriber(URL url, NotifyListener listener, List<ServiceInstance> serviceInstances) {
|
|
||||||
List<ServiceInstance> healthyInstances = new LinkedList<ServiceInstance>(serviceInstances);
|
|
||||||
// Healthy Instances
|
|
||||||
filterHealthyInstances(healthyInstances);
|
|
||||||
List<URL> urls = buildURLs(url, healthyInstances);
|
|
||||||
this.notify(url, listener, urls);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void filterHealthyInstances(Collection<ServiceInstance> instances) {
|
|
||||||
filter(instances, new Filter<ServiceInstance>() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(ServiceInstance data) {
|
|
||||||
// TODO check the details of status
|
|
||||||
// return serviceRegistry.getStatus(new DubboRegistration(data)) != null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<URL> buildURLs(URL consumerURL, Collection<ServiceInstance> serviceInstances) {
|
|
||||||
if (serviceInstances.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
List<URL> urls = new LinkedList<URL>();
|
|
||||||
for (ServiceInstance serviceInstance : serviceInstances) {
|
|
||||||
URL url = buildURL(serviceInstance);
|
|
||||||
if (UrlUtils.isMatch(consumerURL, url)) {
|
|
||||||
urls.add(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return urls;
|
|
||||||
}
|
|
||||||
|
|
||||||
private URL buildURL(ServiceInstance serviceInstance) {
|
|
||||||
URL url = new URL(serviceInstance.getMetadata().get(Constants.PROTOCOL_KEY),
|
|
||||||
serviceInstance.getHost(),
|
|
||||||
serviceInstance.getPort(),
|
|
||||||
serviceInstance.getMetadata());
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the service names for Dubbo OPS
|
|
||||||
*
|
|
||||||
* @param url {@link URL}
|
|
||||||
* @return non-null
|
|
||||||
*/
|
|
||||||
private List<String> getServiceNamesForOps(URL url) {
|
|
||||||
List<String> serviceNames = getAllServiceNames();
|
|
||||||
filterServiceNames(serviceNames);
|
|
||||||
return serviceNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> void filter(Collection<T> collection, Filter<T> filter) {
|
|
||||||
Iterator<T> iterator = collection.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
T data = iterator.next();
|
|
||||||
if (!filter.accept(data)) { // remove if not accept
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> T[] of(T... values) {
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A filter
|
|
||||||
*/
|
|
||||||
public interface Filter<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether or not the specified data should be accepted.
|
|
||||||
*
|
|
||||||
* @param data The data to be tested
|
|
||||||
* @return <code>true</code> if and only if <code>data</code>
|
|
||||||
* should be accepted
|
|
||||||
*/
|
|
||||||
boolean accept(T data);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,9 @@ import org.apache.dubbo.common.URL;
|
|||||||
import org.apache.dubbo.common.utils.NamedThreadFactory;
|
import org.apache.dubbo.common.utils.NamedThreadFactory;
|
||||||
import org.apache.dubbo.registry.Registry;
|
import org.apache.dubbo.registry.Registry;
|
||||||
import org.apache.dubbo.registry.RegistryFactory;
|
import org.apache.dubbo.registry.RegistryFactory;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
@ -46,16 +44,12 @@ public class SpringCloudRegistryFactory implements RegistryFactory {
|
|||||||
|
|
||||||
private static ConfigurableApplicationContext applicationContext;
|
private static ConfigurableApplicationContext applicationContext;
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
private final ScheduledExecutorService servicesLookupScheduler;
|
private final ScheduledExecutorService servicesLookupScheduler;
|
||||||
|
|
||||||
private ServiceRegistry<Registration> serviceRegistry;
|
|
||||||
|
|
||||||
private RegistrationFactory registrationFactory;
|
|
||||||
|
|
||||||
private DiscoveryClient discoveryClient;
|
private DiscoveryClient discoveryClient;
|
||||||
|
|
||||||
|
private DubboServiceMetadataRepository dubboServiceMetadataRepository;
|
||||||
|
|
||||||
private volatile boolean initialized = false;
|
private volatile boolean initialized = false;
|
||||||
|
|
||||||
public SpringCloudRegistryFactory() {
|
public SpringCloudRegistryFactory() {
|
||||||
@ -67,17 +61,15 @@ public class SpringCloudRegistryFactory implements RegistryFactory {
|
|||||||
if (initialized || applicationContext == null) {
|
if (initialized || applicationContext == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.serviceRegistry = applicationContext.getBean(ServiceRegistry.class);
|
|
||||||
this.registrationFactory = applicationContext.getBean(RegistrationFactory.class);
|
|
||||||
this.discoveryClient = applicationContext.getBean(DiscoveryClient.class);
|
this.discoveryClient = applicationContext.getBean(DiscoveryClient.class);
|
||||||
|
this.dubboServiceMetadataRepository = applicationContext.getBean(DubboServiceMetadataRepository.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Registry getRegistry(URL url) {
|
public Registry getRegistry(URL url) {
|
||||||
init();
|
init();
|
||||||
return new SpringCloudRegistry(url, serviceRegistry, registrationFactory, discoveryClient,
|
return new SpringCloudRegistry(url, discoveryClient, servicesLookupScheduler,
|
||||||
servicesLookupScheduler, applicationContext);
|
dubboServiceMetadataRepository, applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setApplicationContext(ConfigurableApplicationContext applicationContext) {
|
public static void setApplicationContext(ConfigurableApplicationContext applicationContext) {
|
||||||
|
@ -1,52 +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.springframework.cloud.alibaba.dubbo.registry.apache.zookeeper;
|
|
||||||
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
|
|
||||||
import org.springframework.cloud.zookeeper.serviceregistry.ServiceInstanceRegistration;
|
|
||||||
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zookeeper {@link RegistrationFactory}
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public class ZookeeperRegistrationFactory extends AbstractRegistrationFactory<ZookeeperRegistration> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ZookeeperRegistration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
|
|
||||||
ZookeeperInstance zookeeperInstance = new ZookeeperInstance(serviceInstance.getInstanceId(),
|
|
||||||
serviceInstance.getServiceId(), serviceInstance.getMetadata());
|
|
||||||
|
|
||||||
ZookeeperRegistration registration = ServiceInstanceRegistration
|
|
||||||
.builder()
|
|
||||||
.address(serviceInstance.getHost())
|
|
||||||
.name(serviceInstance.getServiceId())
|
|
||||||
.payload(zookeeperInstance)
|
|
||||||
.port(serviceInstance.getPort())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// To trigger build() method
|
|
||||||
registration.getServiceInstance();
|
|
||||||
|
|
||||||
return registration;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* 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.springframework.cloud.alibaba.dubbo.registry.env;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.WebApplicationType;
|
||||||
|
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.apache.dubbo.common.Constants.DEFAULT_PROTOCOL;
|
||||||
|
import static org.apache.dubbo.config.spring.util.PropertySourcesUtils.getSubProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dubbo {@link WebApplicationType#NONE Non-Web Application} {@link EnvironmentPostProcessor}
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
public class DubboNonWebApplicationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||||
|
|
||||||
|
private static final String DOT = ".";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of default {@link PropertySource} defined in SpringApplication#configurePropertySources method.
|
||||||
|
*/
|
||||||
|
private static final String PROPERTY_SOURCE_NAME = "defaultProperties";
|
||||||
|
|
||||||
|
private static final String SERVER_PORT_PROPERTY_NAME = "server.port";
|
||||||
|
|
||||||
|
private static final String PORT_PROPERTY_NAME = "port";
|
||||||
|
|
||||||
|
private static final String PROTOCOL_PROPERTY_NAME_PREFIX = "dubbo.protocol";
|
||||||
|
|
||||||
|
private static final String PROTOCOL_NAME_PROPERTY_NAME_SUFFIX = DOT + "name";
|
||||||
|
|
||||||
|
private static final String PROTOCOL_PORT_PROPERTY_NAME_SUFFIX = DOT + PORT_PROPERTY_NAME;
|
||||||
|
|
||||||
|
private static final String PROTOCOL_PORT_PROPERTY_NAME = PROTOCOL_PROPERTY_NAME_PREFIX + PROTOCOL_PORT_PROPERTY_NAME_SUFFIX;
|
||||||
|
|
||||||
|
private static final String PROTOCOL_NAME_PROPERTY_NAME = PROTOCOL_PROPERTY_NAME_PREFIX + PROTOCOL_NAME_PROPERTY_NAME_SUFFIX;
|
||||||
|
|
||||||
|
private static final String PROTOCOLS_PROPERTY_NAME_PREFIX = "dubbo.protocols";
|
||||||
|
|
||||||
|
private static final String REST_PROTOCOL = "rest";
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(DubboNonWebApplicationEnvironmentPostProcessor.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||||
|
WebApplicationType webApplicationType = application.getWebApplicationType();
|
||||||
|
|
||||||
|
if (!WebApplicationType.NONE.equals(webApplicationType)) { // Just works in Non-Web Application
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Current application is a Web Application, the process will be ignored.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetServerPort(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset server port property if it's absent, whose value is configured by "dubbbo.protocol.port"
|
||||||
|
* or "dubbo.protcols.rest.port"
|
||||||
|
*
|
||||||
|
* @param environment
|
||||||
|
*/
|
||||||
|
private void resetServerPort(ConfigurableEnvironment environment) {
|
||||||
|
|
||||||
|
String serverPort = environment.getProperty(SERVER_PORT_PROPERTY_NAME, environment.getProperty(PORT_PROPERTY_NAME));
|
||||||
|
|
||||||
|
if (serverPort != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serverPort = getRestPortFromProtocolProperty(environment);
|
||||||
|
|
||||||
|
if (serverPort == null) {
|
||||||
|
serverPort = getRestPortFromProtocolsProperties(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
setServerPort(environment, serverPort);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRestPortFromProtocolProperty(ConfigurableEnvironment environment) {
|
||||||
|
|
||||||
|
String protocol = environment.getProperty(PROTOCOL_NAME_PROPERTY_NAME, DEFAULT_PROTOCOL);
|
||||||
|
|
||||||
|
return isRestProtocol(protocol) ?
|
||||||
|
environment.getProperty(PROTOCOL_PORT_PROPERTY_NAME) :
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRestPortFromProtocolsProperties(ConfigurableEnvironment environment) {
|
||||||
|
|
||||||
|
String restPort = null;
|
||||||
|
|
||||||
|
Map<String, Object> subProperties = getSubProperties(environment, PROTOCOLS_PROPERTY_NAME_PREFIX);
|
||||||
|
|
||||||
|
Properties properties = new Properties();
|
||||||
|
|
||||||
|
properties.putAll(subProperties);
|
||||||
|
|
||||||
|
for (String propertyName : properties.stringPropertyNames()) {
|
||||||
|
if (propertyName.endsWith(PROTOCOL_NAME_PROPERTY_NAME_SUFFIX)) { // protocol name property
|
||||||
|
String protocol = properties.getProperty(propertyName);
|
||||||
|
if (isRestProtocol(protocol)) {
|
||||||
|
String beanName = resolveBeanName(propertyName);
|
||||||
|
if (StringUtils.hasText(beanName)) {
|
||||||
|
restPort = properties.getProperty(beanName + PROTOCOL_PORT_PROPERTY_NAME_SUFFIX);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return restPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveBeanName(String propertyName) {
|
||||||
|
int index = propertyName.indexOf(DOT);
|
||||||
|
return index > -1 ? propertyName.substring(0, index) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setServerPort(ConfigurableEnvironment environment, String serverPort) {
|
||||||
|
if (serverPort == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutablePropertySources propertySources = environment.getPropertySources();
|
||||||
|
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put(SERVER_PORT_PROPERTY_NAME, String.valueOf(serverPort));
|
||||||
|
|
||||||
|
addOrReplace(propertySources, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy from BusEnvironmentPostProcessor#addOrReplace(MutablePropertySources, Map)
|
||||||
|
*
|
||||||
|
* @param propertySources {@link MutablePropertySources}
|
||||||
|
* @param map Default Dubbo Properties
|
||||||
|
*/
|
||||||
|
private void addOrReplace(MutablePropertySources propertySources,
|
||||||
|
Map<String, Object> map) {
|
||||||
|
MapPropertySource target = null;
|
||||||
|
if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
|
||||||
|
PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
|
||||||
|
if (source instanceof MapPropertySource) {
|
||||||
|
target = (MapPropertySource) source;
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
if (!target.containsProperty(key)) {
|
||||||
|
target.getSource().put(key, map.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (target == null) {
|
||||||
|
target = new MapPropertySource(PROPERTY_SOURCE_NAME, map);
|
||||||
|
}
|
||||||
|
if (!propertySources.contains(PROPERTY_SOURCE_NAME)) {
|
||||||
|
propertySources.addLast(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() { // Keep LOWEST_PRECEDENCE
|
||||||
|
return LOWEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRestProtocol(String protocol) {
|
||||||
|
return REST_PROTOCOL.equalsIgnoreCase(protocol);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.cloud.alibaba.dubbo.registry.event;
|
||||||
|
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The before-{@link ServiceRegistry#register(Registration) register} event for {@link ServiceInstance}
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
public class ServiceInstancePreRegisteredEvent extends ApplicationEvent {
|
||||||
|
|
||||||
|
public ServiceInstancePreRegisteredEvent(Registration source) {
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Registration getSource() {
|
||||||
|
return (Registration) super.getSource();
|
||||||
|
}
|
||||||
|
}
|
@ -14,21 +14,26 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.registry;
|
package org.springframework.cloud.alibaba.dubbo.registry.event;
|
||||||
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.client.serviceregistry.Registration;
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default {@link RegistrationFactory}
|
* The after-{@link ServiceRegistry#register(Registration) register} event for {@link Registration}
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
*/
|
*/
|
||||||
public class DefaultRegistrationFactory extends AbstractRegistrationFactory<Registration> {
|
public class ServiceInstanceRegisteredEvent extends EventObject {
|
||||||
|
|
||||||
|
public ServiceInstanceRegisteredEvent(Registration source) {
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Registration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
|
public Registration getSource() {
|
||||||
return new DelegatingRegistration(serviceInstance);
|
return (Registration) super.getSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,53 +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.springframework.cloud.alibaba.dubbo.registry.handler;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.registry.Registry;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dubbo {@link Registry} Spring Cloud Service Id Builder
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public interface DubboRegistryServiceIdHandler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Supports the specified id of Spring Cloud Service or not
|
|
||||||
*
|
|
||||||
* @param serviceId the specified id of Spring Cloud Service
|
|
||||||
* @return if supports, return <code>true</code>, or <code>false</code>
|
|
||||||
*/
|
|
||||||
boolean supports(String serviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the id of Spring Cloud Service
|
|
||||||
*
|
|
||||||
* @param url The Dubbo's {@link URL}
|
|
||||||
* @return non-null
|
|
||||||
*/
|
|
||||||
String createServiceId(URL url);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The instance if {@link ConfigurableApplicationContext} .
|
|
||||||
*
|
|
||||||
* @return non-null
|
|
||||||
*/
|
|
||||||
ConfigurableApplicationContext getContext();
|
|
||||||
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.cloud.alibaba.dubbo.registry.handler;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.Constants;
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static java.lang.System.getProperty;
|
|
||||||
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
|
|
||||||
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
|
|
||||||
import static org.springframework.util.StringUtils.startsWithIgnoreCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Standard {@link DubboRegistryServiceIdHandler}
|
|
||||||
* <p>
|
|
||||||
* The service ID pattern is "${category}:${interface}:${version}:${group}"
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public class StandardDubboRegistryServiceIdHandler implements DubboRegistryServiceIdHandler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The separator for service name that could be changed by the Java Property "dubbo.service.name.separator".
|
|
||||||
*/
|
|
||||||
protected static final String SERVICE_NAME_SEPARATOR = getProperty("dubbo.service.name.separator", ":");
|
|
||||||
|
|
||||||
private final ConfigurableApplicationContext context;
|
|
||||||
|
|
||||||
public StandardDubboRegistryServiceIdHandler(ConfigurableApplicationContext context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String serviceId) {
|
|
||||||
return startsWithIgnoreCase(serviceId, PROVIDERS_CATEGORY) ||
|
|
||||||
startsWithIgnoreCase(serviceId, CONSUMERS_CATEGORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String createServiceId(URL url) {
|
|
||||||
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
|
|
||||||
if (!Objects.equals(category, PROVIDERS_CATEGORY) && !Objects.equals(category, CONSUMERS_CATEGORY)) {
|
|
||||||
category = PROVIDERS_CATEGORY;
|
|
||||||
}
|
|
||||||
return createServiceId(url, category);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConfigurableApplicationContext getContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method maybe override by sub-class.
|
|
||||||
*
|
|
||||||
* @param url The Dubbo's {@link URL}
|
|
||||||
* @param category The category
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected String createServiceId(URL url, String category) {
|
|
||||||
StringBuilder serviceNameBuilder = new StringBuilder(category);
|
|
||||||
appendIfPresent(serviceNameBuilder, url, Constants.INTERFACE_KEY);
|
|
||||||
appendIfPresent(serviceNameBuilder, url, Constants.VERSION_KEY);
|
|
||||||
appendIfPresent(serviceNameBuilder, url, Constants.GROUP_KEY);
|
|
||||||
return serviceNameBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void appendIfPresent(StringBuilder target, URL url, String parameterName) {
|
|
||||||
String parameterValue = url.getParameter(parameterName);
|
|
||||||
appendIfPresent(target, parameterValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void appendIfPresent(StringBuilder target, String parameterValue) {
|
|
||||||
if (StringUtils.hasText(parameterValue)) {
|
|
||||||
target.append(SERVICE_NAME_SEPARATOR).append(parameterValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.cloud.alibaba.dubbo.registry.hashicorp.consul;
|
|
||||||
|
|
||||||
import com.ecwid.consul.v1.agent.model.NewService;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
|
|
||||||
import org.springframework.cloud.consul.discovery.ConsulServerUtils;
|
|
||||||
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ConsulRegistration} {@link RegistrationFactory} implementation
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public class ConsulRegistrationFactory extends AbstractRegistrationFactory<ConsulRegistration> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConsulRegistration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
|
|
||||||
Map<String, String> metadata = getMetadata(serviceInstance);
|
|
||||||
List<String> tags = createTags(metadata);
|
|
||||||
|
|
||||||
NewService service = new NewService();
|
|
||||||
service.setId(serviceInstance.getInstanceId());
|
|
||||||
service.setName(serviceInstance.getServiceId());
|
|
||||||
service.setAddress(serviceInstance.getHost());
|
|
||||||
service.setPort(serviceInstance.getPort());
|
|
||||||
service.setMeta(metadata);
|
|
||||||
service.setTags(tags);
|
|
||||||
|
|
||||||
ConsulDiscoveryProperties properties = applicationContext.getBean(ConsulDiscoveryProperties.class);
|
|
||||||
|
|
||||||
ConsulRegistration registration = new ConsulRegistration(service, properties);
|
|
||||||
return registration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param metadata
|
|
||||||
* @return
|
|
||||||
* @see ConsulServerUtils#getMetadata(java.util.List)
|
|
||||||
*/
|
|
||||||
private List<String> createTags(Map<String, String> metadata) {
|
|
||||||
List<String> tags = new LinkedList<>();
|
|
||||||
for (Map.Entry<String, String> entry : metadata.entrySet()) {
|
|
||||||
String tag = entry.getKey() + "=" + entry.getValue();
|
|
||||||
tags.add(tag);
|
|
||||||
|
|
||||||
}
|
|
||||||
return tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> getMetadata(ServiceInstance serviceInstance) {
|
|
||||||
Map<String, String> metadata = serviceInstance.getMetadata();
|
|
||||||
Set<String> removedKeys = new LinkedHashSet<>();
|
|
||||||
for (String key : metadata.keySet()) {
|
|
||||||
if (key.contains(".")) {
|
|
||||||
removedKeys.add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String removedKey : removedKeys) {
|
|
||||||
metadata.remove(removedKey);
|
|
||||||
}
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +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.springframework.cloud.alibaba.dubbo.registry.netflix.eureka;
|
|
||||||
|
|
||||||
import com.netflix.appinfo.HealthCheckHandler;
|
|
||||||
import com.netflix.discovery.EurekaClientConfig;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.commons.util.InetUtils;
|
|
||||||
import org.springframework.cloud.netflix.eureka.CloudEurekaInstanceConfig;
|
|
||||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
|
||||||
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link EurekaRegistration} Factory
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
public class EurekaRegistrationFactory extends AbstractRegistrationFactory<EurekaRegistration> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EurekaRegistration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
|
|
||||||
CloudEurekaInstanceConfig cloudEurekaInstanceConfig = applicationContext.getBean(CloudEurekaInstanceConfig.class);
|
|
||||||
ObjectProvider<HealthCheckHandler> healthCheckHandler = applicationContext.getBeanProvider(HealthCheckHandler.class);
|
|
||||||
EurekaClientConfig eurekaClientConfig = applicationContext.getBean(EurekaClientConfig.class);
|
|
||||||
InetUtils inetUtils = applicationContext.getBean(InetUtils.class);
|
|
||||||
EurekaInstanceConfigBean eurekaInstanceConfigBean = new EurekaInstanceConfigBean(inetUtils);
|
|
||||||
BeanUtils.copyProperties(cloudEurekaInstanceConfig, eurekaInstanceConfigBean);
|
|
||||||
String serviceId = serviceInstance.getServiceId();
|
|
||||||
eurekaInstanceConfigBean.setInstanceId(serviceInstance.getInstanceId());
|
|
||||||
eurekaInstanceConfigBean.setVirtualHostName(serviceId);
|
|
||||||
eurekaInstanceConfigBean.setSecureVirtualHostName(serviceId);
|
|
||||||
eurekaInstanceConfigBean.setAppname(serviceId);
|
|
||||||
eurekaInstanceConfigBean.setHostname(serviceInstance.getHost());
|
|
||||||
eurekaInstanceConfigBean.setNonSecurePort(serviceInstance.getPort());
|
|
||||||
eurekaInstanceConfigBean.setMetadataMap(serviceInstance.getMetadata());
|
|
||||||
|
|
||||||
return EurekaRegistration.builder(eurekaInstanceConfigBean)
|
|
||||||
.with(healthCheckHandler)
|
|
||||||
.with(eurekaClientConfig, applicationContext)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,7 +25,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.DubboRestServiceMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.validation.DataBinder;
|
import org.springframework.validation.DataBinder;
|
||||||
@ -54,7 +54,7 @@ public class DubboGenericServiceFactory {
|
|||||||
|
|
||||||
private final ConcurrentMap<Integer, ReferenceBean<GenericService>> cache = new ConcurrentHashMap<>();
|
private final ConcurrentMap<Integer, ReferenceBean<GenericService>> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public GenericService create(DubboServiceMetadata dubboServiceMetadata,
|
public GenericService create(DubboRestServiceMetadata dubboServiceMetadata,
|
||||||
Map<String, Object> dubboTranslatedAttributes) {
|
Map<String, Object> dubboTranslatedAttributes) {
|
||||||
|
|
||||||
ReferenceBean<GenericService> referenceBean = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTranslatedAttributes);
|
ReferenceBean<GenericService> referenceBean = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTranslatedAttributes);
|
||||||
|
@ -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.springframework.cloud.alibaba.dubbo.service;
|
||||||
|
|
||||||
|
import org.apache.dubbo.config.ApplicationConfig;
|
||||||
|
import org.apache.dubbo.config.ProtocolConfig;
|
||||||
|
import org.apache.dubbo.config.ServiceConfig;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link DubboMetadataConfigService} exporter
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DubboMetadataConfigServiceExporter {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationConfig applicationConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Supplier<ProtocolConfig> protocolConfigSupplier;
|
||||||
|
|
||||||
|
@Value("${spring.application.name:application}")
|
||||||
|
private String currentApplicationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ServiceConfig of DubboMetadataConfigService to be exported, can be nullable.
|
||||||
|
*/
|
||||||
|
private ServiceConfig<DubboMetadataConfigService> serviceConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* export {@link DubboMetadataConfigService} as Dubbo service
|
||||||
|
*/
|
||||||
|
public void export() {
|
||||||
|
|
||||||
|
if (serviceConfig != null && serviceConfig.isExported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(dubboMetadataConfigService.getServiceRestMetadata())) {
|
||||||
|
// If there is no REST metadata, DubboMetadataConfigService will not be exported.
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("There is no REST metadata, the Dubbo service[{}] will not be exported.",
|
||||||
|
dubboMetadataConfigService.getClass().getName());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceConfig = new ServiceConfig<>();
|
||||||
|
|
||||||
|
serviceConfig.setInterface(DubboMetadataConfigService.class);
|
||||||
|
// Use current Spring application name as the Dubbo Service version
|
||||||
|
serviceConfig.setVersion(currentApplicationName);
|
||||||
|
serviceConfig.setRef(dubboMetadataConfigService);
|
||||||
|
serviceConfig.setApplication(applicationConfig);
|
||||||
|
serviceConfig.setProtocol(protocolConfigSupplier.get());
|
||||||
|
|
||||||
|
serviceConfig.export();
|
||||||
|
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("The Dubbo service[{}] has been exported.", serviceConfig.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unexport {@link DubboMetadataConfigService}
|
||||||
|
*/
|
||||||
|
public void unexport() {
|
||||||
|
|
||||||
|
if (serviceConfig == null || serviceConfig.isUnexported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceConfig.unexport();
|
||||||
|
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("The Dubbo service[{}] has been unexported.", serviceConfig.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,13 +16,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.service;
|
package org.springframework.cloud.alibaba.dubbo.service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
||||||
|
import org.springframework.cloud.alibaba.dubbo.util.JSONUtils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -41,12 +39,8 @@ public class PublishingDubboMetadataConfigService implements DubboMetadataConfig
|
|||||||
*/
|
*/
|
||||||
private final Set<ServiceRestMetadata> serviceRestMetadata = new LinkedHashSet<>();
|
private final Set<ServiceRestMetadata> serviceRestMetadata = new LinkedHashSet<>();
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
@Autowired
|
||||||
|
private JSONUtils jsonUtils;
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish the {@link Set} of {@link ServiceRestMetadata}
|
* Publish the {@link Set} of {@link ServiceRestMetadata}
|
||||||
@ -64,12 +58,8 @@ public class PublishingDubboMetadataConfigService implements DubboMetadataConfig
|
|||||||
@Override
|
@Override
|
||||||
public String getServiceRestMetadata() {
|
public String getServiceRestMetadata() {
|
||||||
String serviceRestMetadataJsonConfig = null;
|
String serviceRestMetadataJsonConfig = null;
|
||||||
try {
|
if (!isEmpty(serviceRestMetadata)) {
|
||||||
if (!isEmpty(serviceRestMetadata)) {
|
serviceRestMetadataJsonConfig = jsonUtils.toJSON(serviceRestMetadata);
|
||||||
serviceRestMetadataJsonConfig = objectMapper.writeValueAsString(serviceRestMetadata);
|
|
||||||
}
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
return serviceRestMetadataJsonConfig;
|
return serviceRestMetadataJsonConfig;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.springframework.cloud.alibaba.dubbo.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON Utilities class
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
public class JSONUtils {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSON(Object object) {
|
||||||
|
String jsonContent = null;
|
||||||
|
try {
|
||||||
|
jsonContent = objectMapper.writeValueAsString(object);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
if (logger.isErrorEnabled()) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> toList(String json) {
|
||||||
|
List<String> list = Collections.emptyList();
|
||||||
|
try {
|
||||||
|
if (StringUtils.hasText(json)) {
|
||||||
|
list = objectMapper.readValue(json, List.class);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (logger.isErrorEnabled()) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,15 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration,\
|
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration,\
|
||||||
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration,\
|
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration,\
|
||||||
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataEventHandlingAutoConfiguration,\
|
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration,\
|
||||||
|
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationNonWebApplicationAutoConfiguration,\
|
||||||
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\
|
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\
|
||||||
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceAutoConfiguration
|
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceAutoConfiguration
|
||||||
|
|
||||||
|
|
||||||
org.springframework.context.ApplicationContextInitializer=\
|
org.springframework.context.ApplicationContextInitializer=\
|
||||||
org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer
|
org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer
|
||||||
|
|
||||||
org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory=\
|
|
||||||
org.springframework.cloud.alibaba.dubbo.registry.netflix.eureka.EurekaRegistrationFactory,\
|
org.springframework.boot.env.EnvironmentPostProcessor=\
|
||||||
org.springframework.cloud.alibaba.dubbo.registry.apache.zookeeper.ZookeeperRegistrationFactory,\
|
org.springframework.cloud.alibaba.dubbo.registry.env.DubboNonWebApplicationEnvironmentPostProcessor
|
||||||
org.springframework.cloud.alibaba.dubbo.registry.hashicorp.consul.ConsulRegistrationFactory
|
|
@ -20,6 +20,7 @@
|
|||||||
<module>spring-cloud-dubbo-provider-sample</module>
|
<module>spring-cloud-dubbo-provider-sample</module>
|
||||||
<module>spring-cloud-dubbo-consumer-sample</module>
|
<module>spring-cloud-dubbo-consumer-sample</module>
|
||||||
<module>spring-cloud-dubbo-provider-web-sample</module>
|
<module>spring-cloud-dubbo-provider-web-sample</module>
|
||||||
|
<module>spring-cloud-dubbo-servlet-gateway-sample</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.springframework.cloud.alibaba.dubbo.bootstrap;
|
package org.springframework.cloud.alibaba.dubbo.bootstrap;
|
||||||
|
|
||||||
import org.apache.dubbo.config.annotation.Reference;
|
import org.apache.dubbo.config.annotation.Reference;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
@ -52,7 +53,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
|
|||||||
@EnableFeignClients
|
@EnableFeignClients
|
||||||
public class DubboSpringCloudConsumerBootstrap {
|
public class DubboSpringCloudConsumerBootstrap {
|
||||||
|
|
||||||
@Reference(version = "1.0.0")
|
@Reference(version = "1.0.0", protocol = "dubbo")
|
||||||
private RestService restService;
|
private RestService restService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -94,7 +95,7 @@ public class DubboSpringCloudConsumerBootstrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FeignClient("${provider.application.name}")
|
@FeignClient("${provider.application.name}")
|
||||||
@DubboTransported()
|
@DubboTransported(protocol = "dubbo")
|
||||||
public interface DubboFeignRestService {
|
public interface DubboFeignRestService {
|
||||||
|
|
||||||
@GetMapping(value = "/param")
|
@GetMapping(value = "/param")
|
||||||
|
@ -9,4 +9,4 @@ server:
|
|||||||
|
|
||||||
provider:
|
provider:
|
||||||
application:
|
application:
|
||||||
name: spring-cloud-alibaba-dubbo-web-provider
|
name: spring-cloud-alibaba-dubbo-provider
|
@ -17,6 +17,13 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Resolve the Dubbo REST RPC issue -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Resolve the Spring Cloud registration issue -->
|
<!-- Resolve the Spring Cloud registration issue -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.bootstrap;
|
package org.springframework.cloud.alibaba.dubbo.bootstrap;
|
||||||
|
|
||||||
|
import org.springframework.boot.WebApplicationType;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
@ -30,6 +31,7 @@ public class DubboSpringCloudProviderBootstrap {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new SpringApplicationBuilder(DubboSpringCloudProviderBootstrap.class)
|
new SpringApplicationBuilder(DubboSpringCloudProviderBootstrap.class)
|
||||||
.properties("spring.profiles.active=nacos")
|
.properties("spring.profiles.active=nacos")
|
||||||
|
.web(WebApplicationType.NONE)
|
||||||
.run(args);
|
.run(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: spring-cloud-alibaba-dubbo-web-provider
|
name: spring-cloud-alibaba-dubbo-provider
|
||||||
main:
|
main:
|
||||||
allow-bean-definition-overriding: true
|
allow-bean-definition-overriding: true
|
||||||
|
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-alibaba-dubbo-examples</artifactId>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<version>0.2.2.BUILD-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dubbo-servlet-gateway-sample</artifactId>
|
||||||
|
<name>Spring Cloud Dubbo Servlet Gateway Sample</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sample API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Cloud Open Feign -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.springframework.cloud.alibaba.dubbo.bootstrap;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dubbo Spring Cloud Servlet Gateway Bootstrap
|
||||||
|
*/
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@EnableFeignClients
|
||||||
|
@ServletComponentScan(basePackages = "org.springframework.cloud.alibaba.dubbo.gateway")
|
||||||
|
public class DubboSpringCloudServletGatewayBootstrap {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new SpringApplicationBuilder(DubboSpringCloudServletGatewayBootstrap.class)
|
||||||
|
.properties("spring.profiles.active=nacos")
|
||||||
|
.run(args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,188 @@
|
|||||||
|
//package org.springframework.cloud.alibaba.dubbo.gateway;
|
||||||
|
//
|
||||||
|
//import org.apache.commons.lang.StringUtils;
|
||||||
|
//import org.apache.dubbo.rpc.service.GenericException;
|
||||||
|
//import org.apache.dubbo.rpc.service.GenericService;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.http.MutableHttpServerRequest;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContext;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
|
||||||
|
//import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
|
||||||
|
//import org.springframework.http.HttpHeaders;
|
||||||
|
//import org.springframework.http.HttpRequest;
|
||||||
|
//import org.springframework.util.AntPathMatcher;
|
||||||
|
//import org.springframework.util.CollectionUtils;
|
||||||
|
//import org.springframework.util.PathMatcher;
|
||||||
|
//import org.springframework.util.StreamUtils;
|
||||||
|
//import org.springframework.web.util.UriComponents;
|
||||||
|
//
|
||||||
|
//import javax.servlet.ServletException;
|
||||||
|
//import javax.servlet.ServletInputStream;
|
||||||
|
//import javax.servlet.annotation.WebServlet;
|
||||||
|
//import javax.servlet.http.HttpServlet;
|
||||||
|
//import javax.servlet.http.HttpServletRequest;
|
||||||
|
//import javax.servlet.http.HttpServletResponse;
|
||||||
|
//import java.io.IOException;
|
||||||
|
//import java.net.URI;
|
||||||
|
//import java.net.URISyntaxException;
|
||||||
|
//import java.util.*;
|
||||||
|
//
|
||||||
|
//import static org.springframework.web.util.UriComponentsBuilder.fromUriString;
|
||||||
|
//
|
||||||
|
//@WebServlet(urlPatterns = "/dsc/*")
|
||||||
|
//public class DubboGatewayServlet extends HttpServlet {
|
||||||
|
//
|
||||||
|
// private final DubboServiceMetadataRepository repository;
|
||||||
|
//
|
||||||
|
// private final DubboTransportedMetadata dubboTransportedMetadata;
|
||||||
|
//
|
||||||
|
// private final DubboGenericServiceFactory serviceFactory;
|
||||||
|
//
|
||||||
|
// private final DubboGenericServiceExecutionContextFactory contextFactory;
|
||||||
|
//
|
||||||
|
// private final PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
|
//
|
||||||
|
// public DubboGatewayServlet(DubboServiceMetadataRepository repository,
|
||||||
|
// DubboGenericServiceFactory serviceFactory,
|
||||||
|
// DubboGenericServiceExecutionContextFactory contextFactory) {
|
||||||
|
// this.repository = repository;
|
||||||
|
// this.dubboTransportedMetadata = new DubboTransportedMetadata();
|
||||||
|
// dubboTransportedMetadata.setProtocol("dubbo");
|
||||||
|
// dubboTransportedMetadata.setCluster("failover");
|
||||||
|
// this.serviceFactory = serviceFactory;
|
||||||
|
// this.contextFactory = contextFactory;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
//
|
||||||
|
// // /g/{app-name}/{rest-path}
|
||||||
|
// String requestURI = request.getRequestURI();
|
||||||
|
// // /g/
|
||||||
|
// String servletPath = request.getServletPath();
|
||||||
|
//
|
||||||
|
// String part = StringUtils.substringAfter(requestURI, servletPath);
|
||||||
|
//
|
||||||
|
// String serviceName = StringUtils.substringBetween(part, "/", "/");
|
||||||
|
//
|
||||||
|
// // App name= spring-cloud-alibaba-dubbo-web-provider (127.0.0.1:8080)
|
||||||
|
//
|
||||||
|
// String restPath = StringUtils.substringAfter(part, serviceName);
|
||||||
|
//
|
||||||
|
// // 初始化 serviceName 的 REST 请求元数据
|
||||||
|
// repository.initialize(serviceName);
|
||||||
|
// // 将 HttpServletRequest 转化为 RequestMetadata
|
||||||
|
// RequestMetadata clientMetadata = buildRequestMetadata(request, restPath);
|
||||||
|
//
|
||||||
|
// DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, clientMetadata);
|
||||||
|
//
|
||||||
|
// if (dubboServiceMetadata == null) {
|
||||||
|
// // if DubboServiceMetadata is not found, executes next
|
||||||
|
// throw new ServletException("DubboServiceMetadata can't be found!");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// RestMethodMetadata dubboRestMethodMetadata = dubboServiceMetadata.getRestMethodMetadata();
|
||||||
|
//
|
||||||
|
// GenericService genericService = serviceFactory.create(dubboServiceMetadata, dubboTransportedMetadata);
|
||||||
|
//
|
||||||
|
// // TODO: Get the Request Body from HttpServletRequest
|
||||||
|
// byte[] body = getRequestBody(request);
|
||||||
|
//
|
||||||
|
// MutableHttpServerRequest httpServerRequest = new MutableHttpServerRequest(new HttpRequestAdapter(request), body);
|
||||||
|
//
|
||||||
|
//// customizeRequest(httpServerRequest, dubboRestMethodMetadata, clientMetadata);
|
||||||
|
//
|
||||||
|
// DubboGenericServiceExecutionContext context = contextFactory.create(dubboRestMethodMetadata, httpServerRequest);
|
||||||
|
//
|
||||||
|
// Object result = null;
|
||||||
|
// GenericException exception = null;
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// result = genericService.$invoke(context.getMethodName(), context.getParameterTypes(), context.getParameters());
|
||||||
|
// } catch (GenericException e) {
|
||||||
|
// exception = e;
|
||||||
|
// }
|
||||||
|
// response.getWriter().println(result);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private byte[] getRequestBody(HttpServletRequest request) throws IOException {
|
||||||
|
// ServletInputStream inputStream = request.getInputStream();
|
||||||
|
// return StreamUtils.copyToByteArray(inputStream);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private static class HttpRequestAdapter implements HttpRequest {
|
||||||
|
//
|
||||||
|
// private final HttpServletRequest request;
|
||||||
|
//
|
||||||
|
// private HttpRequestAdapter(HttpServletRequest request) {
|
||||||
|
// this.request = request;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public String getMethodValue() {
|
||||||
|
// return request.getMethod();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public URI getURI() {
|
||||||
|
// try {
|
||||||
|
// return new URI(request.getRequestURL().toString() + "?" + request.getQueryString());
|
||||||
|
// } catch (URISyntaxException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// throw new RuntimeException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public HttpHeaders getHeaders() {
|
||||||
|
// return new HttpHeaders();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// protected void customizeRequest(MutableHttpServerRequest httpServerRequest,
|
||||||
|
//// RestMethodMetadata dubboRestMethodMetadata, RequestMetadata clientMetadata) {
|
||||||
|
////
|
||||||
|
//// RequestMetadata dubboRequestMetadata = dubboRestMethodMetadata.getRequest();
|
||||||
|
//// String pathPattern = dubboRequestMetadata.getPath();
|
||||||
|
////
|
||||||
|
//// Map<String, String> pathVariables = pathMatcher.extractUriTemplateVariables(pathPattern, httpServerRequest.getPath());
|
||||||
|
////
|
||||||
|
//// if (!CollectionUtils.isEmpty(pathVariables)) {
|
||||||
|
//// // Put path variables Map into query parameters Map
|
||||||
|
//// httpServerRequest.params(pathVariables);
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
// private RequestMetadata buildRequestMetadata(HttpServletRequest request, String restPath) {
|
||||||
|
// UriComponents uriComponents = fromUriString(request.getRequestURI()).build(true);
|
||||||
|
// RequestMetadata requestMetadata = new RequestMetadata();
|
||||||
|
// requestMetadata.setPath(restPath);
|
||||||
|
// requestMetadata.setMethod(request.getMethod());
|
||||||
|
// requestMetadata.setParams(getParams(request));
|
||||||
|
// requestMetadata.setHeaders(getHeaders(request));
|
||||||
|
// return requestMetadata;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private Map<String, List<String>> getHeaders(HttpServletRequest request) {
|
||||||
|
// Map<String, List<String>> map = new LinkedHashMap<>();
|
||||||
|
// Enumeration<String> headerNames = request.getHeaderNames();
|
||||||
|
// while (headerNames.hasMoreElements()) {
|
||||||
|
// String headerName = headerNames.nextElement();
|
||||||
|
// Enumeration<String> headerValues = request.getHeaders(headerName);
|
||||||
|
// map.put(headerName, Collections.list(headerValues));
|
||||||
|
// }
|
||||||
|
// return map;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private Map<String, List<String>> getParams(HttpServletRequest request) {
|
||||||
|
// Map<String, List<String>> map = new LinkedHashMap<>();
|
||||||
|
// for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
|
||||||
|
// map.put(entry.getKey(), Arrays.asList(entry.getValue()));
|
||||||
|
// }
|
||||||
|
// return map;
|
||||||
|
// }
|
||||||
|
//}
|
@ -0,0 +1,12 @@
|
|||||||
|
dubbo:
|
||||||
|
registry:
|
||||||
|
# The Spring Cloud Dubbo's registry extension
|
||||||
|
address: spring-cloud://localhost
|
||||||
|
# The traditional Dubbo's registry
|
||||||
|
# address: zookeeper://127.0.0.1:2181
|
||||||
|
server:
|
||||||
|
port: 0
|
||||||
|
|
||||||
|
provider:
|
||||||
|
application:
|
||||||
|
name: spring-cloud-alibaba-dubbo-web-provider
|
@ -0,0 +1,70 @@
|
|||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: spring-cloud-alibaba-dubbo-servlet-gateway
|
||||||
|
main:
|
||||||
|
allow-bean-definition-overriding: true
|
||||||
|
|
||||||
|
|
||||||
|
# default disable all
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
enabled: false
|
||||||
|
register-enabled: false
|
||||||
|
zookeeper:
|
||||||
|
enabled: false
|
||||||
|
consul:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
eureka:
|
||||||
|
client:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
ribbon:
|
||||||
|
nacos:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
---
|
||||||
|
spring:
|
||||||
|
profiles: nacos
|
||||||
|
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
enabled: true
|
||||||
|
register-enabled: true
|
||||||
|
server-addr: 127.0.0.1:8848
|
||||||
|
|
||||||
|
ribbon:
|
||||||
|
nacos:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
---
|
||||||
|
spring:
|
||||||
|
profiles: eureka
|
||||||
|
|
||||||
|
eureka:
|
||||||
|
client:
|
||||||
|
enabled: true
|
||||||
|
service-url:
|
||||||
|
defaultZone: http://127.0.0.1:8761/eureka/
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
spring:
|
||||||
|
profiles: zookeeper
|
||||||
|
cloud:
|
||||||
|
zookeeper:
|
||||||
|
enabled: true
|
||||||
|
connect-string: 127.0.0.1:2181
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
spring:
|
||||||
|
profiles: consul
|
||||||
|
|
||||||
|
cloud:
|
||||||
|
consul:
|
||||||
|
enabled: true
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 8500
|
@ -16,12 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.nacos;
|
package org.springframework.cloud.alibaba.nacos;
|
||||||
|
|
||||||
import org.springframework.boot.ApplicationRunner;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration;
|
import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration;
|
||||||
@ -77,26 +75,4 @@ public class NacosDiscoveryAutoConfiguration {
|
|||||||
return new NacosAutoServiceRegistration(registry,
|
return new NacosAutoServiceRegistration(registry,
|
||||||
autoServiceRegistrationProperties, registration);
|
autoServiceRegistrationProperties, registration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnBean(NacosAutoServiceRegistration.class) // NacosAutoServiceRegistration
|
|
||||||
// should be present
|
|
||||||
@ConditionalOnNotWebApplication // Not Web Application
|
|
||||||
public ApplicationRunner applicationRunner(
|
|
||||||
NacosAutoServiceRegistration nacosAutoServiceRegistration) {
|
|
||||||
return args -> {
|
|
||||||
// WebServerInitializedEvent should not be multicast in Non-Web environment.
|
|
||||||
// Whatever, NacosAutoServiceRegistration must be checked it's running or not.
|
|
||||||
if (!nacosAutoServiceRegistration.isRunning()) { // If it's not running, let
|
|
||||||
// it start.
|
|
||||||
// FIXME: Please make sure "spring.cloud.nacos.discovery.port" must be
|
|
||||||
// configured on an available port,
|
|
||||||
// or the startup or Nacos health check will be failed.
|
|
||||||
nacosAutoServiceRegistration.start();
|
|
||||||
// NacosAutoServiceRegistration will be stopped after its destroy() method
|
|
||||||
// is invoked.
|
|
||||||
// @PreDestroy destroy() -> stop()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user