From 49f6d41a7a0b3135a01fa1e5716c5317e52dfcc5 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Fri, 15 Mar 2019 00:42:04 +0800 Subject: [PATCH] Polish apache/incubator-dubbo#3582 : nacos support on 2.7 --- .../AbstractCloudNativeRegistryFactory.java | 84 ++++++ .../support/cloud/CloudNativeRegistry.java | 257 ++++++++++++++++++ .../support/cloud/CloudServiceDiscovery.java | 61 +++++ .../support/cloud/CloudServiceRegistry.java | 57 ++++ .../support/cloud/ServiceInstance.java | 50 +++- .../support/cloud/ServiceInstanceFactory.java | 33 ++- dubbo-registry/dubbo-registry-nacos/pom.xml | 148 ++++++++++ .../registry/nacos/NacosCloudService.java | 126 +++++++++ .../registry/nacos/NacosRegistryFactory.java | 132 +++++++++ .../registry/nacos/NacosServiceInstance.java | 64 +++++ .../nacos/NacosServiceInstanceFactory.java | 100 +++++++ .../org.apache.dubbo.registry.RegistryFactory | 1 + .../DemoServiceConsumerBootstrap.java | 54 ++++ .../DemoServiceConsumerXmlBootstrap.java | 41 +++ .../DemoServiceProviderBootstrap.java | 41 +++ .../DemoServiceProviderXmlBootstrap.java | 30 +- .../dubbo/demo/service/DefaultService.java | 38 +-- .../dubbo/demo/service/DemoService.java | 26 +- .../spring/dubbo-consumer-context.xml | 16 ++ .../spring/dubbo-provider-context.xml | 21 ++ .../test/resources/consumer-config.properties | 6 + .../test/resources/provider-config.properties | 14 + dubbo-registry/pom.xml | 1 + 23 files changed, 1329 insertions(+), 72 deletions(-) create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/AbstractCloudNativeRegistryFactory.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudNativeRegistry.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceDiscovery.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceRegistry.java rename dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/DefaultDemoService.java => dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstance.java (56%) rename dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/ProviderConfiguration.java => dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstanceFactory.java (54%) create mode 100644 dubbo-registry/dubbo-registry-nacos/pom.xml create mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosCloudService.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstance.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstanceFactory.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/org.apache.dubbo.registry.RegistryFactory create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerBootstrap.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerXmlBootstrap.java create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderBootstrap.java rename dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/EnableRestService.java => dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderXmlBootstrap.java (55%) mode change 100755 => 100644 rename dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestServiceConfiguration.java => dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DefaultService.java (50%) mode change 100755 => 100644 rename dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestService.java => dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DemoService.java (66%) mode change 100755 => 100644 create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-consumer-context.xml create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-provider-context.xml create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/resources/consumer-config.properties create mode 100644 dubbo-registry/dubbo-registry-nacos/src/test/resources/provider-config.properties diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/AbstractCloudNativeRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/AbstractCloudNativeRegistryFactory.java new file mode 100644 index 00000000000..b9a14bd169b --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/AbstractCloudNativeRegistryFactory.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.registry.support.cloud; + +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.NamedThreadFactory; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.support.AbstractRegistryFactory; + +import java.util.concurrent.ScheduledExecutorService; + +import static java.lang.System.getProperty; +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; + +/** + * Abstract {@link CloudNativeRegistry} Factory + * + * @param The subclass of {@link ServiceInstance} + * @since 2.7.1 + */ +public abstract class AbstractCloudNativeRegistryFactory extends AbstractRegistryFactory { + + private static String SERVICES_LOOKUP_SCHEDULER_THREAD_NAME_PREFIX = + getProperty("dubbo.services.lookup.scheduler.thread.name.prefix ", "dubbo-services-lookup-"); + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private final ScheduledExecutorService servicesLookupScheduler; + + public AbstractCloudNativeRegistryFactory() { + this.servicesLookupScheduler = newSingleThreadScheduledExecutor( + new NamedThreadFactory(SERVICES_LOOKUP_SCHEDULER_THREAD_NAME_PREFIX)); + } + + @Override + protected final Registry createRegistry(URL url) { + return new CloudNativeRegistry(url, + createCloudServiceRegistry(url), + createCloudServiceDiscovery(url), + createServiceInstanceFactory(url), + servicesLookupScheduler + ); + } + + /** + * The subclass implement this method to create {@link CloudServiceRegistry} + * + * @param url The {@link URL} of Dubbo Registry + * @return non-null + */ + protected abstract CloudServiceRegistry createCloudServiceRegistry(URL url); + + /** + * The subclass implement this method to create {@link CloudServiceDiscovery} + * + * @param url The {@link URL} of Dubbo Registry + * @return non-null + */ + protected abstract CloudServiceDiscovery createCloudServiceDiscovery(URL url); + + /** + * The subclass implement this method to create {@link ServiceInstanceFactory} + * + * @param url The {@link URL} of Dubbo Registry + * @return non-null + */ + protected abstract ServiceInstanceFactory createServiceInstanceFactory(URL url); +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudNativeRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudNativeRegistry.java new file mode 100644 index 00000000000..bd43f150c7c --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudNativeRegistry.java @@ -0,0 +1,257 @@ +/* + * 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.support.cloud; + +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.Registry; +import org.apache.dubbo.registry.support.FailbackRegistry; + +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.Map; +import java.util.Set; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static java.util.Collections.singletonList; +import static org.apache.dubbo.common.Constants.PROVIDER_SIDE; +import static org.apache.dubbo.common.Constants.SIDE_KEY; + +/** + * Dubbo Cloud-Native Service {@link Registry} abstraction + * + * @param The subclass of {@link ServiceInstance} + * @since 2.7.1 + */ +public class CloudNativeRegistry extends FailbackRegistry { + + /** + * The parameter name of {@link #allServicesLookupInterval} + */ + public static final String ALL_SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.all.services.lookup.interval"; + + /** + * The parameter name of {@link #registeredServicesLookupInterval} + */ + public static final String REGISTERED_SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.registered.services.lookup.interval"; + + /** + * The interval in second of lookup service names(only for Dubbo-OPS) + */ + private final long allServicesLookupInterval; + + private final long registeredServicesLookupInterval; + + private final CloudServiceRegistry cloudServiceRegistry; + + private final CloudServiceDiscovery cloudServiceDiscovery; + + private final ServiceInstanceFactory serviceInstanceFactory; + + private final ScheduledExecutorService servicesLookupScheduler; + + public CloudNativeRegistry(URL url, + CloudServiceRegistry cloudServiceRegistry, + CloudServiceDiscovery cloudServiceDiscovery, + ServiceInstanceFactory serviceInstanceFactory, + ScheduledExecutorService servicesLookupScheduler) { + super(url); + this.allServicesLookupInterval = url.getParameter(ALL_SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 30L); + this.registeredServicesLookupInterval = url.getParameter(REGISTERED_SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 300L); + this.cloudServiceRegistry = cloudServiceRegistry; + this.cloudServiceDiscovery = cloudServiceDiscovery; + this.serviceInstanceFactory = serviceInstanceFactory; + this.servicesLookupScheduler = servicesLookupScheduler; + } + + protected boolean shouldRegister(S serviceInstance) { + Map metadata = serviceInstance.getMetadata(); + String side = metadata.get(SIDE_KEY); + return PROVIDER_SIDE.equals(side); // Only register the Provider. + } + + @Override + public void doRegister(URL url) { + S serviceInstance = serviceInstanceFactory.create(url); + if (shouldRegister(serviceInstance)) { + cloudServiceRegistry.register(serviceInstance); + } + } + + @Override + public void doUnregister(URL url) { + S serviceInstance = serviceInstanceFactory.create(url); + if (shouldRegister(serviceInstance)) { + cloudServiceRegistry.deregister(serviceInstance); + } + } + + @Override + public void doSubscribe(URL url, NotifyListener listener) { + List serviceNames = getServiceNames(url, listener); + doSubscribe(url, listener, serviceNames); + this.servicesLookupScheduler.scheduleAtFixedRate(() -> { + doSubscribe(url, listener, serviceNames); + }, registeredServicesLookupInterval, registeredServicesLookupInterval, TimeUnit.SECONDS); + } + + @Override + public void doUnsubscribe(URL url, NotifyListener listener) { + if (isAdminProtocol(url)) { + shutdownServiceNamesLookup(); + } + } + + private void shutdownServiceNamesLookup() { + if (servicesLookupScheduler != null) { + servicesLookupScheduler.shutdown(); + } + } + + /** + * Get all service names + * + * @return non-null {@link List} + */ + protected List getAllServiceNames() { + return cloudServiceDiscovery.getServices(); + } + + private void doSubscribe(final URL url, final NotifyListener listener, final List serviceNames) { + for (String serviceName : serviceNames) { + List serviceInstances = cloudServiceDiscovery.getServiceInstances(serviceName); + notifySubscriber(url, listener, serviceInstances); + } + } + + /** + * Get the service names from the specified {@link URL url} + * + * @param url {@link URL} + * @param listener {@link NotifyListener} + * @return non-null + */ + private List getServiceNames(URL url, NotifyListener listener) { + if (isAdminProtocol(url)) { + initAllServicesLookupScheduler(url, listener); + return getServiceNamesForOps(url); + } else { + return singletonList(serviceInstanceFactory.createServiceName(url)); + } + } + + /** + * Get the service names for Dubbo OPS + * + * @param url {@link URL} + * @return non-null + */ + private List getServiceNamesForOps(URL url) { + List serviceNames = getAllServiceNames(); + filterServiceNames(serviceNames); + return serviceNames; + } + + + private boolean isAdminProtocol(URL url) { + return Constants.ADMIN_PROTOCOL.equals(url.getProtocol()); + } + + private void filter(Collection collection, Predicate predicate) { + Iterator iterator = collection.iterator(); + while (iterator.hasNext()) { + T data = iterator.next(); + if (!predicate.test(data)) { // remove if not accept + iterator.remove(); + } + } + } + + private void initAllServicesLookupScheduler(final URL url, final NotifyListener listener) { + servicesLookupScheduler.scheduleAtFixedRate(() -> { + List serviceNames = getAllServiceNames(); + filterServiceNames(serviceNames); + doSubscribe(url, listener, serviceNames); + }, allServicesLookupInterval, allServicesLookupInterval, TimeUnit.SECONDS); + } + + private void filterServiceNames(List serviceNames) { + filter(serviceNames, cloudServiceDiscovery::supports); + } + + private void doSubscribe(final URL url, final NotifyListener listener, final Set serviceNames) { + Collection serviceInstances = serviceNames.stream() + .map(cloudServiceDiscovery::getServiceInstances) + .flatMap(v -> v.stream()) + .collect(Collectors.toList()); + notifySubscriber(url, listener, serviceInstances); + } + + /** + * Notify the Healthy {@link S service instance} to subscriber. + * + * @param url {@link URL} + * @param listener {@link NotifyListener} + * @param serviceInstances all {@link S registrations} + */ + private void notifySubscriber(URL url, NotifyListener listener, Collection serviceInstances) { + Set healthyServiceInstances = new LinkedHashSet(serviceInstances); + // Healthy Instances + filterHealthyInstances(healthyServiceInstances); + List urls = buildURLs(url, healthyServiceInstances); + this.notify(url, listener, urls); + } + + private void filterHealthyInstances(Collection serviceInstances) { + filter(serviceInstances, cloudServiceRegistry::isHealthy); + } + + private List buildURLs(URL consumerURL, Collection serviceInstances) { + if (serviceInstances.isEmpty()) { + return Collections.emptyList(); + } + List urls = new LinkedList(); + for (S serviceInstance : serviceInstances) { + URL url = buildURL(serviceInstance); + if (UrlUtils.isMatch(consumerURL, url)) { + urls.add(url); + } + } + return urls; + } + + private URL buildURL(S serviceInstance) { + URL url = new URL(serviceInstance.getMetadata().get(Constants.PROTOCOL_KEY), + serviceInstance.getHost(), serviceInstance.getPort(), + serviceInstance.getMetadata()); + return url; + } + + @Override + public boolean isAvailable() { + return cloudServiceRegistry.isAvailable(); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceDiscovery.java new file mode 100644 index 00000000000..ff8907abb76 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceDiscovery.java @@ -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.apache.dubbo.registry.support.cloud; + +import java.util.List; + +/** + * Cloud {@link ServiceInstance Service} Discovery + * + * @param The subclass of {@link ServiceInstance} + * @since 2.7.1 + */ +public interface CloudServiceDiscovery { + + /** + * The total number of all services. + * + * @return must be equal or more than 0 + */ + default long getTotalServices() { + return getServices().size(); + } + + /** + * Get all service names + * + * @return non-null read-only {@link List} + */ + List getServices(); + + + /** + * Get all service instances by the specified name + * + * @param serviceName the service name + * @return non-null read-only {@link List} + */ + List getServiceInstances(String serviceName); + + /** + * Supports the specified name of Cloud Service or not + * + * @param serviceName the specified service name + * @return if supports, return true, or false + */ + boolean supports(String serviceName); +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceRegistry.java new file mode 100644 index 00000000000..eb0eaf032f5 --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/CloudServiceRegistry.java @@ -0,0 +1,57 @@ +/* + * 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.support.cloud; + +/** + * Cloud {@link ServiceInstance Service} Registry + * + * @param The subclass of {@link ServiceInstance} + * @since 2.7.1 + */ +public interface CloudServiceRegistry extends AutoCloseable { + + /** + * Registers the {@link ServiceInstance}. + * + * @param serviceInstance The {@link ServiceInstance} + */ + void register(S serviceInstance); + + /** + * Deregisters the {@link ServiceInstance} + * + * @param serviceInstance The {@link ServiceInstance} + */ + void deregister(S serviceInstance); + + + /** + * Test the specified {@link ServiceInstance} is healthy or not + * + * @param serviceInstance The {@link ServiceInstance} + * @return true if the specified {@link ServiceInstance} is healthy + */ + boolean isHealthy(S serviceInstance); + + /** + * Is available or not + * + * @return true if current {@link CloudServiceRegistry} is available + */ + boolean isAvailable(); + +} diff --git a/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/DefaultDemoService.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstance.java similarity index 56% rename from dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/DefaultDemoService.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstance.java index 7c747717ef9..fae97bc6374 100644 --- a/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/DefaultDemoService.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstance.java @@ -14,27 +14,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.test.provider; +package org.apache.dubbo.registry.support.cloud; -import org.apache.dubbo.config.annotation.Service; -import org.apache.dubbo.demo.DemoService; +import java.util.Map; /** - * Default {@link DemoService} implementation + * The Service Instance * - * @since 2.5.8 + * @since 2.7.1 */ -@Service( - version = "2.5.8", - application = "dubbo-annotation-provider", - protocol = "dubbo", - registry = "my-registry" -) -public class DefaultDemoService implements DemoService { +public interface ServiceInstance { - @Override - public String sayHello(String name) { - return "DefaultDemoService - sayHell() : " + name; + /** + * @return The service name + */ + String getServiceName(); + + /** + * @return The Host + */ + String getHost(); + + /** + * @return The service port + */ + int getPort(); + + /** + * @return The read-only metadata + */ + Map getMetadata(); + + /** + * @return The scheme of the service instance. + */ + default String getScheme() { + return null; } + @Override + boolean equals(Object o); + + @Override + int hashCode(); } diff --git a/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/ProviderConfiguration.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstanceFactory.java similarity index 54% rename from dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/ProviderConfiguration.java rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstanceFactory.java index d959e544516..7f8d21ebc92 100644 --- a/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/org/apache/dubbo/test/provider/ProviderConfiguration.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/cloud/ServiceInstanceFactory.java @@ -14,20 +14,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.test.provider; +package org.apache.dubbo.registry.support.cloud; -import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; +import org.apache.dubbo.common.URL; /** - * Provider {@Link Configuration} + * {@link ServiceInstance} Factory to create a instance of {@link ServiceInstance} * - * @since 2.5.8 + * @param The subclass of {@link ServiceInstance} + * @since 2.7.1 */ -@Configuration -@ImportResource("META-INF/spring/dubbo-provider.xml") -@DubboComponentScan -public class ProviderConfiguration { +public interface ServiceInstanceFactory { + + /** + * Creates a instance of {@link S} + * + * @param url The Dubbo's {@link URL} + * @return a instance of {@link S}, if null, it indicates the registration will not be executed. + */ + S create(URL url); + + /** + * Creates the Service Name + * + * @param url The Dubbo's {@link URL} + * @return non-null + */ + String createServiceName(URL url); } diff --git a/dubbo-registry/dubbo-registry-nacos/pom.xml b/dubbo-registry/dubbo-registry-nacos/pom.xml new file mode 100644 index 00000000000..2abf8b07538 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/pom.xml @@ -0,0 +1,148 @@ + + + + org.apache.dubbo + dubbo-registry + 2.7.1-SNAPSHOT + ../pom.xml + + 4.0.0 + + org.apache.dubbo + dubbo-registry-nacos + ${project.artifactId} + The Nacos registry module of Dubbo project + + + UTF-8 + UTF-8 + 0.9.0 + + + + + + org.apache.dubbo + dubbo-registry-api + ${project.version} + true + + + + org.apache.dubbo + dubbo-common + ${project.version} + true + + + + com.alibaba.nacos + nacos-client + ${nacos.version} + true + + + + + org.apache.dubbo + dubbo-config-api + ${project.version} + test + + + + org.apache.dubbo + dubbo-serialization-hessian2 + ${project.version} + test + + + + org.apache.dubbo + dubbo-config-spring + ${project.version} + test + + + + org.apache.dubbo + dubbo-rpc-dubbo + ${project.version} + test + + + + org.apache.dubbo + dubbo-remoting-netty4 + ${project.version} + test + + + + ch.qos.logback + logback-classic + 1.2.3 + test + + + + + org.apache.dubbo + dubbo-rpc-rest + ${project.version} + test + + + + org.jboss.resteasy + resteasy-jaxrs + test + + + + org.jboss.resteasy + resteasy-client + test + + + + org.jboss.resteasy + resteasy-netty4 + test + + + + javax.validation + validation-api + test + + + + org.jboss.resteasy + resteasy-jackson-provider + test + + + + org.jboss.resteasy + resteasy-jaxb-provider + test + + + + org.springframework + spring-test + test + + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosCloudService.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosCloudService.java new file mode 100644 index 00000000000..d3074974b7b --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosCloudService.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.registry.nacos; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingService; + +import org.apache.dubbo.registry.support.cloud.CloudServiceDiscovery; +import org.apache.dubbo.registry.support.cloud.CloudServiceRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.apache.commons.lang3.StringUtils.startsWithIgnoreCase; +import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY; +import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY; + +/** + * Nacos Cloud Service implements {@link CloudServiceRegistry} and {@link CloudServiceDiscovery} + */ +class NacosCloudService implements CloudServiceRegistry, CloudServiceDiscovery { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final NamingService namingService; + + public NacosCloudService(NamingService namingService) { + this.namingService = namingService; + } + + @Override + public List getServices() { + return execute(namingService -> + namingService.getServicesOfServer(0, Integer.MAX_VALUE).getData() + ); + } + + @Override + public List getServiceInstances(String serviceName) { + return execute(namingService -> + namingService.selectInstances(serviceName, true) + .stream().map(NacosServiceInstance::new) + .collect(Collectors.toList()) + ); + } + + @Override + public boolean supports(String serviceName) { + return startsWithIgnoreCase(serviceName, PROVIDERS_CATEGORY) || + startsWithIgnoreCase(serviceName, CONSUMERS_CATEGORY); + } + + @Override + public void register(NacosServiceInstance serviceInstance) { + execute(namingService -> { + namingService.registerInstance(serviceInstance.getServiceName(), serviceInstance.getSource()); + return null; + }); + } + + @Override + public void deregister(NacosServiceInstance serviceInstance) { + execute(namingService -> { + namingService.deregisterInstance(serviceInstance.getServiceName(), + serviceInstance.getHost(), serviceInstance.getPort()); + return null; + }); + } + + @Override + public boolean isHealthy(NacosServiceInstance serviceInstance) { + return serviceInstance.getSource().isHealthy(); + } + + @Override + public boolean isAvailable() { + return "UP".equals(namingService.getServerStatus()); + } + + @Override + public void close() throws Exception { + // DO NOTHING + } + + private T execute(NamingServiceFunction function) { + try { + return function.apply(namingService); + } catch (NacosException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getErrMsg(), e); + } + throw new RuntimeException(e); + } + } + + /** + * {@link NamingService} Function + */ + interface NamingServiceFunction { + + /** + * Callback + * + * @param namingService {@link NamingService} + * @throws NacosException + */ + T apply(NamingService namingService) throws NacosException; + + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java new file mode 100644 index 00000000000..02e0d61434a --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java @@ -0,0 +1,132 @@ +/* + * 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.RegistryFactory; +import org.apache.dubbo.registry.support.cloud.AbstractCloudNativeRegistryFactory; +import org.apache.dubbo.registry.support.cloud.CloudServiceDiscovery; +import org.apache.dubbo.registry.support.cloud.CloudServiceRegistry; +import org.apache.dubbo.registry.support.cloud.ServiceInstanceFactory; + +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.HashMap; +import java.util.Map; +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.6 + */ +public class NacosRegistryFactory extends AbstractCloudNativeRegistryFactory { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private Map nacosCloudServicesCache = new HashMap<>(); + + 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); + } + } + + private NacosCloudService createNacosCloudService(URL url) { + nacosCloudServicesCache.computeIfAbsent(url, u -> + new NacosCloudService(buildNamingService(u)) + ); + return nacosCloudServicesCache.get(url); + } + + @Override + protected CloudServiceRegistry createCloudServiceRegistry(URL url) { + return createNacosCloudService(url); + } + + @Override + protected CloudServiceDiscovery createCloudServiceDiscovery(URL url) { + return createNacosCloudService(url); + } + + @Override + protected ServiceInstanceFactory createServiceInstanceFactory(URL url) { + return new NacosServiceInstanceFactory(); + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstance.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstance.java new file mode 100644 index 00000000000..775df9aadab --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstance.java @@ -0,0 +1,64 @@ +/* + * 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.registry.support.cloud.ServiceInstance; + +import com.alibaba.nacos.api.naming.pojo.Instance; + +import java.util.Map; + +/** + * Nacos {@link ServiceInstance} + */ +public class NacosServiceInstance implements ServiceInstance { + + private final Instance source; + + public NacosServiceInstance(Instance instance) { + this.source = instance; + } + + @Override + public String getServiceName() { + return source.getServiceName(); + } + + @Override + public String getHost() { + return source.getIp(); + } + + @Override + public int getPort() { + return source.getPort(); + } + + @Override + public Map getMetadata() { + return source.getMetadata(); + } + + @Override + public String getScheme() { + return "nacos"; + } + + public Instance getSource() { + return source; + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstanceFactory.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstanceFactory.java new file mode 100644 index 00000000000..73850c610a0 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceInstanceFactory.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.registry.nacos; + +import com.alibaba.nacos.api.naming.pojo.Instance; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.registry.support.cloud.ServiceInstanceFactory; + +import java.util.LinkedHashMap; +import java.util.Objects; + +import static java.lang.System.getProperty; +import static org.apache.dubbo.common.Constants.CATEGORY_KEY; +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.PROTOCOL_KEY; +import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY; +import static org.apache.dubbo.common.Constants.VERSION_KEY; + +/** + * Nacos {@link ServiceInstanceFactory} + * + * @since 2.7.1 + */ +public class NacosServiceInstanceFactory implements ServiceInstanceFactory { + + /** + * The separator for service name + */ + private static final String SERVICE_NAME_SEPARATOR = getProperty("dubbo.service.name.separator", ":"); + + @Override + public NacosServiceInstance create(URL url) { + Instance instance = createInstance(url); + return new NacosServiceInstance(instance); + } + + private Instance createInstance(URL url) { + // Append default category if absent + String category = url.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + URL newURL = url.addParameter(CATEGORY_KEY, category); + newURL = newURL.addParameter(PROTOCOL_KEY, url.getProtocol()); + String ip = url.getHost(); + int port = url.getPort(); + String serviceName = createServiceName(url); + Instance instance = new Instance(); + instance.setServiceName(serviceName); + instance.setIp(ip); + instance.setPort(port); + instance.setMetadata(new LinkedHashMap<>(newURL.getParameters())); + return instance; + } + + @Override + public String createServiceName(URL url) { + String category = url.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY); + if (!Objects.equals(category, PROVIDERS_CATEGORY) && !Objects.equals(category, CONSUMERS_CATEGORY)) { + category = PROVIDERS_CATEGORY; + } + return createServiceName(url, category); + } + + private static String createServiceName(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 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.isNotEmpty(parameterValue)) { + target.append(SERVICE_NAME_SEPARATOR).append(parameterValue); + } + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/org.apache.dubbo.registry.RegistryFactory b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/org.apache.dubbo.registry.RegistryFactory new file mode 100644 index 00000000000..bb754674978 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/org.apache.dubbo.registry.RegistryFactory @@ -0,0 +1 @@ +nacos=org.apache.dubbo.registry.nacos.NacosRegistryFactory \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerBootstrap.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerBootstrap.java new file mode 100644 index 00000000000..cf2754a1ddf --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerBootstrap.java @@ -0,0 +1,54 @@ +/* + * 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}", protocol = "dubbo") + private DemoService demoService; + + @PostConstruct + public void init() throws InterruptedException { + for (int j = 0; j < 10; j++) { + System.out.println(demoService.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(); + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerXmlBootstrap.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerXmlBootstrap.java new file mode 100644 index 00000000000..d2a7a7bd9fe --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/consumer/DemoServiceConsumerXmlBootstrap.java @@ -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.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(); + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderBootstrap.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderBootstrap.java new file mode 100644 index 00000000000..c1d2ec4f0f5 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderBootstrap.java @@ -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(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/EnableRestService.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderXmlBootstrap.java old mode 100755 new mode 100644 similarity index 55% rename from dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/EnableRestService.java rename to dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderXmlBootstrap.java index efd8aa9385c..0a37f3fabe9 --- a/dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/EnableRestService.java +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/provider/DemoServiceProviderXmlBootstrap.java @@ -14,24 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.spring.webmvc.annotation; +package org.apache.dubbo.demo.provider; -import org.springframework.context.annotation.Import; +import org.apache.dubbo.demo.service.DemoService; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.io.IOException; /** - * Enable {@link RestService Rest Service} - * - * @since 2.7.0 + * {@link DemoService} provider demo XML bootstrap */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Import(RestServiceConfiguration.class) -public @interface EnableRestService { +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(); + } } diff --git a/dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestServiceConfiguration.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DefaultService.java old mode 100755 new mode 100644 similarity index 50% rename from dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestServiceConfiguration.java rename to dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DefaultService.java index 2774ccd3267..a7c87d32afd --- a/dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestServiceConfiguration.java +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DefaultService.java @@ -14,30 +14,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.spring.webmvc.annotation; +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; -import com.alibaba.dubbo.rpc.protocol.spring.webmvc.method.annotation.RestServiceHandlerAdapter; -import com.alibaba.dubbo.rpc.protocol.spring.webmvc.method.annotation.RestServiceHandlerMapping; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** - * {@link RestService} + * Default {@link DemoService} * - * @since 2.7.0 + * @since 2.6.5 */ -@Configuration -public class RestServiceConfiguration { +@Service(version = "${demo.service.version}") +public class DefaultService implements DemoService { - @Bean - public RestServiceHandlerMapping restServiceHandlerMapping() { - return new RestServiceHandlerMapping(); - } + @Value("${demo.service.name}") + private String serviceName; - @Bean - public RestServiceHandlerAdapter restServiceHandlerAdapter(){ - return new RestServiceHandlerAdapter(); + 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); } - - } diff --git a/dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestService.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DemoService.java old mode 100755 new mode 100644 similarity index 66% rename from dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestService.java rename to dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DemoService.java index 62aa81c5eec..0c808779311 --- a/dubbo-rpc/dubbo-rpc-springmvc/src/main/java/com/alibaba/dubbo/rpc/protocol/spring/webmvc/annotation/RestService.java +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/demo/service/DemoService.java @@ -14,21 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.spring.webmvc.annotation; +package org.apache.dubbo.demo.service; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; /** - * Rest Service Annotation + * DemoService * - * @since 2.7.0 + * @since 2.6.5 */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface RestService { -} +@Path("/demo-service") +public interface DemoService { + + @GET + String sayName(@QueryParam("name") String name); + +} \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-consumer-context.xml b/dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-consumer-context.xml new file mode 100644 index 00000000000..d4ad9324816 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-consumer-context.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-provider-context.xml b/dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-provider-context.xml new file mode 100644 index 00000000000..adf937dd544 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/resources/META-INF/spring/dubbo-provider-context.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/resources/consumer-config.properties b/dubbo-registry/dubbo-registry-nacos/src/test/resources/consumer-config.properties new file mode 100644 index 00000000000..d32e6e8a64e --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/resources/consumer-config.properties @@ -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 \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/resources/provider-config.properties b/dubbo-registry/dubbo-registry-nacos/src/test/resources/provider-config.properties new file mode 100644 index 00000000000..a52a00b2f86 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/resources/provider-config.properties @@ -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 \ No newline at end of file diff --git a/dubbo-registry/pom.xml b/dubbo-registry/pom.xml index 33a329bb0fd..ea09685010a 100644 --- a/dubbo-registry/pom.xml +++ b/dubbo-registry/pom.xml @@ -36,5 +36,6 @@ dubbo-registry-redis dubbo-registry-consul dubbo-registry-etcd3 + dubbo-registry-nacos