Enhancement and Bugfix in 2.7.1 ( Part 3 ) (#3675)

* Polish /apache/incubator-dubbo#1306  : @Reference bean name conflict

* Polish /apache/incubator-dubbo#3582 : service register support on nacos

* Polish /apache/incubator-dubbo#3582 : Add license header and remove hard-code version

* Polish /apache/incubator-dubbo#3582 : Remove junit

* Polish /apache/incubator-dubbo#3582 : Translate to English
This commit is contained in:
Mercy Ma 2019-03-15 17:14:08 +08:00 committed by Ian Luo
parent fcdf9c8ce7
commit 7fefb8145c
20 changed files with 1288 additions and 148 deletions

View File

@ -0,0 +1,142 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.registry.Registry;
import org.springframework.core.env.Environment;
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
import static org.apache.dubbo.common.Constants.DEFAULT_PROTOCOL;
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName;
import static org.springframework.util.StringUtils.arrayToCommaDelimitedString;
import static org.springframework.util.StringUtils.hasText;
/**
* The Bean Name Builder for the annotations {@link Service} and {@link Reference}
* <p>
* The naming rule is consistent with the the implementation {@link Registry} that is based on the service-name aware
* infrastructure, e.g Spring Cloud, Cloud Native and so on.
* <p>
* The pattern of bean name : ${category}:${protocol}:${serviceInterface}:${version}:${group}.
* <p>
* ${version} and ${group} are optional.
*
* @since 2.6.6
*/
class AnnotationBeanNameBuilder {
private static final String SEPARATOR = ":";
// Required properties
private final String category;
private final String protocol;
private final String interfaceClassName;
// Optional properties
private String version;
private String group;
private Environment environment;
private AnnotationBeanNameBuilder(String category, String protocol, String interfaceClassName) {
this.category = category;
this.protocol = protocol;
this.interfaceClassName = interfaceClassName;
}
private AnnotationBeanNameBuilder(Service service, Class<?> interfaceClass) {
this(PROVIDERS_CATEGORY, resolveProtocol(service.protocol()), resolveInterfaceName(service, interfaceClass));
this.group(service.group());
this.version(service.version());
}
private AnnotationBeanNameBuilder(Reference reference, Class<?> interfaceClass) {
this(CONSUMERS_CATEGORY, resolveProtocol(reference.protocol()), resolveInterfaceName(reference, interfaceClass));
this.group(reference.group());
this.version(reference.version());
}
public static AnnotationBeanNameBuilder create(Service service, Class<?> interfaceClass) {
return new AnnotationBeanNameBuilder(service, interfaceClass);
}
public static AnnotationBeanNameBuilder create(Reference reference, Class<?> interfaceClass) {
return new AnnotationBeanNameBuilder(reference, interfaceClass);
}
private static void append(StringBuilder builder, String value) {
if (hasText(value)) {
builder.append(SEPARATOR).append(value);
}
}
public AnnotationBeanNameBuilder group(String group) {
this.group = group;
return this;
}
public AnnotationBeanNameBuilder version(String version) {
this.version = version;
return this;
}
public AnnotationBeanNameBuilder environment(Environment environment) {
this.environment = environment;
return this;
}
/**
* Resolve the protocol
*
* @param protocols one or more protocols
* @return if <code>protocols</code> == <code>null</code>, it will return
* {@link Constants#DEFAULT_PROTOCOL "dubbo"} as the default protocol
* @see Constants#DEFAULT_PROTOCOL
*/
private static String resolveProtocol(String... protocols) {
String protocol = arrayToCommaDelimitedString(protocols);
return hasText(protocol) ? protocol : DEFAULT_PROTOCOL;
}
/**
* Build bean name while resolve the placeholders if possible.
*
* @return pattern : ${category}:${protocol}:${serviceInterface}:${version}:${group}
*/
public String build() {
// Append the required properties
StringBuilder beanNameBuilder = new StringBuilder(category);
append(beanNameBuilder, protocol);
append(beanNameBuilder, interfaceClassName);
// Append the optional properties
append(beanNameBuilder, version);
append(beanNameBuilder, group);
String beanName = beanNameBuilder.toString();
// Resolve placeholders
return environment != null ? environment.resolvePlaceholders(beanName) : beanName;
}
}

View File

@ -188,7 +188,9 @@ public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBean
private String buildReferencedBeanName(Reference reference, Class<?> injectedType) {
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(reference, injectedType, getEnvironment());
AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(reference, injectedType);
builder.environment(getEnvironment());
return getEnvironment().resolvePlaceholders(builder.build());
}
@ -261,4 +263,4 @@ public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBean
this.injectedFieldReferenceBeanCache.clear();
this.injectedMethodReferenceBeanCache.clear();
}
}
}

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner;
@ -290,8 +289,9 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr
*/
private String generateServiceBeanName(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) {
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(service, interfaceClass, environment);
AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(service, interfaceClass);
builder.environment(environment);
return builder.build();
@ -316,8 +316,9 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr
}
if (interfaceClass == null) {
Class<?>[] allInterfaces = annotatedServiceBeanClass.getInterfaces();
// Find all interfaces from the annotated class
// To resolve an issue : https://github.com/apache/incubator-dubbo/issues/3251
Class<?>[] allInterfaces = ClassUtils.getAllInterfacesForClass(annotatedServiceBeanClass);
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
@ -435,11 +436,6 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(service.methods());
if (!methodConfigs.isEmpty()) {
builder.addPropertyValue("methods", methodConfigs);
}
return builder.getBeanDefinition();
}
@ -490,4 +486,4 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr
this.classLoader = classLoader;
}
}
}

View File

@ -1,113 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName;
/**
* Dubbo {@link Service @Service} Bean Builder
*
* @see Service
* @see Reference
* @see ServiceBean
* @see ReferenceBean
* @since 2.6.5
*/
class ServiceBeanNameBuilder {
private static final String SEPARATOR = ":";
private final String interfaceClassName;
private final Environment environment;
// Optional
private String version;
private String group;
private ServiceBeanNameBuilder(String interfaceClassName, Environment environment) {
this.interfaceClassName = interfaceClassName;
this.environment = environment;
}
private ServiceBeanNameBuilder(Class<?> interfaceClass, Environment environment) {
this(interfaceClass.getName(), environment);
}
private ServiceBeanNameBuilder(Service service, Class<?> interfaceClass, Environment environment) {
this(resolveInterfaceName(service, interfaceClass), environment);
this.group(service.group());
this.version(service.version());
}
private ServiceBeanNameBuilder(Reference reference, Class<?> interfaceClass, Environment environment) {
this(resolveInterfaceName(reference, interfaceClass), environment);
this.group(reference.group());
this.version(reference.version());
}
public static ServiceBeanNameBuilder create(Class<?> interfaceClass, Environment environment) {
return new ServiceBeanNameBuilder(interfaceClass, environment);
}
public static ServiceBeanNameBuilder create(Service service, Class<?> interfaceClass, Environment environment) {
return new ServiceBeanNameBuilder(service, interfaceClass, environment);
}
public static ServiceBeanNameBuilder create(Reference reference, Class<?> interfaceClass, Environment environment) {
return new ServiceBeanNameBuilder(reference, interfaceClass, environment);
}
private static void append(StringBuilder builder, String value) {
if (StringUtils.hasText(value)) {
builder.append(SEPARATOR).append(value);
}
}
public ServiceBeanNameBuilder group(String group) {
this.group = group;
return this;
}
public ServiceBeanNameBuilder version(String version) {
this.version = version;
return this;
}
public String build() {
StringBuilder beanNameBuilder = new StringBuilder("ServiceBean");
// Required
append(beanNameBuilder, interfaceClassName);
// Optional
append(beanNameBuilder, version);
append(beanNameBuilder, group);
// Build
String rawBeanName = beanNameBuilder.toString();
// Resolve placeholders
return environment.resolvePlaceholders(rawBeanName);
}
}

View File

@ -16,29 +16,31 @@
*/
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.api.DemoService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.ReflectionUtils;
import static org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationBeanNameBuilderTest.GROUP;
import static org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationBeanNameBuilderTest.VERSION;
/**
* {@link ServiceBeanNameBuilder} Test
* {@link AnnotationBeanNameBuilder} Test
*
* @see ServiceBeanNameBuilder
* @since 2.6.5
* @see AnnotationBeanNameBuilder
* @since 2.6.6
*/
@Service(interfaceClass = DemoService.class, group = ServiceBeanNameBuilderTest.GROUP, version = ServiceBeanNameBuilderTest.VERSION,
@Service(interfaceClass = DemoService.class, group = GROUP, version = VERSION,
application = "application", module = "module", registry = {"1", "2", "3"})
public class ServiceBeanNameBuilderTest {
public class AnnotationBeanNameBuilderTest {
@Reference(interfaceClass = DemoService.class, group = "DUBBO", version = "1.0.0",
@Reference(interfaceClass = DemoService.class, group = "DUBBO", version = "${dubbo.version}",
application = "application", module = "module", registry = {"1", "2", "3"})
static final Class<?> INTERFACE_CLASS = DemoService.class;
@ -46,30 +48,36 @@ public class ServiceBeanNameBuilderTest {
static final String VERSION = "1.0.0";
static final String BEAN_NAME = "ServiceBean:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO";
private MockEnvironment environment;
private MockEnvironment environment = new MockEnvironment();
@Test
public void testRequiredAttributes() {
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(INTERFACE_CLASS, environment);
Assertions.assertEquals("ServiceBean:org.apache.dubbo.config.spring.api.DemoService", builder.build());
@Before
public void prepare() {
environment = new MockEnvironment();
environment.setProperty("dubbo.version", "1.0.0");
}
@Test
public void testServiceAnnotation() {
Service service = AnnotationUtils.getAnnotation(ServiceBeanNameBuilderTest.class, Service.class);
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(service, INTERFACE_CLASS, environment);
Assertions.assertEquals(BEAN_NAME,
Service service = AnnotationUtils.getAnnotation(AnnotationBeanNameBuilderTest.class, Service.class);
AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(service, INTERFACE_CLASS);
Assert.assertEquals("providers:dubbo:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO",
builder.build());
builder.environment(environment);
Assert.assertEquals("providers:dubbo:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO",
builder.build());
}
@Test
public void testReferenceAnnotation() {
Reference reference = AnnotationUtils.getAnnotation(ReflectionUtils.findField(ServiceBeanNameBuilderTest.class, "INTERFACE_CLASS"), Reference.class);
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(reference, INTERFACE_CLASS, environment);
Assertions.assertEquals(BEAN_NAME,
Reference reference = AnnotationUtils.getAnnotation(ReflectionUtils.findField(AnnotationBeanNameBuilderTest.class, "INTERFACE_CLASS"), Reference.class);
AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(reference, INTERFACE_CLASS);
Assert.assertEquals("consumers:dubbo:org.apache.dubbo.config.spring.api.DemoService:${dubbo.version}:DUBBO",
builder.build());
builder.environment(environment);
Assert.assertEquals("consumers:dubbo:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO",
builder.build());
}
}
}

View File

@ -0,0 +1,153 @@
<!--
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.
-->
<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>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry</artifactId>
<version>2.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<name>${project.artifactId}</name>
<description>The Nacos registry module of Dubbo project</description>
<properties>
<nacos.version>0.9.0</nacos.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-api</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
<optional>true</optional>
</dependency>
<!-- Test Libraries -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-spring</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-netty4</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<!-- REST support dependencies -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-netty4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,530 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.nacos;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.registry.NotifyListener;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.support.FailbackRegistry;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
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.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.Constants.ADMIN_PROTOCOL;
import static org.apache.dubbo.common.Constants.CATEGORY_KEY;
import static org.apache.dubbo.common.Constants.CONFIGURATORS_CATEGORY;
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
import static org.apache.dubbo.common.Constants.DEFAULT_CATEGORY;
import static org.apache.dubbo.common.Constants.GROUP_KEY;
import static org.apache.dubbo.common.Constants.INTERFACE_KEY;
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static org.apache.dubbo.common.Constants.ROUTERS_CATEGORY;
import static org.apache.dubbo.common.Constants.VERSION_KEY;
/**
* Nacos {@link Registry}
*
* @see #SERVICE_NAME_SEPARATOR
* @see #PAGINATION_SIZE
* @see #LOOKUP_INTERVAL
* @since 2.6.5
*/
public class NacosRegistry extends FailbackRegistry {
/**
* All supported categories
*/
private static final String[] ALL_SUPPORTED_CATEGORIES = of(
PROVIDERS_CATEGORY,
CONSUMERS_CATEGORY,
ROUTERS_CATEGORY,
CONFIGURATORS_CATEGORY
);
private static final int CATEGORY_INDEX = 0;
private static final int SERVICE_INTERFACE_INDEX = 1;
private static final int SERVICE_VERSION_INDEX = 2;
private static final int SERVICE_GROUP_INDEX = 3;
private static final String WILDCARD = "*";
/**
* The separator for service name
*
* @revert change a constant to be configurable, it's designed for Windows file name that is compatible with old
* Nacos binary release(< 0.6.1)
*/
private static final String SERVICE_NAME_SEPARATOR = System.getProperty("nacos.service.name.separator", ":");
/**
* The pagination size of query for Nacos service names(only for Dubbo-OPS)
*/
private static final int PAGINATION_SIZE = Integer.getInteger("nacos.service.names.pagination.size", 100);
/**
* The interval in second of lookup Nacos service names(only for Dubbo-OPS)
*/
private static final long LOOKUP_INTERVAL = Long.getLong("nacos.service.names.lookup.interval", 30);
/**
* {@link ScheduledExecutorService} lookup Nacos service names(only for Dubbo-OPS)
*/
private volatile ScheduledExecutorService scheduledExecutorService;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final NamingService namingService;
private final ConcurrentMap<String, EventListener> nacosListeners;
public NacosRegistry(URL url, NamingService namingService) {
super(url);
this.namingService = namingService;
this.nacosListeners = new ConcurrentHashMap<String, EventListener>();
}
@Override
public boolean isAvailable() {
return "UP".equals(namingService.getServerStatus());
}
@Override
public List<URL> lookup(final URL url) {
final List<URL> urls = new LinkedList<URL>();
execute(new NamingServiceCallback() {
@Override
public void callback(NamingService namingService) throws NacosException {
List<String> serviceNames = getServiceNames(url, null);
for (String serviceName : serviceNames) {
List<Instance> instances = namingService.getAllInstances(serviceName);
urls.addAll(buildURLs(url, instances));
}
}
});
return urls;
}
@Override
public void doRegister(URL url) {
final String serviceName = getServiceName(url);
final Instance instance = createInstance(url);
execute(new NamingServiceCallback() {
public void callback(NamingService namingService) throws NacosException {
namingService.registerInstance(serviceName, instance);
}
});
}
@Override
public void doUnregister(final URL url) {
execute(new NamingServiceCallback() {
public void callback(NamingService namingService) throws NacosException {
String serviceName = getServiceName(url);
Instance instance = createInstance(url);
namingService.deregisterInstance(serviceName, instance.getIp(), instance.getPort());
}
});
}
@Override
public void doSubscribe(final URL url, final NotifyListener listener) {
List<String> serviceNames = getServiceNames(url, listener);
doSubscribe(url, listener, serviceNames);
}
private void doSubscribe(final URL url, final NotifyListener listener, final List<String> serviceNames) {
execute(new NamingServiceCallback() {
@Override
public void callback(NamingService namingService) throws NacosException {
for (String serviceName : serviceNames) {
List<Instance> instances = namingService.getAllInstances(serviceName);
notifySubscriber(url, listener, instances);
subscribeEventListener(serviceName, url, listener);
}
}
});
}
@Override
public void doUnsubscribe(URL url, NotifyListener listener) {
if (isAdminProtocol(url)) {
shutdownServiceNamesLookup();
}
}
private void shutdownServiceNamesLookup() {
if (scheduledExecutorService != null) {
scheduledExecutorService.shutdown();
}
}
/**
* 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)) {
scheduleServiceNamesLookup(url, listener);
return getServiceNamesForOps(url);
} else {
return doGetServiceNames(url);
}
}
private boolean isAdminProtocol(URL url) {
return ADMIN_PROTOCOL.equals(url.getProtocol());
}
private void scheduleServiceNamesLookup(final URL url, final NotifyListener listener) {
if (scheduledExecutorService == null) {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
List<String> serviceNames = getAllServiceNames();
filterData(serviceNames, new NacosDataFilter<String>() {
@Override
public boolean accept(String serviceName) {
boolean accepted = false;
for (String category : ALL_SUPPORTED_CATEGORIES) {
String prefix = category + SERVICE_NAME_SEPARATOR;
if (StringUtils.startsWith(serviceName, prefix)) {
accepted = true;
break;
}
}
return accepted;
}
});
doSubscribe(url, listener, serviceNames);
}
}, LOOKUP_INTERVAL, LOOKUP_INTERVAL, TimeUnit.SECONDS);
}
}
/**
* 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, url);
return serviceNames;
}
private List<String> getAllServiceNames() {
final List<String> serviceNames = new LinkedList<String>();
execute(new NamingServiceCallback() {
@Override
public void callback(NamingService namingService) throws NacosException {
int pageIndex = 1;
ListView<String> listView = namingService.getServicesOfServer(pageIndex, PAGINATION_SIZE);
// First page data
List<String> firstPageData = listView.getData();
// Append first page into list
serviceNames.addAll(firstPageData);
// the total count
int count = listView.getCount();
// the number of pages
int pageNumbers = count / PAGINATION_SIZE;
int remainder = count % PAGINATION_SIZE;
// remain
if (remainder > 0) {
pageNumbers += 1;
}
// If more than 1 page
while (pageIndex < pageNumbers) {
listView = namingService.getServicesOfServer(++pageIndex, PAGINATION_SIZE);
serviceNames.addAll(listView.getData());
}
}
});
return serviceNames;
}
private void filterServiceNames(List<String> serviceNames, URL url) {
final String[] categories = getCategories(url);
final String targetServiceInterface = url.getServiceInterface();
final String targetVersion = url.getParameter(VERSION_KEY);
final String targetGroup = url.getParameter(GROUP_KEY);
filterData(serviceNames, new NacosDataFilter<String>() {
@Override
public boolean accept(String serviceName) {
// split service name to segments
// (required) segments[0] = category
// (required) segments[1] = serviceInterface
// (required) segments[2] = version
// (optional) segments[3] = group
String[] segments = StringUtils.split(serviceName, SERVICE_NAME_SEPARATOR);
int length = segments.length;
if (length < 3) { // must present 3 segments or more
return false;
}
String category = segments[CATEGORY_INDEX];
if (!ArrayUtils.contains(categories, category)) { // no match category
return false;
}
String serviceInterface = segments[SERVICE_INTERFACE_INDEX];
if (!WILDCARD.equals(targetServiceInterface) &&
!StringUtils.equals(targetServiceInterface, serviceInterface)) { // no match service interface
return false;
}
String version = segments[SERVICE_VERSION_INDEX];
if (!WILDCARD.equals(targetVersion) &&
!StringUtils.equals(targetVersion, version)) { // no match service version
return false;
}
String group = length > 3 ? segments[SERVICE_GROUP_INDEX] : null;
if (group != null && !WILDCARD.equals(targetGroup)
&& !StringUtils.equals(targetGroup, group)) { // no match service group
return false;
}
return true;
}
});
}
private <T> void filterData(Collection<T> collection, NacosDataFilter<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 List<String> doGetServiceNames(URL url) {
String[] categories = getCategories(url);
List<String> serviceNames = new ArrayList<String>(categories.length);
for (String category : categories) {
final String serviceName = getServiceName(url, category);
serviceNames.add(serviceName);
}
return serviceNames;
}
private List<URL> buildURLs(URL consumerURL, Collection<Instance> instances) {
if (instances.isEmpty()) {
return Collections.emptyList();
}
List<URL> urls = new LinkedList<URL>();
for (Instance instance : instances) {
URL url = buildURL(instance);
if (UrlUtils.isMatch(consumerURL, url)) {
urls.add(url);
}
}
return urls;
}
private void subscribeEventListener(String serviceName, final URL url, final NotifyListener listener)
throws NacosException {
if (!nacosListeners.containsKey(serviceName)) {
EventListener eventListener = new EventListener() {
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent e = (NamingEvent) event;
notifySubscriber(url, listener, e.getInstances());
}
}
};
namingService.subscribe(serviceName, eventListener);
nacosListeners.put(serviceName, eventListener);
}
}
/**
* Notify the Healthy {@link Instance instances} to subscriber.
*
* @param url {@link URL}
* @param listener {@link NotifyListener}
* @param instances all {@link Instance instances}
*/
private void notifySubscriber(URL url, NotifyListener listener, Collection<Instance> instances) {
List<Instance> healthyInstances = new LinkedList<Instance>(instances);
// Healthy Instances
filterHealthyInstances(healthyInstances);
List<URL> urls = buildURLs(url, healthyInstances);
NacosRegistry.this.notify(url, listener, urls);
}
/**
* Get the categories from {@link URL}
*
* @param url {@link URL}
* @return non-null array
*/
private String[] getCategories(URL url) {
return Constants.ANY_VALUE.equals(url.getServiceInterface()) ?
ALL_SUPPORTED_CATEGORIES : of(Constants.DEFAULT_CATEGORY);
}
private URL buildURL(Instance instance) {
Map<String, String> metadata = instance.getMetadata();
String protocol = metadata.get(Constants.PROTOCOL_KEY);
String path = metadata.get(Constants.PATH_KEY);
URL url = new URL(protocol,
instance.getIp(),
instance.getPort(),
path,
instance.getMetadata());
return url;
}
private Instance createInstance(URL url) {
// 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());
newURL = newURL.addParameter(Constants.PATH_KEY, url.getPath());
String ip = url.getHost();
int port = url.getPort();
Instance instance = new Instance();
instance.setIp(ip);
instance.setPort(port);
instance.setMetadata(new HashMap<String, String>(newURL.getParameters()));
return instance;
}
private String getServiceName(URL url) {
String category = url.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY);
return getServiceName(url, category);
}
private String getServiceName(URL url, String category) {
StringBuilder serviceNameBuilder = new StringBuilder(category);
appendIfPresent(serviceNameBuilder, url, INTERFACE_KEY);
appendIfPresent(serviceNameBuilder, url, VERSION_KEY);
appendIfPresent(serviceNameBuilder, url, GROUP_KEY);
return serviceNameBuilder.toString();
}
private void appendIfPresent(StringBuilder target, URL url, String parameterName) {
String parameterValue = url.getParameter(parameterName);
if (!StringUtils.isBlank(parameterValue)) {
target.append(SERVICE_NAME_SEPARATOR).append(parameterValue);
}
}
private void execute(NamingServiceCallback callback) {
try {
callback.callback(namingService);
} catch (NacosException e) {
if (logger.isErrorEnabled()) {
logger.error(e.getErrMsg(), e);
}
}
}
private void filterHealthyInstances(Collection<Instance> instances) {
filterData(instances, new NacosDataFilter<Instance>() {
@Override
public boolean accept(Instance data) {
return data.isEnabled();
}
});
}
private static <T> T[] of(T... values) {
return values;
}
/**
* A filter for Nacos data
*
* @since 2.6.5
*/
private interface NacosDataFilter<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);
}
/**
* {@link NamingService} Callback
*
* @since 2.6.5
*/
interface NamingServiceCallback {
/**
* Callback
*
* @param namingService {@link NamingService}
* @throws NacosException
*/
void callback(NamingService namingService) throws NacosException;
}
}

View File

@ -0,0 +1,108 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.nacos;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.client.naming.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties;
import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import static com.alibaba.nacos.client.naming.utils.UtilAndComs.NACOS_NAMING_LOG_NAME;
import static org.apache.dubbo.common.Constants.BACKUP_KEY;
/**
* Nacos {@link RegistryFactory}
*
* @since 2.6.5
*/
public class NacosRegistryFactory extends AbstractRegistryFactory {
private final Logger logger = LoggerFactory.getLogger(getClass());
protected Registry createRegistry(URL url) {
return new NacosRegistry(url, buildNamingService(url));
}
private NamingService buildNamingService(URL url) {
Properties nacosProperties = buildNacosProperties(url);
NamingService namingService = null;
try {
namingService = NacosFactory.createNamingService(nacosProperties);
} catch (NacosException e) {
if (logger.isErrorEnabled()) {
logger.error(e.getErrMsg(), e);
}
throw new IllegalStateException(e);
}
return namingService;
}
private Properties buildNacosProperties(URL url) {
Properties properties = new Properties();
setServerAddr(url, properties);
setProperties(url, properties);
return properties;
}
private void setServerAddr(URL url, Properties properties) {
StringBuilder serverAddrBuilder =
new StringBuilder(url.getHost()) // Host
.append(":")
.append(url.getPort()); // Port
// Append backup parameter as other servers
String backup = url.getParameter(BACKUP_KEY);
if (backup != null) {
serverAddrBuilder.append(",").append(backup);
}
String serverAddr = serverAddrBuilder.toString();
properties.put(SERVER_ADDR, serverAddr);
}
private void setProperties(URL url, Properties properties) {
putPropertyIfAbsent(url, properties, NAMESPACE);
putPropertyIfAbsent(url, properties, NACOS_NAMING_LOG_NAME);
putPropertyIfAbsent(url, properties, ENDPOINT);
putPropertyIfAbsent(url, properties, NAMESPACE);
putPropertyIfAbsent(url, properties, ACCESS_KEY);
putPropertyIfAbsent(url, properties, SECRET_KEY);
putPropertyIfAbsent(url, properties, CLUSTER_NAME);
}
private void putPropertyIfAbsent(URL url, Properties properties, String propertyName) {
String propertyValue = url.getParameter(propertyName);
if (StringUtils.isNotEmpty(propertyValue)) {
properties.setProperty(propertyName, propertyValue);
}
}
}

View File

@ -0,0 +1 @@
nacos=org.apache.dubbo.registry.nacos.NacosRegistryFactory

View File

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.demo.consumer;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.demo.service.DemoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* {@link DemoService} consumer demo
*/
@EnableDubbo
@PropertySource(value = "classpath:/consumer-config.properties")
public class DemoServiceConsumerBootstrap {
@Reference(version = "${demo.service.version}")
private DemoService demoService;
@Reference(version = "${demo.service.version}", protocol = "rest")
private DemoService restDemoService;
@PostConstruct
public void init() throws InterruptedException {
for (int j = 0; j < 10; j++) {
System.out.println(demoService.sayName("小马哥mercyblitz"));
System.out.println(restDemoService.sayName("小马哥mercyblitz"));
}
Thread.sleep(TimeUnit.SECONDS.toMillis(5));
}
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(DemoServiceConsumerBootstrap.class);
context.refresh();
System.in.read();
context.close();
}
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.demo.consumer;
import org.apache.dubbo.demo.service.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* {@link DemoService} consumer demo XML bootstrap
*/
public class DemoServiceConsumerXmlBootstrap {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.setConfigLocation("/META-INF/spring/dubbo-consumer-context.xml");
context.refresh();
System.out.println("DemoService consumer (XML) is starting...");
DemoService demoService = context.getBean("demoService", DemoService.class);
for (int i = 0; i < 10; i++) {
System.out.println(demoService.sayName("小马哥mercyblitz"));
}
System.in.read();
context.close();
}
}

View File

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.demo.provider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.demo.service.DemoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;
import java.io.IOException;
/**
* {@link DemoService} provider demo
*/
@EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.service")
@PropertySource(value = "classpath:/provider-config.properties")
public class DemoServiceProviderBootstrap {
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(DemoServiceProviderBootstrap.class);
context.refresh();
System.out.println("DemoService provider is starting...");
System.in.read();
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.demo.provider;
import org.apache.dubbo.demo.service.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* {@link DemoService} provider demo XML bootstrap
*/
public class DemoServiceProviderXmlBootstrap {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.setConfigLocation("/META-INF/spring/dubbo-provider-context.xml");
context.refresh();
System.out.println("DemoService provider (XML) is starting...");
System.in.read();
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.demo.service;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.beans.factory.annotation.Value;
/**
* Default {@link DemoService}
*
* @since 2.6.5
*/
@Service(version = "${demo.service.version}")
public class DefaultService implements DemoService {
@Value("${demo.service.name}")
private String serviceName;
public String sayName(String name) {
RpcContext rpcContext = RpcContext.getContext();
return String.format("Service [name :%s , protocol: %s , port : %d] %s(\"%s\") : Hello,%s",
serviceName,
rpcContext.getUrl().getProtocol(),
rpcContext.getLocalPort(),
rpcContext.getMethodName(),
name,
name);
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.demo.service;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
/**
* DemoService
*
* @since 2.6.5
*/
@Path("/demo-service")
public interface DemoService {
@GET
String sayName(@QueryParam("name") String name);
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-consumer-xml-demo"/>
<!-- Nacos Registry -->
<dubbo:registry address="nacos://127.0.0.1:8848"/>
<!-- Reference interface -->
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.service.DemoService" version="2.0.0"/>
</beans>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-provider-xml-demo"/>
<!-- Nacos Registry -->
<dubbo:registry address="nacos://127.0.0.1:8848"/>
<!-- Use random port as Dubbo -->
<dubbo:protocol name="dubbo" port="-1"/>
<dubbo:service interface="org.apache.dubbo.demo.service.DemoService" ref="demoService" version="2.0.0"/>
<bean id="demoService" class="org.apache.dubbo.demo.service.DefaultService"/>
</beans>

View File

@ -0,0 +1,6 @@
## Dubbo Application info
dubbo.application.name=dubbo-consumer-demo
## Nacos registry address
dubbo.registry.address=nacos://127.0.0.1:8848
# @Reference version
demo.service.version=1.0.0

View File

@ -0,0 +1,14 @@
## Dubbo Application info
dubbo.application.name=dubbo-provider-demo
## Nacos registry address
dubbo.registry.protocol=nacos
dubbo.registry.address=127.0.0.1:8848
## Exports multiple protocols
### Dubbo Protocol using random port
dubbo.protocols.dubbo.port=-1
### REST protocol
dubbo.protocols.rest.port=9090
dubbo.protocols.rest.server=netty
# Provider @Service info
demo.service.version=1.0.0
demo.service.name=demoService

View File

@ -36,5 +36,6 @@
<module>dubbo-registry-redis</module>
<module>dubbo-registry-consul</module>
<module>dubbo-registry-etcd3</module>
<module>dubbo-registry-nacos</module>
</modules>
</project>