You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/08/09 02:40:31 UTC

[dubbo] 01/04: Change how service instance is created.

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch cloud-native
in repository https://gitbox.apache.org/repos/asf/dubbo.git

commit 550b40461197fbd9d1e6dc7ba5cb6ade8d7be77f
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Aug 8 16:03:27 2019 +0800

    Change how service instance is created.
---
 dubbo-bootstrap/pom.xml                            |   7 ++
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java | 139 +++++++++++++--------
 .../bootstrap/DubboServiceProviderBootstrap.java   |   3 +-
 .../wrapper/CompositeDynamicConfiguration.java     |   2 +-
 .../apache/dubbo/config/AbstractServiceConfig.java |   2 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |  32 +++--
 .../dubbo/config/builders/ConfigCenterBuilder.java |   1 -
 .../apache/dubbo/config/context/ConfigManager.java |   2 +-
 .../ConfigurableMetadataServiceExporter.java       |   1 +
 .../dubbo/config/DubboProviderBootstrap.java       |   5 +-
 .../org/apache/dubbo/config/mock/MockProtocol.java |   8 ++
 .../apache/dubbo/config/mock/MockProtocol2.java    |   8 ++
 .../apache/dubbo/config/mock/MockTransporter.java  |   6 +-
 .../src/main/resources/META-INF/compat/dubbo.xsd   |  10 ++
 .../src/main/resources/META-INF/dubbo.xsd          |  10 ++
 .../dubbo/metadata/WritableMetadataService.java    |   1 +
 .../client/AbstractServiceDiscoveryFactory.java    |  71 +++++++++++
 .../EventPublishingServiceDiscoveryFactory.java    |  47 -------
 .../registry/client/ServiceDiscoveryFactory.java   |  17 +--
 ...ExportedServicesRevisionMetadataCustomizer.java |   5 +-
 ...MetadataServiceURLParamsMetadataCustomizer.java |   5 +-
 .../registry/integration/RegistryProtocol.java     |   6 +
 .../registry/support/AbstractRegistryFactory.java  |   1 -
 .../registry/support/ServiceOrientedRegistry.java  |   5 +-
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 -
 .../client/InMemoryServiceDiscoveryFactory.java    |   4 +-
 .../client/ServiceDiscoveryFactoryTest.java        |  55 --------
 .../registry/etcd/EtcdServiceDiscoveryFactory.java |   6 +-
 .../nacos/NacosServiceDiscoveryFactory.java        |   5 +-
 .../ZookeeperServiceDiscoveryFactory.java          |   5 +-
 .../java/org/apache/dubbo/remoting/Channel.java    |   4 +-
 .../java/org/apache/dubbo/remoting/Endpoint.java   |   2 +-
 .../remoting/{Server.java => RemotingServer.java}  | 116 ++++++++---------
 .../org/apache/dubbo/remoting/Transporter.java     |   2 +-
 .../org/apache/dubbo/remoting/Transporters.java    |   4 +-
 .../dubbo/remoting/exchange/ExchangeServer.java    |   4 +-
 .../support/header/HeaderExchangeServer.java       |   8 +-
 .../dubbo/remoting/transport/AbstractServer.java   |   8 +-
 .../dubbo/remoting/transport/ServerDelegate.java   |  12 +-
 .../transport/grizzly/GrizzlyTransporter.java      |   4 +-
 .../org/apache/dubbo/remoting/http/HttpServer.java |   3 +-
 .../remoting/http/support/AbstractHttpServer.java  |  48 +++++++
 .../remoting/transport/mina/MinaTransporter.java   |   4 +-
 .../remoting/transport/netty/NettyServer.java      |   4 +-
 .../remoting/transport/netty/NettyTransporter.java |   4 +-
 .../transport/netty/ClientReconnectTest.java       |   8 +-
 .../remoting/transport/netty/NettyClientTest.java  |   6 +-
 .../remoting/transport/netty4/NettyServer.java     |   4 +-
 .../transport/netty4/NettyTransporter.java         |   4 +-
 .../transport/netty4/ClientReconnectTest.java      |   8 +-
 .../transport/netty4/NettyTransporterTest.java     |   4 +-
 .../java/org/apache/dubbo/remoting/p2p/Peer.java   |   4 +-
 .../exchange/support/AbstractExchangeGroup.java    |   4 +-
 .../dubbo/remoting/p2p/support/AbstractGroup.java  |   8 +-
 .../dubbo/remoting/p2p/support/ServerPeer.java     |   4 +-
 .../main/java/org/apache/dubbo/rpc/Protocol.java   |   9 ++
 .../java/org/apache/dubbo/rpc/ProtocolServer.java  |  33 +++--
 .../dubbo/rpc/protocol/AbstractProtocol.java       |  12 ++
 .../dubbo/rpc/protocol/AbstractProxyProtocol.java  |  38 ++++++
 .../dubbo/rpc/protocol/ProtocolFilterWrapper.java  |   6 +
 .../rpc/protocol/ProtocolListenerWrapper.java      |   9 +-
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    |  22 ++--
 .../rpc/protocol/dubbo/DubboProtocolServer.java    |  62 +++++++++
 .../protocol/dubbo/status/ServerStatusChecker.java |  10 +-
 .../protocol/dubbo/telnet/PortTelnetHandler.java   |  12 +-
 .../rpc/protocol/dubbo/support/ProtocolUtils.java  |   8 +-
 .../rpc/protocol/hessian/HessianProtocol.java      |  25 ++--
 .../dubbo/rpc/protocol/http/HttpProtocol.java      |  14 +--
 .../rpc/protocol/jsonrpc/JsonRpcProtocol.java      |  21 ++--
 ...RestServer.java => BaseRestProtocolServer.java} |   2 +-
 .../dubbo/rpc/protocol/rest/DubboHttpServer.java   |   4 +-
 ...ttyServer.java => NettyRestProtocolServer.java} |   6 +-
 .../dubbo/rpc/protocol/rest/RestProtocol.java      |  16 ++-
 .../{RestServer.java => RestProtocolServer.java}   |   4 +-
 .../dubbo/rpc/protocol/rest/RestServerFactory.java |   4 +-
 .../dubbo/rpc/protocol/thrift/ThriftProtocol.java  |  58 +++++++--
 .../protocol/webservice/WebServiceProtocol.java    |  15 +--
 .../xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java    |  15 ++-
 78 files changed, 727 insertions(+), 429 deletions(-)

diff --git a/dubbo-bootstrap/pom.xml b/dubbo-bootstrap/pom.xml
index 77af3e2..6f70916 100644
--- a/dubbo-bootstrap/pom.xml
+++ b/dubbo-bootstrap/pom.xml
@@ -101,6 +101,13 @@
 
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-rpc-hessian</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-remoting-netty4</artifactId>
             <version>${project.parent.version}</version>
             <scope>test</scope>
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
index 394e345..e88d9ac 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
-import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
@@ -49,10 +49,12 @@ import org.apache.dubbo.event.EventDispatcher;
 import org.apache.dubbo.event.EventListener;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.store.RemoteWritableMetadataService;
+import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.support.ServiceOrientedRegistry;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -67,16 +69,17 @@ import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
-import java.util.stream.Collectors;
 
 import static java.util.Arrays.asList;
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
 import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration;
-import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPERATOR;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
 import static org.apache.dubbo.config.context.ConfigManager.getInstance;
-import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries;
 import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
 
 /**
@@ -257,7 +260,7 @@ public class DubboBootstrap {
     }
 
     public DubboBootstrap protocols(List<ProtocolConfig> protocolConfigs) {
-        configManager.addProtocols(protocolConfigs, true);
+        configManager.addProtocols(protocolConfigs);
         return this;
     }
 
@@ -402,7 +405,7 @@ public class DubboBootstrap {
             }
         });
 
-        configManager.addProtocols(tmpProtocols, true);
+        configManager.addProtocols(tmpProtocols);
     }
 
     /**
@@ -419,31 +422,28 @@ public class DubboBootstrap {
             return;
         }
 
-        configManager.getRegistries().forEach(registryConfig -> {
-            String protocol = registryConfig.getProtocol();
-            String id = "config-center-" + protocol + "-" + registryConfig.getPort();
-            ConfigCenterConfig cc = new ConfigCenterConfig();
-            cc.setId(id);
-            cc.setParameters(registryConfig.getParameters() == null ?
-                    new HashMap<>() :
-                    new HashMap<>(registryConfig.getParameters()));
-            cc.getParameters().put(CLIENT_KEY,registryConfig.getClient());
-            cc.setProtocol(registryConfig.getProtocol());
-            cc.setAddress(registryConfig.getAddress());
-            cc.setNamespace(registryConfig.getGroup());
-            cc.setHighestPriority(false);
-            configManager.addConfigCenter(cc);
-        });
+        configManager.getDefaultRegistries().stream()
+                .filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter())
+                .forEach(registryConfig -> {
+                    String protocol = registryConfig.getProtocol();
+                    String id = "config-center-" + protocol + "-" + registryConfig.getPort();
+                    ConfigCenterConfig cc = new ConfigCenterConfig();
+                    cc.setId(id);
+                    cc.setParameters(registryConfig.getParameters() == null ?
+                            new HashMap<>() :
+                            new HashMap<>(registryConfig.getParameters()));
+                    cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
+                    cc.setProtocol(registryConfig.getProtocol());
+                    cc.setAddress(registryConfig.getAddress());
+                    cc.setNamespace(registryConfig.getGroup());
+                    cc.setHighestPriority(false);
+                    configManager.addConfigCenter(cc);
+                });
         startConfigCenter();
     }
 
-    private List<ServiceDiscovery> getServiceDiscoveries() {
-        return getRegistries()
-                .stream()
-                .filter(registry -> ServiceOrientedRegistry.class.isInstance(registry))
-                .map(registry -> ServiceOrientedRegistry.class.cast(registry))
-                .map(ServiceOrientedRegistry::getServiceDiscovery)
-                .collect(Collectors.toList());
+    private Collection<ServiceDiscovery> getServiceDiscoveries() {
+        return AbstractServiceDiscoveryFactory.getDiscoveries();
     }
 
     /**
@@ -464,16 +464,18 @@ public class DubboBootstrap {
                  * export {@link MetadataService}
                  */
                 // TODO, only export to default registry?
-                List<URL> exportedURLs = exportMetadataService(
-                        configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")),
-                        configManager.getRegistries(),
-                        configManager.getProtocols()
-                );
-
+                ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null"));
+                if (!METADATA_REMOTE.equals(applicationConfig.getMetadata())) {
+                    exportMetadataService(
+                            applicationConfig,
+                            configManager.getRegistries(),
+                            configManager.getProtocols()
+                    );
+                }
                 /**
                  * Register the local {@link ServiceInstance}
                  */
-                registerServiceInstance(exportedURLs);
+                registerServiceInstance(applicationConfig);
             }
 
             started = true;
@@ -572,12 +574,15 @@ public class DubboBootstrap {
     /* serve for builder apis, end */
 
     private void startMetadataReport() {
-        ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified."));
+        ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(
+                () -> new IllegalStateException("There's no ApplicationConfig specified.")
+        );
 
+        String metadataType = applicationConfig.getMetadata();
         // FIXME, multiple metadata config support.
         Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
         if (CollectionUtils.isEmpty(metadataReportConfigs)) {
-            if (CommonConstants.METADATA_REMOTE.equals(applicationConfig.getMetadata())) {
+            if (METADATA_REMOTE.equals(metadataType)) {
                 throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'.");
             }
             return;
@@ -588,7 +593,7 @@ public class DubboBootstrap {
         }
 
         RemoteWritableMetadataService remoteMetadataService =
-                (RemoteWritableMetadataService) WritableMetadataService.getExtension(applicationConfig.getMetadata());
+                (RemoteWritableMetadataService) WritableMetadataService.getExtension(metadataType);
         remoteMetadataService.initMetadataReport(metadataReportConfig.toUrl());
     }
 
@@ -663,21 +668,52 @@ public class DubboBootstrap {
         serviceConfig.export();
     }
 
-    private void registerServiceInstance(List<URL> exportedURLs) {
+    private void registerServiceInstance(ApplicationConfig applicationConfig) {
+        ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
+        Set<String> protocols = loader.getLoadedExtensions();
+        if (CollectionUtils.isEmpty(protocols)) {
+            throw new IllegalStateException("There should has at least one Protocol specified.");
+        }
 
-        exportedURLs
-                .stream()
-                .findFirst()
-                .ifPresent(url -> {
-                    String serviceName = url.getParameter(APPLICATION_KEY);
-                    String host = url.getHost();
-                    int port = url.getPort();
+        String protocol = findOneProtocolForServiceInstance(protocols);
 
-                    ServiceInstance serviceInstance = initServiceInstance(serviceName, host, port);
+        Protocol protocolInstance = loader.getExtension(protocol);
 
-                    getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance));
+        String serviceName = applicationConfig.getName();
+        // TODO, only support exporting one server
+        ProtocolServer server = protocolInstance.getServers().get(0);
+        String[] address = server.getAddress().split(GROUP_CHAR_SEPERATOR);
+        String host = address[0];
+        int port = Integer.parseInt(address[1]);
 
-                });
+        ServiceInstance serviceInstance = initServiceInstance(
+                serviceName,
+                host,
+                port,
+                applicationConfig.getMetadata() == null ? METADATA_DEFAULT : applicationConfig.getMetadata()
+        );
+
+        getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance));
+    }
+
+    /**
+     * If use rest protocol if there's one, otherwise, choose the first one available.
+     *
+     * @return
+     */
+    private String findOneProtocolForServiceInstance(Set<String> protocols) {
+        String result = null;
+        for (String protocol : protocols) {
+            if ("rest".equals(protocol)) {
+                result = protocol;
+                break;
+            }
+        }
+
+        if (result == null) {
+            result = protocols.iterator().next();
+        }
+        return result;
     }
 
     private void unregisterServiceInstance() {
@@ -690,8 +726,9 @@ public class DubboBootstrap {
 
     }
 
-    private ServiceInstance initServiceInstance(String serviceName, String host, int port) {
+    private ServiceInstance initServiceInstance(String serviceName, String host, int port, String metadataType) {
         this.serviceInstance = new DefaultServiceInstance(serviceName, host, port);
+        this.serviceInstance.getMetadata().put(METADATA_KEY, metadataType);
         return this.serviceInstance;
     }
 
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
index 019a61a..15d1628 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
@@ -29,9 +29,10 @@ public class DubboServiceProviderBootstrap {
                 // Zookeeper in service registry type
                 .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service"))
                 // Nacos
-                .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service"))
+//                .registry("zookeeper", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service"))
 //                .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry-type=service").build())
                 .protocol(builder -> builder.port(-1).name("dubbo"))
+                .protocol(builder -> builder.port(-1).name("hessian"))
                 .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()))
                 .start()
                 .await();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
index 700a724..3a85c41 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
@@ -27,7 +27,7 @@ import java.util.function.Consumer;
 import java.util.function.Function;
 
 /**
- * support multiple config center, simply iterating each underlying config center.
+ * support multiple config center, simply iterating each concrete config center.
  */
 public class CompositeDynamicConfiguration implements DynamicConfiguration {
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
index dc40e52..b7fb5c1 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
@@ -206,7 +206,7 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
 
     @SuppressWarnings({"unchecked"})
     public void setProtocols(List<? extends ProtocolConfig> protocols) {
-        ConfigManager.getInstance().addProtocols((List<ProtocolConfig>) protocols, false);
+        ConfigManager.getInstance().addProtocols((List<ProtocolConfig>) protocols);
         this.protocols = (List<ProtocolConfig>) protocols;
     }
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
index 22974b8..55a76c7 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
@@ -30,7 +30,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY;
 import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
-import static org.apache.dubbo.config.Constants.ZOOKEEPER_PROTOCOL;
 import static org.apache.dubbo.registry.Constants.EXTRA_KEYS_KEY;
 
 /**
@@ -151,6 +150,16 @@ public class RegistryConfig extends AbstractConfig {
      */
     private String extraKeys;
 
+    /**
+     * the address work as config center or not
+     */
+    private Boolean useAsConfigCenter;
+
+    /**
+     * the address work as remote metadata center or not
+     */
+    private Boolean useAsMetadataCenter;
+
     public RegistryConfig() {
     }
 
@@ -426,12 +435,21 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     @Parameter(excluded = true)
-    public boolean isZookeeperProtocol() {
-        if (!isValid()) {
-            return false;
-        }
-        return ZOOKEEPER_PROTOCOL.equals(getProtocol())
-                || getAddress().startsWith(ZOOKEEPER_PROTOCOL);
+    public Boolean getUseAsConfigCenter() {
+        return useAsConfigCenter;
+    }
+
+    public void setUseAsConfigCenter(Boolean useAsConfigCenter) {
+        this.useAsConfigCenter = useAsConfigCenter;
+    }
+
+    @Parameter(excluded = true)
+    public Boolean getUseAsMetadataCenter() {
+        return useAsMetadataCenter;
+    }
+
+    public void setUseAsMetadataCenter(Boolean useAsMetadataCenter) {
+        this.useAsMetadataCenter = useAsMetadataCenter;
     }
 
     @Override
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ConfigCenterBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ConfigCenterBuilder.java
index 87ac00f..590170c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ConfigCenterBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ConfigCenterBuilder.java
@@ -38,7 +38,6 @@ public class ConfigCenterBuilder extends AbstractBuilder<ConfigCenterConfig, Con
     private Boolean highestPriority = true;
     private Boolean check = true;
 
-    private String appName;
     private String configFile = "dubbo.properties";
     private String appConfigFile;
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
index 1888819..07895ec 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
@@ -228,7 +228,7 @@ public class ConfigManager {
         addIfAbsent(protocolConfig, protocols);
     }
 
-    public void addProtocols(Iterable<ProtocolConfig> protocolConfigs, boolean canBeDefault) {
+    public void addProtocols(Iterable<ProtocolConfig> protocolConfigs) {
         if (protocolConfigs != null) {
             protocolConfigs.forEach(this::addProtocol);
         }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
index 8806f03..21601ad 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
@@ -79,6 +79,7 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
 
         if (!isExported()) {
 
+            // FIXME, if uses remote metadata center, does not need to export MetadataService locally.
             WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
 
             ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java
index ce5cd6a..9b68c68 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
@@ -67,9 +68,9 @@ public class DubboProviderBootstrap {
         // 暴露 MetadataService 服务
         exporter.export();
 
-        ServiceDiscoveryFactory factory = ServiceDiscoveryFactory.getDefaultExtension();
+        ServiceDiscoveryFactory factory = ExtensionLoader.getExtensionLoader(ServiceDiscoveryFactory.class).getAdaptiveExtension();
 
-        ServiceDiscovery serviceDiscovery = factory.create(connectionURL);
+        ServiceDiscovery serviceDiscovery = factory.getDiscovery(connectionURL);
 
         serviceDiscovery.start();
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol.java
index 7c33d9c..e5b0dc3 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol.java
@@ -21,11 +21,14 @@ import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcException;
 
 import org.mockito.Mockito;
 
+import java.util.List;
+
 public class MockProtocol implements Protocol {
 
     /* (non-Javadoc)
@@ -85,4 +88,9 @@ public class MockProtocol implements Protocol {
 
     }
 
+    @Override
+    public List<ProtocolServer> getServers() {
+        return null;
+    }
+
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol2.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol2.java
index 91653d4..ec68c1a 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol2.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockProtocol2.java
@@ -21,8 +21,11 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
 
+import java.util.List;
+
 public class MockProtocol2 implements Protocol {
     public static Protocol delegate;
 
@@ -45,4 +48,9 @@ public class MockProtocol2 implements Protocol {
     public void destroy() {
         delegate.destroy();
     }
+
+    @Override
+    public List<ProtocolServer> getServers() {
+        return delegate.getServers();
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockTransporter.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockTransporter.java
index 8abfe19..28bce33 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockTransporter.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockTransporter.java
@@ -21,17 +21,17 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 
 import org.mockito.Mockito;
 
 public class MockTransporter implements Transporter {
-    private Server server = Mockito.mock(Server.class);
+    private RemotingServer server = Mockito.mock(RemotingServer.class);
     private Client client = Mockito.mock(Client.class);
 
     @Override
-    public Server bind(URL url, ChannelHandler handler) throws RemotingException {
+    public RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException {
         return server;
     }
 
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index 4331ea4..e926994 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -580,6 +580,16 @@
                 <xsd:documentation><![CDATA[ Extra Parameter Keys. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="use-as-config-center" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ work as config center or not. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="use-as-metadata-center" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ work as metadata center or not. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="metadataReportType">
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index f7124c8..d75b51b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -574,6 +574,16 @@
                 <xsd:documentation><![CDATA[ Extra Parameter Keys. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="use-as-config-center" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ work as config center or not. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="use-as-metadata-center" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ work as metadata center or not. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="metadataReportType">
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
index f1a1ea4..478bd93 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
@@ -91,4 +91,5 @@ public interface WritableMetadataService extends MetadataService {
         return getExtensionLoader(WritableMetadataService.class).getExtension(name);
     }
 
+
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java
new file mode 100644
index 0000000..c9c6ec0
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.client;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public abstract class AbstractServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+
+    private static final Logger logger = LoggerFactory.getLogger(AbstractServiceDiscoveryFactory.class);
+
+    private static ConcurrentMap<String, ServiceDiscovery> discoveries = new ConcurrentHashMap<>();
+
+    public static Collection<ServiceDiscovery> getDiscoveries() {
+        return Collections.unmodifiableCollection(discoveries.values());
+    }
+
+    /**
+     * Close all created registries
+     */
+    public static void destroyAll() {
+        if (logger.isInfoEnabled()) {
+            logger.info("Closing all ServiceDicovery instances: " + getDiscoveries());
+        }
+
+        for (ServiceDiscovery discovery : getDiscoveries()) {
+            try {
+                discovery.stop();
+            } catch (Throwable e) {
+                logger.error("Error trying to close ServiceDiscovery instance.", e);
+            }
+        }
+        discoveries.clear();
+    }
+
+    /**
+     * @param url "zookeeper://ip:port/RegistryService?xxx"
+     * @return
+     */
+    @Override
+    public ServiceDiscovery getDiscovery(URL url) {
+        String key = url.toServiceStringWithoutResolving();
+
+        return discoveries.computeIfAbsent(key, k -> {
+            ServiceDiscovery discovery = createDiscovery(url);
+            return new EventPublishingServiceDiscovery(discovery);
+        });
+    }
+
+    protected abstract ServiceDiscovery createDiscovery(URL url);
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryFactory.java
deleted file mode 100644
index 00d8bb6..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryFactory.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.apache.dubbo.registry.client;/*
- * 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.
- */
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-
-import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
-
-/**
- * The factory class to create an instance of {@link ServiceDiscoveryFactory} based on Event-Publishing as the default
- * {@link SPI} implementation
- *
- * @see ServiceDiscoveryFactory
- * @see EventPublishingServiceDiscovery
- * @see ServiceDiscovery
- * @since 2.7.4
- */
-public class EventPublishingServiceDiscoveryFactory implements ServiceDiscoveryFactory {
-
-    private static final Class<ServiceDiscoveryFactory> FACTORY_CLASS = ServiceDiscoveryFactory.class;
-
-    @Override
-    public ServiceDiscovery create(URL connectionURL) {
-        String protocol = connectionURL.getProtocol();
-        ServiceDiscoveryFactory serviceDiscoveryFactory = loadFactoryByProtocol(protocol);
-        ServiceDiscovery originalServiceDiscovery = serviceDiscoveryFactory.create(connectionURL);
-        return new EventPublishingServiceDiscovery(originalServiceDiscovery);
-    }
-
-    protected ServiceDiscoveryFactory loadFactoryByProtocol(String protocol) {
-        return getExtensionLoader(FACTORY_CLASS).getExtension(protocol);
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java
index a48b9a8..20257f4 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java
@@ -17,17 +17,16 @@
 package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Adaptive;
 import org.apache.dubbo.common.extension.SPI;
 
-import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
-
 /**
  * The Factory interface to create an instance of {@link ServiceDiscovery}
  *
  * @see ServiceDiscovery
  * @since 2.7.4
  */
-@SPI("event-publishing")
+@SPI("zookeeper")
 public interface ServiceDiscoveryFactory {
 
     /**
@@ -36,14 +35,6 @@ public interface ServiceDiscoveryFactory {
      * @param connectionURL the  {@link URL connection url}
      * @return an instance of {@link ServiceDiscovery}
      */
-    ServiceDiscovery create(URL connectionURL);
-
-    /**
-     * Get the default extension of {@link ServiceDiscoveryFactory}
-     *
-     * @return non-null
-     */
-    static ServiceDiscoveryFactory getDefaultExtension() {
-        return getExtensionLoader(ServiceDiscoveryFactory.class).getDefaultExtension();
-    }
+    @Adaptive({"protocol"})
+    ServiceDiscovery getDiscovery(URL connectionURL);
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
index 920096a..8c3c9d5 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
@@ -29,6 +29,7 @@ import java.util.List;
 
 import static java.lang.String.valueOf;
 import static java.util.Objects.hash;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY;
 
 /**
@@ -47,7 +48,9 @@ public class ExportedServicesRevisionMetadataCustomizer extends ServiceInstanceM
 
     @Override
     protected String buildMetadataValue(ServiceInstance serviceInstance) {
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getExtension(
+                serviceInstance.getMetadata().get(METADATA_KEY)
+        );
         List<String> exportedURLs = writableMetadataService.getExportedURLs();
         Object[] data = exportedURLs.stream()
                 .map(URL::valueOf)                       // String to URL
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
index 754a275..ed86919 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
@@ -24,6 +24,7 @@ import org.apache.dubbo.registry.client.ServiceInstanceMetadataCustomizer;
 
 import java.util.List;
 
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
 import static org.apache.dubbo.metadata.MetadataService.toURLs;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceParameter;
@@ -45,7 +46,9 @@ public class MetadataServiceURLParamsMetadataCustomizer extends ServiceInstanceM
     @Override
     public String buildMetadataValue(ServiceInstance serviceInstance) {
 
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getExtension(
+                serviceInstance.getMetadata().get(METADATA_KEY)
+        );
 
         String serviceInterface = MetadataService.class.getName();
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
index fbf194f..bae63ec 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
@@ -34,6 +34,7 @@ import org.apache.dubbo.registry.RegistryService;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.cluster.Cluster;
@@ -446,6 +447,11 @@ public class RegistryProtocol implements Protocol {
                 .removeListener(ApplicationModel.getApplication() + CONFIGURATORS_SUFFIX, providerConfigurationListener);
     }
 
+    @Override
+    public List<ProtocolServer> getServers() {
+        return protocol.getServers();
+    }
+
     //Merge the urls of configurators
     private static URL getConfigedInvokerUrl(List<Configurator> configurators, URL url) {
         if (configurators != null && configurators.size() > 0) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
index 9441b36..0458ada 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
@@ -62,7 +62,6 @@ public abstract class AbstractRegistryFactory implements RegistryFactory {
     /**
      * Close all created registries
      */
-    // TODO: 2017/8/30 to move somewhere else better
     public static void destroyAll() {
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info("Close all registries " + getRegistries());
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java
index 8018eff..ba1976b 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.registry.support;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.StringUtils;
@@ -114,8 +115,8 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
     }
 
     private ServiceDiscovery buildServiceDiscovery(URL url) {
-        ServiceDiscoveryFactory serviceDiscoveryFactory = ServiceDiscoveryFactory.getDefaultExtension();
-        ServiceDiscovery serviceDiscovery = serviceDiscoveryFactory.create(url);
+        ServiceDiscoveryFactory factory = ExtensionLoader.getExtensionLoader(ServiceDiscoveryFactory.class).getAdaptiveExtension();
+        ServiceDiscovery serviceDiscovery = factory.getDiscovery(url);
         serviceDiscovery.start();
         return serviceDiscovery;
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
deleted file mode 100644
index 20b8e66..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ /dev/null
@@ -1 +0,0 @@
-event-publishing=org.apache.dubbo.registry.client.EventPublishingServiceDiscoveryFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
index bbd3639..6264611 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
@@ -24,10 +24,10 @@ import org.apache.dubbo.common.URL;
  * @see InMemoryServiceDiscovery
  * @since 2.7.4
  */
-public class InMemoryServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+public class InMemoryServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
 
     @Override
-    public ServiceDiscovery create(URL connectionURL) {
+    public ServiceDiscovery createDiscovery(URL connectionURL) {
         return new InMemoryServiceDiscovery();
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactoryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactoryTest.java
deleted file mode 100644
index 01c2fbd..0000000
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactoryTest.java
+++ /dev/null
@@ -1,55 +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.registry.client;
-
-import org.apache.dubbo.common.URL;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.apache.dubbo.common.URL.valueOf;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * {@link ServiceDiscoveryFactory} Test
- *
- * @since 2.7.4
- */
-public class ServiceDiscoveryFactoryTest {
-
-    private static final URL dubboURL = valueOf("dubbo://localhost:20880");
-
-    private static final URL inMemoryURL = valueOf("in-memory://localhost:12345");
-
-    private ServiceDiscoveryFactory serviceDiscoveryFactory;
-
-    @BeforeEach
-    public void init() {
-        serviceDiscoveryFactory = ServiceDiscoveryFactory.getDefaultExtension();
-    }
-
-    @Test
-    public void testClass() {
-        assertEquals(EventPublishingServiceDiscoveryFactory.class, serviceDiscoveryFactory.getClass());
-    }
-
-    @Test
-    public void testCreate() {
-        ServiceDiscovery serviceDiscovery = serviceDiscoveryFactory.create(inMemoryURL);
-        assertEquals(EventPublishingServiceDiscovery.class, serviceDiscovery.getClass());
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java
index 8d1e3b5..fb75006 100644
--- a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java
@@ -17,14 +17,14 @@
 package org.apache.dubbo.registry.etcd;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
 import org.apache.dubbo.remoting.etcd.EtcdTransporter;
 
 /**
  * 2019-07-08
  */
-public class EtcdServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+public class EtcdServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
 
     private EtcdTransporter etcdTransporter;
 
@@ -33,7 +33,7 @@ public class EtcdServiceDiscoveryFactory implements ServiceDiscoveryFactory {
     }
 
     @Override
-    public ServiceDiscovery create(URL connectionURL) {
+    public ServiceDiscovery createDiscovery(URL connectionURL) {
         return new EtcdServiceDiscovery(connectionURL, etcdTransporter);
     }
 }
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java
index 4e5709e..e2ac08b 100644
--- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java
@@ -16,6 +16,7 @@ package org.apache.dubbo.registry.nacos;/*
  */
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
 
@@ -26,10 +27,10 @@ import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
  * @see ServiceDiscovery
  * @since 2.7.4
  */
-public class NacosServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+public class NacosServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
 
     @Override
-    public ServiceDiscovery create(URL connectionURL) {
+    public ServiceDiscovery createDiscovery(URL connectionURL) {
         return new NacosServiceDiscovery(connectionURL);
     }
 }
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
index 44488a4..4bf354d 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.registry.zookeeper;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
 
@@ -26,10 +27,10 @@ import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
  * @see ServiceDiscoveryFactory
  * @since 2.7.4
  */
-public class ZookeeperServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+public class ZookeeperServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
 
     @Override
-    public ServiceDiscovery create(URL connectionURL) {
+    public ServiceDiscovery createDiscovery(URL connectionURL) {
         try {
             return new ZookeeperServiceDiscovery(connectionURL);
         } catch (Exception e) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java
index aa54b7a..c88cb4f 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java
@@ -22,8 +22,8 @@ import java.net.InetSocketAddress;
  * Channel. (API/SPI, Prototype, ThreadSafe)
  *
  * @see org.apache.dubbo.remoting.Client
- * @see org.apache.dubbo.remoting.Server#getChannels()
- * @see org.apache.dubbo.remoting.Server#getChannel(InetSocketAddress)
+ * @see RemotingServer#getChannels()
+ * @see RemotingServer#getChannel(InetSocketAddress)
  */
 public interface Channel extends Endpoint {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java
index 0b69e1b..caafa9e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java
@@ -26,7 +26,7 @@ import java.net.InetSocketAddress;
  *
  * @see org.apache.dubbo.remoting.Channel
  * @see org.apache.dubbo.remoting.Client
- * @see org.apache.dubbo.remoting.Server
+ * @see RemotingServer
  */
 public interface Endpoint {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Server.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingServer.java
similarity index 92%
rename from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Server.java
rename to dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingServer.java
index c6ecf16..2c60d39 100755
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Server.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingServer.java
@@ -1,58 +1,58 @@
-/*
- * 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.remoting;
-
-import org.apache.dubbo.common.Resetable;
-
-import java.net.InetSocketAddress;
-import java.util.Collection;
-
-/**
- * Remoting Server. (API/SPI, Prototype, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Client%E2%80%93server_model">Client/Server</a>
- *
- * @see org.apache.dubbo.remoting.Transporter#bind(org.apache.dubbo.common.URL, ChannelHandler)
- */
-public interface Server extends Endpoint, Resetable, IdleSensible {
-
-    /**
-     * is bound.
-     *
-     * @return bound
-     */
-    boolean isBound();
-
-    /**
-     * get channels.
-     *
-     * @return channels
-     */
-    Collection<Channel> getChannels();
-
-    /**
-     * get channel.
-     *
-     * @param remoteAddress
-     * @return channel
-     */
-    Channel getChannel(InetSocketAddress remoteAddress);
-
-    @Deprecated
-    void reset(org.apache.dubbo.common.Parameters parameters);
-
-}
+/*
+ * 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.remoting;
+
+import org.apache.dubbo.common.Resetable;
+
+import java.net.InetSocketAddress;
+import java.util.Collection;
+
+/**
+ * Remoting Server. (API/SPI, Prototype, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Client%E2%80%93server_model">Client/Server</a>
+ *
+ * @see org.apache.dubbo.remoting.Transporter#bind(org.apache.dubbo.common.URL, ChannelHandler)
+ */
+public interface RemotingServer extends Endpoint, Resetable, IdleSensible {
+
+    /**
+     * is bound.
+     *
+     * @return bound
+     */
+    boolean isBound();
+
+    /**
+     * get channels.
+     *
+     * @return channels
+     */
+    Collection<Channel> getChannels();
+
+    /**
+     * get channel.
+     *
+     * @param remoteAddress
+     * @return channel
+     */
+    Channel getChannel(InetSocketAddress remoteAddress);
+
+    @Deprecated
+    void reset(org.apache.dubbo.common.Parameters parameters);
+
+}
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java
index 2266b82..9bee120 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java
@@ -41,7 +41,7 @@ public interface Transporter {
      * @see org.apache.dubbo.remoting.Transporters#bind(URL, ChannelHandler...)
      */
     @Adaptive({Constants.SERVER_KEY, Constants.TRANSPORTER_KEY})
-    Server bind(URL url, ChannelHandler handler) throws RemotingException;
+    RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException;
 
     /**
      * Connect to a server.
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java
index 2d008af..bd64854 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java
@@ -36,11 +36,11 @@ public class Transporters {
     private Transporters() {
     }
 
-    public static Server bind(String url, ChannelHandler... handler) throws RemotingException {
+    public static RemotingServer bind(String url, ChannelHandler... handler) throws RemotingException {
         return bind(URL.valueOf(url), handler);
     }
 
-    public static Server bind(URL url, ChannelHandler... handlers) throws RemotingException {
+    public static RemotingServer bind(URL url, ChannelHandler... handlers) throws RemotingException {
         if (url == null) {
             throw new IllegalArgumentException("url == null");
         }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java
index 8bce090..8c52f47 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java
@@ -16,7 +16,7 @@
  */
 package org.apache.dubbo.remoting.exchange;
 
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 
 import java.net.InetSocketAddress;
 import java.util.Collection;
@@ -24,7 +24,7 @@ import java.util.Collection;
 /**
  * ExchangeServer. (API/SPI, Prototype, ThreadSafe)
  */
-public interface ExchangeServer extends Server {
+public interface ExchangeServer extends RemotingServer {
 
     /**
      * get channels.
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
index c0524ab..93cd66a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
@@ -28,7 +28,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.exchange.ExchangeChannel;
 import org.apache.dubbo.remoting.exchange.ExchangeServer;
 import org.apache.dubbo.remoting.exchange.Request;
@@ -53,7 +53,7 @@ public class HeaderExchangeServer implements ExchangeServer {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final Server server;
+    private final RemotingServer server;
     private AtomicBoolean closed = new AtomicBoolean(false);
 
     private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer(new NamedThreadFactory("dubbo-server-idleCheck", true), 1,
@@ -61,13 +61,13 @@ public class HeaderExchangeServer implements ExchangeServer {
 
     private CloseTimerTask closeTimerTask;
 
-    public HeaderExchangeServer(Server server) {
+    public HeaderExchangeServer(RemotingServer server) {
         Assert.notNull(server, "server == null");
         this.server = server;
         startIdleCheckTask(getUrl());
     }
 
-    public Server getServer() {
+    public RemotingServer getServer() {
         return server;
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java
index d1cbdbb..f8f867b 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java
@@ -27,7 +27,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 
 import java.net.InetSocketAddress;
 import java.util.Collection;
@@ -37,15 +37,15 @@ import java.util.concurrent.ThreadPoolExecutor;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY;
-import static org.apache.dubbo.remoting.Constants.IDLE_TIMEOUT_KEY;
-import static org.apache.dubbo.remoting.Constants.DEFAULT_IDLE_TIMEOUT;
 import static org.apache.dubbo.remoting.Constants.ACCEPTS_KEY;
 import static org.apache.dubbo.remoting.Constants.DEFAULT_ACCEPTS;
+import static org.apache.dubbo.remoting.Constants.DEFAULT_IDLE_TIMEOUT;
+import static org.apache.dubbo.remoting.Constants.IDLE_TIMEOUT_KEY;
 
 /**
  * AbstractServer
  */
-public abstract class AbstractServer extends AbstractEndpoint implements Server {
+public abstract class AbstractServer extends AbstractEndpoint implements RemotingServer {
 
     protected static final String SERVER_THREAD_POOL_NAME = "DubboServerHandler";
     private static final Logger logger = LoggerFactory.getLogger(AbstractServer.class);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java
index 6aeed60..49b508a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 
 import java.net.InetSocketAddress;
 import java.util.Collection;
@@ -30,22 +30,22 @@ import java.util.Collection;
  *
  *
  */
-public class ServerDelegate implements Server {
+public class ServerDelegate implements RemotingServer {
 
-    private transient Server server;
+    private transient RemotingServer server;
 
     public ServerDelegate() {
     }
 
-    public ServerDelegate(Server server) {
+    public ServerDelegate(RemotingServer server) {
         setServer(server);
     }
 
-    public Server getServer() {
+    public RemotingServer getServer() {
         return server;
     }
 
-    public void setServer(Server server) {
+    public void setServer(RemotingServer server) {
         this.server = server;
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-grizzly/src/main/java/org/apache/dubbo/remoting/transport/grizzly/GrizzlyTransporter.java b/dubbo-remoting/dubbo-remoting-grizzly/src/main/java/org/apache/dubbo/remoting/transport/grizzly/GrizzlyTransporter.java
index bac7d65..8e30dad 100644
--- a/dubbo-remoting/dubbo-remoting-grizzly/src/main/java/org/apache/dubbo/remoting/transport/grizzly/GrizzlyTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-grizzly/src/main/java/org/apache/dubbo/remoting/transport/grizzly/GrizzlyTransporter.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 
 /**
@@ -31,7 +31,7 @@ public class GrizzlyTransporter implements Transporter {
     public static final String NAME = "grizzly";
 
     @Override
-    public Server bind(URL url, ChannelHandler listener) throws RemotingException {
+    public RemotingServer bind(URL url, ChannelHandler listener) throws RemotingException {
         return new GrizzlyServer(url, listener);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java
index 2ff7692..643fda4 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java
@@ -18,10 +18,11 @@ package org.apache.dubbo.remoting.http;
 
 import org.apache.dubbo.common.Resetable;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingServer;
 
 import java.net.InetSocketAddress;
 
-public interface HttpServer extends Resetable {
+public interface HttpServer extends Resetable, RemotingServer {
 
     /**
      * get http handler.
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/support/AbstractHttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/support/AbstractHttpServer.java
index ba4928d..2d87274 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/support/AbstractHttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/support/AbstractHttpServer.java
@@ -16,11 +16,16 @@
  */
 package org.apache.dubbo.remoting.http.support;
 
+import org.apache.dubbo.common.Parameters;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.ChannelHandler;
+import org.apache.dubbo.remoting.RemotingException;
 import org.apache.dubbo.remoting.http.HttpHandler;
 import org.apache.dubbo.remoting.http.HttpServer;
 
 import java.net.InetSocketAddress;
+import java.util.Collection;
 
 /**
  * AbstractHttpServer
@@ -83,4 +88,47 @@ public abstract class AbstractHttpServer implements HttpServer {
         return closed;
     }
 
+    /**
+     * Following methods are extended from RemotingServer, useless for http servers
+     */
+
+    @Override
+    public boolean canHandleIdle() {
+        return false;
+    }
+
+    @Override
+    public Collection<Channel> getChannels() {
+        return null;
+    }
+
+    @Override
+    public Channel getChannel(InetSocketAddress remoteAddress) {
+        return null;
+    }
+
+    @Override
+    public void reset(Parameters parameters) {
+
+    }
+
+    @Override
+    public ChannelHandler getChannelHandler() {
+        return null;
+    }
+
+    @Override
+    public void send(Object message) throws RemotingException {
+
+    }
+
+    @Override
+    public void send(Object message, boolean sent) throws RemotingException {
+
+    }
+
+    @Override
+    public void startClose() {
+
+    }
 }
diff --git a/dubbo-remoting/dubbo-remoting-mina/src/main/java/org/apache/dubbo/remoting/transport/mina/MinaTransporter.java b/dubbo-remoting/dubbo-remoting-mina/src/main/java/org/apache/dubbo/remoting/transport/mina/MinaTransporter.java
index 4efdb13..d8739f4 100644
--- a/dubbo-remoting/dubbo-remoting-mina/src/main/java/org/apache/dubbo/remoting/transport/mina/MinaTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-mina/src/main/java/org/apache/dubbo/remoting/transport/mina/MinaTransporter.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 
 public class MinaTransporter implements Transporter {
@@ -28,7 +28,7 @@ public class MinaTransporter implements Transporter {
     public static final String NAME = "mina";
 
     @Override
-    public Server bind(URL url, ChannelHandler handler) throws RemotingException {
+    public RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException {
         return new MinaServer(url, handler);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java
index 8d1cc3f..34bfab5 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java
@@ -27,7 +27,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.transport.AbstractServer;
 import org.apache.dubbo.remoting.transport.dispatcher.ChannelHandlers;
 
@@ -50,7 +50,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.IO_THREADS_KEY;
 /**
  * NettyServer
  */
-public class NettyServer extends AbstractServer implements Server {
+public class NettyServer extends AbstractServer implements RemotingServer {
 
     private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
 
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java
index f154a60..7ce2d03 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 
 public class NettyTransporter implements Transporter {
@@ -28,7 +28,7 @@ public class NettyTransporter implements Transporter {
     public static final String NAME = "netty3";
 
     @Override
-    public Server bind(URL url, ChannelHandler listener) throws RemotingException {
+    public RemotingServer bind(URL url, ChannelHandler listener) throws RemotingException {
         return new NettyServer(url, listener);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java
index d328eb0..65fa6a0 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.exchange.Exchangers;
 import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;
 
@@ -46,7 +46,7 @@ public class ClientReconnectTest {
             int port = NetUtils.getAvailablePort();
             Client client = startClient(port, 200);
             Assertions.assertFalse(client.isConnected());
-            Server server = startServer(port);
+            RemotingServer server = startServer(port);
             for (int i = 0; i < 100 && !client.isConnected(); i++) {
                 Thread.sleep(10);
             }
@@ -58,7 +58,7 @@ public class ClientReconnectTest {
             int port = NetUtils.getAvailablePort();
             Client client = startClient(port, 20000);
             Assertions.assertFalse(client.isConnected());
-            Server server = startServer(port);
+            RemotingServer server = startServer(port);
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(200);
             }
@@ -74,7 +74,7 @@ public class ClientReconnectTest {
         return Exchangers.connect(url);
     }
 
-    public Server startServer(int port) throws RemotingException {
+    public RemotingServer startServer(int port) throws RemotingException {
         final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?server=netty3";
         return Exchangers.bind(url, new HandlerAdapter());
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java
index af4fca1..0290529 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java
@@ -18,7 +18,7 @@ package org.apache.dubbo.remoting.transport.netty;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.exchange.ExchangeChannel;
 import org.apache.dubbo.remoting.exchange.Exchangers;
 
@@ -34,7 +34,7 @@ import java.util.List;
  * Time: 5:47 PM
  */
 public class NettyClientTest {
-    static Server server;
+    static RemotingServer server;
 
 
     @BeforeAll
@@ -73,7 +73,7 @@ public class NettyClientTest {
     @Test
     public void testServerClose() throws Exception {
         for (int i = 0; i < 100; i++) {
-            Server aServer = Exchangers.bind(URL.valueOf("exchange://localhost:" + (6000 + i) + "?server=netty3"), new TelnetServerHandler());
+            RemotingServer aServer = Exchangers.bind(URL.valueOf("exchange://localhost:" + (6000 + i) + "?server=netty3"), new TelnetServerHandler());
             aServer.close();
         }
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java
index 0cdd9f7..882ecc8 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java
@@ -25,7 +25,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.transport.AbstractServer;
 import org.apache.dubbo.remoting.transport.dispatcher.ChannelHandlers;
 import org.apache.dubbo.remoting.utils.UrlUtils;
@@ -53,7 +53,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.IO_THREADS_KEY;
 /**
  * NettyServer.
  */
-public class NettyServer extends AbstractServer implements Server {
+public class NettyServer extends AbstractServer implements RemotingServer {
 
     private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
     /**
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporter.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporter.java
index fce2df1..c6e75af 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporter.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 
 /**
@@ -31,7 +31,7 @@ public class NettyTransporter implements Transporter {
     public static final String NAME = "netty";
 
     @Override
-    public Server bind(URL url, ChannelHandler listener) throws RemotingException {
+    public RemotingServer bind(URL url, ChannelHandler listener) throws RemotingException {
         return new NettyServer(url, listener);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientReconnectTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientReconnectTest.java
index 3c357ce..22156fa 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientReconnectTest.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientReconnectTest.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.exchange.Exchangers;
 import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;
 
@@ -49,7 +49,7 @@ public class ClientReconnectTest {
             int port = NetUtils.getAvailablePort();
             Client client = startClient(port, 200);
             Assertions.assertFalse(client.isConnected());
-            Server server = startServer(port);
+            RemotingServer server = startServer(port);
             for (int i = 0; i < 100 && !client.isConnected(); i++) {
                 Thread.sleep(10);
             }
@@ -61,7 +61,7 @@ public class ClientReconnectTest {
             int port = NetUtils.getAvailablePort();
             Client client = startClient(port, 20000);
             Assertions.assertFalse(client.isConnected());
-            Server server = startServer(port);
+            RemotingServer server = startServer(port);
             for (int i = 0; i < 5; i++) {
                 Thread.sleep(200);
             }
@@ -77,7 +77,7 @@ public class ClientReconnectTest {
         return Exchangers.connect(url);
     }
 
-    public Server startServer(int port) throws RemotingException {
+    public RemotingServer startServer(int port) throws RemotingException {
         final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?server=netty4";
         return Exchangers.bind(url, new HandlerAdapter());
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporterTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporterTest.java
index 41937aa..74e263e 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporterTest.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporterTest.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter;
 
 import org.junit.jupiter.api.Test;
@@ -38,7 +38,7 @@ public class NettyTransporterTest {
         URL url = new URL("http", "localhost", port,
                 new String[]{Constants.BIND_PORT_KEY, String.valueOf(port)});
 
-        Server server = new NettyTransporter().bind(url, new ChannelHandlerAdapter());
+        RemotingServer server = new NettyTransporter().bind(url, new ChannelHandlerAdapter());
 
         assertThat(server.isBound(), is(true));
     }
diff --git a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/Peer.java b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/Peer.java
index b693f76..9d23eac 100644
--- a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/Peer.java
+++ b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/Peer.java
@@ -17,14 +17,14 @@
 package org.apache.dubbo.remoting.p2p;
 
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 
 /**
  * Peer. (SPI, Prototype, ThreadSafe)
  * <p>
  * <a href="http://en.wikipedia.org/wiki/Peer-to-peer">Peer-to-peer</a>
  */
-public interface Peer extends Server {
+public interface Peer extends RemotingServer {
 
     /**
      * leave.
diff --git a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/exchange/support/AbstractExchangeGroup.java b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/exchange/support/AbstractExchangeGroup.java
index 8408f65..55f1a92 100644
--- a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/exchange/support/AbstractExchangeGroup.java
+++ b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/exchange/support/AbstractExchangeGroup.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.exchange.ExchangeClient;
 import org.apache.dubbo.remoting.exchange.ExchangeHandler;
 import org.apache.dubbo.remoting.exchange.ExchangeServer;
@@ -100,7 +100,7 @@ public abstract class AbstractExchangeGroup implements ExchangeGroup {
 
     @Override
     public void leave(URL url) throws RemotingException {
-        Server server = servers.remove(url);
+        RemotingServer server = servers.remove(url);
         if (server != null) {
             server.close();
         }
diff --git a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/AbstractGroup.java b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/AbstractGroup.java
index ffe5c69..0ea76f9 100644
--- a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/AbstractGroup.java
+++ b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/AbstractGroup.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporters;
 import org.apache.dubbo.remoting.p2p.Group;
 import org.apache.dubbo.remoting.p2p.Peer;
@@ -42,7 +42,7 @@ public abstract class AbstractGroup implements Group {
 
     protected final URL url;
 
-    protected final Map<URL, Server> servers = new ConcurrentHashMap<URL, Server>();
+    protected final Map<URL, RemotingServer> servers = new ConcurrentHashMap<URL, RemotingServer>();
 
     protected final Map<URL, Client> clients = new ConcurrentHashMap<URL, Client>();
 
@@ -80,7 +80,7 @@ public abstract class AbstractGroup implements Group {
 
     @Override
     public Peer join(URL url, ChannelHandler handler) throws RemotingException {
-        Server server = servers.get(url);
+        RemotingServer server = servers.get(url);
         if (server == null) { // TODO exist concurrent gap
             server = Transporters.bind(url, handler);
             servers.put(url, server);
@@ -91,7 +91,7 @@ public abstract class AbstractGroup implements Group {
 
     @Override
     public void leave(URL url) throws RemotingException {
-        Server server = servers.remove(url);
+        RemotingServer server = servers.remove(url);
         if (server != null) {
             server.close();
         }
diff --git a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/ServerPeer.java b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/ServerPeer.java
index cff3342..3d10907 100644
--- a/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/ServerPeer.java
+++ b/dubbo-remoting/dubbo-remoting-p2p/src/main/java/org/apache/dubbo/remoting/p2p/support/ServerPeer.java
@@ -23,7 +23,7 @@ import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Client;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
-import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.p2p.Group;
 import org.apache.dubbo.remoting.p2p.Peer;
 import org.apache.dubbo.remoting.transport.ServerDelegate;
@@ -44,7 +44,7 @@ public class ServerPeer extends ServerDelegate implements Peer {
 
     private final Group group;
 
-    public ServerPeer(Server server, Map<URL, Client> clients, Group group) {
+    public ServerPeer(RemotingServer server, Map<URL, Client> clients, Group group) {
         super(server);
         this.clients = clients;
         this.group = group;
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java
index f5705e5..8d8d4b9 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java
@@ -20,6 +20,8 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
 import org.apache.dubbo.common.extension.SPI;
 
+import java.util.List;
+
 /**
  * Protocol. (API/SPI, Singleton, ThreadSafe)
  */
@@ -75,4 +77,11 @@ public interface Protocol {
      */
     void destroy();
 
+    /**
+     * Get all servers serving this protocol
+     *
+     * @return
+     */
+    List<ProtocolServer> getServers();
+
 }
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProtocolServer.java
similarity index 59%
copy from dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
copy to dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProtocolServer.java
index bbd3639..3da2b95 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProtocolServer.java
@@ -14,20 +14,35 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.client;
+package org.apache.dubbo.rpc;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingServer;
 
 /**
- * {@link InMemoryServiceDiscovery} Factory
- *
- * @see InMemoryServiceDiscovery
- * @since 2.7.4
+ * Distinct from {@link RemotingServer}, each protocol holds one or more ProtocolServers(the number usually decides by port numbers),
+ * while each ProtocolServer holds zero or one RemotingServer.
  */
-public class InMemoryServiceDiscoveryFactory implements ServiceDiscoveryFactory {
+public interface ProtocolServer {
+
+    default RemotingServer getRemotingServer() {
+        return null;
+    }
+
+    default void setRemotingServers() {
 
-    @Override
-    public ServiceDiscovery create(URL connectionURL) {
-        return new InMemoryServiceDiscovery();
     }
+
+    String getAddress();
+
+    void setAddress();
+
+    default URL getUrl() {
+        return null;
+    }
+
+    default void reset(URL url) {
+    }
+
+    void close();
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java
index ceeb92e..03fa1d3 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java
@@ -24,10 +24,13 @@ import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -44,6 +47,11 @@ public abstract class AbstractProtocol implements Protocol {
 
     protected final Map<String, Exporter<?>> exporterMap = new ConcurrentHashMap<String, Exporter<?>>();
 
+    /**
+     * <host:port, ProtocolServer>
+     */
+    protected final Map<String, ProtocolServer> serverMap = new ConcurrentHashMap<>();
+
     //TODO SoftReference
     protected final Set<Invoker<?>> invokers = new ConcurrentHashSet<Invoker<?>>();
 
@@ -56,6 +64,10 @@ public abstract class AbstractProtocol implements Protocol {
         return ProtocolUtils.serviceKey(port, serviceName, serviceVersion, serviceGroup);
     }
 
+    public List<ProtocolServer> getServers() {
+        return Collections.unmodifiableList(new ArrayList<>(serverMap.values()));
+    }
+
     @Override
     public void destroy() {
         for (Invoker<?> invoker : invokers) {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java
index d45f9e3..4b5c016 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java
@@ -19,10 +19,13 @@ package org.apache.dubbo.rpc.protocol;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcException;
@@ -149,4 +152,39 @@ public abstract class AbstractProxyProtocol extends AbstractProtocol {
 
     protected abstract <T> T doRefer(Class<T> type, URL url) throws RpcException;
 
+    protected class ProxyProtocolServer implements ProtocolServer {
+
+        private RemotingServer server;
+        private String address;
+
+        public ProxyProtocolServer(RemotingServer server) {
+            this.server = server;
+        }
+
+        @Override
+        public RemotingServer getRemotingServer() {
+            return server;
+        }
+
+        @Override
+        public String getAddress() {
+            return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress();
+        }
+
+        @Override
+        public void setAddress() {
+            this.address = address;
+        }
+
+        @Override
+        public URL getUrl() {
+            return server.getUrl();
+        }
+
+        @Override
+        public void close() {
+            server.close();
+        }
+    }
+
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java
index a7039a1..5a454a6 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.ListenableFilter;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcException;
 
@@ -135,6 +136,11 @@ public class ProtocolFilterWrapper implements Protocol {
         protocol.destroy();
     }
 
+    @Override
+    public List<ProtocolServer> getServers() {
+        return protocol.getServers();
+    }
+
     /**
      * Register callback for each filter may be better, just like {@link java.util.concurrent.CompletionStage}, each callback
      * registration generates a new CompletionStage whose status is determined by the original CompletionStage.
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java
index e8d2a26..5e8deb8 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java
@@ -23,16 +23,17 @@ import org.apache.dubbo.rpc.ExporterListener;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.InvokerListener;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.listener.ListenerExporterWrapper;
 import org.apache.dubbo.rpc.listener.ListenerInvokerWrapper;
 
 import java.util.Collections;
+import java.util.List;
 
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
-
-import static org.apache.dubbo.rpc.Constants.INVOKER_LISTENER_KEY;
 import static org.apache.dubbo.rpc.Constants.EXPORTER_LISTENER_KEY;
+import static org.apache.dubbo.rpc.Constants.INVOKER_LISTENER_KEY;
 
 /**
  * ListenerProtocol
@@ -79,4 +80,8 @@ public class ProtocolListenerWrapper implements Protocol {
         protocol.destroy();
     }
 
+    @Override
+    public List<ProtocolServer> getServers() {
+        return protocol.getServers();
+    }
 }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 529ac47..a0ae206 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -29,6 +29,7 @@ import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 import org.apache.dubbo.remoting.exchange.ExchangeChannel;
 import org.apache.dubbo.remoting.exchange.ExchangeClient;
@@ -40,6 +41,7 @@ import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
@@ -99,10 +101,6 @@ public class DubboProtocol extends AbstractProtocol {
     /**
      * <host:port,Exchanger>
      */
-    private final Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<>();
-    /**
-     * <host:port,Exchanger>
-     */
     private final Map<String, List<ReferenceCountExchangeClient>> referenceClientMap = new ConcurrentHashMap<>();
     private final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
     private final Set<String> optimizers = new ConcurrentHashSet<>();
@@ -219,10 +217,6 @@ public class DubboProtocol extends AbstractProtocol {
         return INSTANCE;
     }
 
-    public Collection<ExchangeServer> getServers() {
-        return Collections.unmodifiableCollection(serverMap.values());
-    }
-
     public Collection<Exporter<?>> getExporters() {
         return Collections.unmodifiableCollection(exporterMap.values());
     }
@@ -315,7 +309,7 @@ public class DubboProtocol extends AbstractProtocol {
         //client can export a service which's only for server to invoke
         boolean isServer = url.getParameter(IS_SERVER_KEY, true);
         if (isServer) {
-            ExchangeServer server = serverMap.get(key);
+            ProtocolServer server = serverMap.get(key);
             if (server == null) {
                 synchronized (this) {
                     server = serverMap.get(key);
@@ -330,7 +324,7 @@ public class DubboProtocol extends AbstractProtocol {
         }
     }
 
-    private ExchangeServer createServer(URL url) {
+    private ProtocolServer createServer(URL url) {
         url = URLBuilder.from(url)
                 // send readonly event when server closes, it's enabled by default
                 .addParameterIfAbsent(CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString())
@@ -359,7 +353,7 @@ public class DubboProtocol extends AbstractProtocol {
             }
         }
 
-        return server;
+        return new DubboProtocolServer(server);
     }
 
     private void optimizeSerialization(URL url) throws RpcException {
@@ -605,12 +599,14 @@ public class DubboProtocol extends AbstractProtocol {
     @Override
     public void destroy() {
         for (String key : new ArrayList<>(serverMap.keySet())) {
-            ExchangeServer server = serverMap.remove(key);
+            ProtocolServer protocolServer = serverMap.remove(key);
 
-            if (server == null) {
+            if (protocolServer == null) {
                 continue;
             }
 
+            RemotingServer server = protocolServer.getRemotingServer();
+
             try {
                 if (logger.isInfoEnabled()) {
                     logger.info("Close dubbo server: " + server.getLocalAddress());
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java
new file mode 100644
index 0000000..d0933bc
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java
@@ -0,0 +1,62 @@
+/*
+ * 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.rpc.protocol.dubbo;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.remoting.RemotingServer;
+import org.apache.dubbo.rpc.ProtocolServer;
+
+public class DubboProtocolServer implements ProtocolServer {
+
+    private RemotingServer server;
+    private String address;
+
+    public DubboProtocolServer(RemotingServer server) {
+        this.server = server;
+    }
+
+    @Override
+    public RemotingServer getRemotingServer() {
+        return server;
+    }
+
+    @Override
+    public String getAddress() {
+        return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress();
+    }
+
+    @Override
+    public void setAddress() {
+        this.address = address;
+    }
+
+    @Override
+    public URL getUrl() {
+        return server.getUrl();
+    }
+
+    @Override
+    public void reset(URL url) {
+        server.reset(url);
+    }
+
+    @Override
+    public void close() {
+        server.close();
+    }
+}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java
index ccbd646..53c6f6d 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java
@@ -19,10 +19,11 @@ package org.apache.dubbo.rpc.protocol.dubbo.status;
 import org.apache.dubbo.common.extension.Activate;
 import org.apache.dubbo.common.status.Status;
 import org.apache.dubbo.common.status.StatusChecker;
-import org.apache.dubbo.remoting.exchange.ExchangeServer;
+import org.apache.dubbo.remoting.RemotingServer;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
 
-import java.util.Collection;
+import java.util.List;
 
 /**
  * ServerStatusChecker
@@ -32,13 +33,14 @@ public class ServerStatusChecker implements StatusChecker {
 
     @Override
     public Status check() {
-        Collection<ExchangeServer> servers = DubboProtocol.getDubboProtocol().getServers();
+        List<ProtocolServer> servers = DubboProtocol.getDubboProtocol().getServers();
         if (servers == null || servers.isEmpty()) {
             return new Status(Status.Level.UNKNOWN);
         }
         Status.Level level = Status.Level.OK;
         StringBuilder buf = new StringBuilder();
-        for (ExchangeServer server : servers) {
+        for (ProtocolServer protocolServer : servers) {
+            RemotingServer server = protocolServer.getRemotingServer();
             if (!server.isBound()) {
                 level = Status.Level.ERROR;
                 buf.setLength(0);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/PortTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/PortTelnetHandler.java
index 4965548..20a9e5a 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/PortTelnetHandler.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/PortTelnetHandler.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.remoting.exchange.ExchangeChannel;
 import org.apache.dubbo.remoting.exchange.ExchangeServer;
 import org.apache.dubbo.remoting.telnet.TelnetHandler;
 import org.apache.dubbo.remoting.telnet.support.Help;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
 
 import java.util.Collection;
@@ -53,7 +54,7 @@ public class PortTelnetHandler implements TelnetHandler {
             }
         }
         if (port == null || port.length() == 0) {
-            for (ExchangeServer server : DubboProtocol.getDubboProtocol().getServers()) {
+            for (ProtocolServer server : DubboProtocol.getDubboProtocol().getServers()) {
                 if (buf.length() > 0) {
                     buf.append("\r\n");
                 }
@@ -65,14 +66,15 @@ public class PortTelnetHandler implements TelnetHandler {
             }
         } else {
             int p = Integer.parseInt(port);
-            ExchangeServer server = null;
-            for (ExchangeServer s : DubboProtocol.getDubboProtocol().getServers()) {
+            ProtocolServer protocolServer = null;
+            for (ProtocolServer s : DubboProtocol.getDubboProtocol().getServers()) {
                 if (p == s.getUrl().getPort()) {
-                    server = s;
+                    protocolServer = s;
                     break;
                 }
             }
-            if (server != null) {
+            if (protocolServer != null) {
+                ExchangeServer server = (ExchangeServer) protocolServer.getRemotingServer();
                 Collection<ExchangeChannel> channels = server.getExchangeChannels();
                 for (ExchangeChannel c : channels) {
                     if (buf.length() > 0) {
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java
index 8552f4a..128e6c6 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java
@@ -18,14 +18,14 @@ package org.apache.dubbo.rpc.protocol.dubbo.support;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.remoting.exchange.ExchangeServer;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
 
-import java.util.Collection;
+import java.util.List;
 
 /**
  * TODO Comment of ProtocolUtils
@@ -57,8 +57,8 @@ public class ProtocolUtils {
 
     public static void closeAll() {
         DubboProtocol.getDubboProtocol().destroy();
-        Collection<ExchangeServer> servers = DubboProtocol.getDubboProtocol().getServers();
-        for (ExchangeServer server : servers) {
+        List<ProtocolServer> servers = DubboProtocol.getDubboProtocol().getServers();
+        for (ProtocolServer server : servers) {
             server.close();
         }
     }
diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java
index 9e30d0d..648e0f2 100644
--- a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java
@@ -17,9 +17,10 @@
 package org.apache.dubbo.rpc.protocol.hessian;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.http.HttpBinder;
 import org.apache.dubbo.remoting.http.HttpHandler;
-import org.apache.dubbo.remoting.http.HttpServer;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
@@ -48,19 +49,17 @@ import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
 import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
 import static org.apache.dubbo.remoting.Constants.DEFAULT_EXCHANGER;
 import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
-import static org.apache.dubbo.rpc.protocol.hessian.Constants.HESSIAN2_REQUEST_KEY;
 import static org.apache.dubbo.rpc.protocol.hessian.Constants.DEFAULT_HESSIAN2_REQUEST;
-import static org.apache.dubbo.rpc.protocol.hessian.Constants.HESSIAN_OVERLOAD_METHOD_KEY;
 import static org.apache.dubbo.rpc.protocol.hessian.Constants.DEFAULT_HESSIAN_OVERLOAD_METHOD;
 import static org.apache.dubbo.rpc.protocol.hessian.Constants.DEFAULT_HTTP_CLIENT;
+import static org.apache.dubbo.rpc.protocol.hessian.Constants.HESSIAN2_REQUEST_KEY;
+import static org.apache.dubbo.rpc.protocol.hessian.Constants.HESSIAN_OVERLOAD_METHOD_KEY;
 
 /**
  * http rpc support.
  */
 public class HessianProtocol extends AbstractProxyProtocol {
 
-    private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<String, HttpServer>();
-
     private final Map<String, HessianSkeleton> skeletonMap = new ConcurrentHashMap<String, HessianSkeleton>();
 
     private HttpBinder httpBinder;
@@ -81,10 +80,10 @@ public class HessianProtocol extends AbstractProxyProtocol {
     @Override
     protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
         String addr = getAddr(url);
-        HttpServer server = serverMap.get(addr);
-        if (server == null) {
-            server = httpBinder.bind(url, new HessianHandler());
-            serverMap.put(addr, server);
+        ProtocolServer protocolServer = serverMap.get(addr);
+        if (protocolServer == null) {
+            RemotingServer remotingServer = httpBinder.bind(url, new HessianHandler());
+            serverMap.put(addr, new ProxyProtocolServer(remotingServer));
         }
         final String path = url.getAbsolutePath();
         final HessianSkeleton skeleton = new HessianSkeleton(impl, type);
@@ -155,13 +154,13 @@ public class HessianProtocol extends AbstractProxyProtocol {
     public void destroy() {
         super.destroy();
         for (String key : new ArrayList<String>(serverMap.keySet())) {
-            HttpServer server = serverMap.remove(key);
-            if (server != null) {
+            ProtocolServer protocolServer = serverMap.remove(key);
+            if (protocolServer != null) {
                 try {
                     if (logger.isInfoEnabled()) {
-                        logger.info("Close hessian server " + server.getUrl());
+                        logger.info("Close hessian server " + protocolServer.getUrl());
                     }
-                    server.close();
+                    protocolServer.close();
                 } catch (Throwable t) {
                     logger.warn(t.getMessage(), t);
                 }
diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java b/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java
index db84d73..d914eda 100644
--- a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java
@@ -20,9 +20,10 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.http.HttpBinder;
 import org.apache.dubbo.remoting.http.HttpHandler;
-import org.apache.dubbo.remoting.http.HttpServer;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
@@ -60,8 +61,6 @@ public class HttpProtocol extends AbstractProxyProtocol {
 
     public static final int DEFAULT_PORT = 80;
 
-    private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<String, HttpServer>();
-
     private final Map<String, HttpInvokerServiceExporter> skeletonMap = new ConcurrentHashMap<String, HttpInvokerServiceExporter>();
 
     private HttpBinder httpBinder;
@@ -82,10 +81,10 @@ public class HttpProtocol extends AbstractProxyProtocol {
     @Override
     protected <T> Runnable doExport(final T impl, Class<T> type, URL url) throws RpcException {
         String addr = getAddr(url);
-        HttpServer server = serverMap.get(addr);
-        if (server == null) {
-            server = httpBinder.bind(url, new InternalHandler());
-            serverMap.put(addr, server);
+        ProtocolServer protocolServer = serverMap.get(addr);
+        if (protocolServer == null) {
+            RemotingServer remotingServer = httpBinder.bind(url, new InternalHandler());
+            serverMap.put(addr, new ProxyProtocolServer(remotingServer));
         }
         final String path = url.getAbsolutePath();
         skeletonMap.put(path, createExporter(impl, type));
@@ -221,5 +220,4 @@ public class HttpProtocol extends AbstractProxyProtocol {
         }
 
     }
-
 }
diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java b/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java
index 28dc56b..8195f7e 100644
--- a/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java
@@ -17,9 +17,10 @@
 package org.apache.dubbo.rpc.protocol.jsonrpc;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.http.HttpBinder;
 import org.apache.dubbo.remoting.http.HttpHandler;
-import org.apache.dubbo.remoting.http.HttpServer;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
@@ -45,8 +46,6 @@ public class JsonRpcProtocol extends AbstractProxyProtocol {
     public static final String ACCESS_CONTROL_ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods";
     public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
 
-    private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<>();
-
     private final Map<String, JsonRpcServer> skeletonMap = new ConcurrentHashMap<>();
 
     private HttpBinder httpBinder;
@@ -102,10 +101,10 @@ public class JsonRpcProtocol extends AbstractProxyProtocol {
     @Override
     protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
         String addr = url.getIp() + ":" + url.getPort();
-        HttpServer server = serverMap.get(addr);
-        if (server == null) {
-            server = httpBinder.bind(url, new InternalHandler(url.getParameter("cors", false)));
-            serverMap.put(addr, server);
+        ProtocolServer protocolServer = serverMap.get(addr);
+        if (protocolServer == null) {
+            RemotingServer remotingServer = httpBinder.bind(url, new InternalHandler(url.getParameter("cors", false)));
+            serverMap.put(addr, new ProxyProtocolServer(remotingServer));
         }
         final String path = url.getAbsolutePath();
         JsonRpcServer skeleton = new JsonRpcServer(impl, type);
@@ -146,13 +145,13 @@ public class JsonRpcProtocol extends AbstractProxyProtocol {
     public void destroy() {
         super.destroy();
         for (String key : new ArrayList<>(serverMap.keySet())) {
-            HttpServer server = serverMap.remove(key);
-            if (server != null) {
+            ProtocolServer protocolServer = serverMap.remove(key);
+            if (protocolServer != null) {
                 try {
                     if (logger.isInfoEnabled()) {
-                        logger.info("Close jsonrpc server " + server.getUrl());
+                        logger.info("Close jsonrpc server " + protocolServer.getUrl());
                     }
-                    server.close();
+                    protocolServer.close();
                 } catch (Throwable t) {
                     logger.warn(t.getMessage(), t);
                 }
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
similarity index 97%
rename from dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestServer.java
rename to dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
index e3d1acc..f16967d 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestServer.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
@@ -24,7 +24,7 @@ import org.jboss.resteasy.spi.ResteasyDeployment;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
 import static org.apache.dubbo.rpc.protocol.rest.Constants.EXTENSION_KEY;
 
-public abstract class BaseRestServer implements RestServer {
+public abstract class BaseRestProtocolServer implements RestProtocolServer {
 
     @Override
     public void start(URL url) {
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpServer.java
index 733b38f..e07d0a7 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpServer.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpServer.java
@@ -36,7 +36,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.Enumeration;
 
-public class DubboHttpServer extends BaseRestServer {
+public class DubboHttpServer extends BaseRestProtocolServer {
 
     private final HttpServletDispatcher dispatcher = new HttpServletDispatcher();
     private final ResteasyDeployment deployment = new ResteasyDeployment();
@@ -72,7 +72,7 @@ public class DubboHttpServer extends BaseRestServer {
     }
 
     @Override
-    public void stop() {
+    public void close() {
         httpServer.close();
     }
 
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
similarity index 96%
rename from dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyServer.java
rename to dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
index dedf44a..b066c79 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyServer.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
@@ -34,14 +34,14 @@ import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
 import static org.apache.dubbo.remoting.Constants.DEFAULT_IO_THREADS;
 import static org.apache.dubbo.remoting.Constants.DEFAULT_PAYLOAD;
 import static org.apache.dubbo.remoting.Constants.PAYLOAD_KEY;
-import static org.apache.dubbo.rpc.protocol.rest.Constants.KEEP_ALIVE_KEY;
 import static org.apache.dubbo.rpc.protocol.rest.Constants.DEFAULT_KEEP_ALIVE;
+import static org.apache.dubbo.rpc.protocol.rest.Constants.KEEP_ALIVE_KEY;
 
 /**
  * Netty server can't support @Context injection of servlet objects since it's not a servlet container
  *
  */
-public class NettyServer extends BaseRestServer {
+public class NettyRestProtocolServer extends BaseRestProtocolServer {
 
     private final NettyJaxrsServer server = new NettyJaxrsServer();
 
@@ -62,7 +62,7 @@ public class NettyServer extends BaseRestServer {
     }
 
     @Override
-    public void stop() {
+    public void close() {
         server.stop();
     }
 
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
index 40a09da..fe30443 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.http.HttpBinder;
 import org.apache.dubbo.remoting.http.servlet.BootstrapListener;
 import org.apache.dubbo.remoting.http.servlet.ServletManager;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
@@ -47,7 +48,6 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
@@ -71,8 +71,6 @@ public class RestProtocol extends AbstractProxyProtocol {
     private static final int HTTPCLIENTCONNECTIONMANAGER_CLOSEWAITTIME_MS = 1000;
     private static final int HTTPCLIENTCONNECTIONMANAGER_CLOSEIDLETIME_S = 30;
 
-    private final Map<String, RestServer> servers = new ConcurrentHashMap<>();
-
     private final RestServerFactory serverFactory = new RestServerFactory();
 
     // TODO in the future maybe we can just use a single rest client and connection manager
@@ -97,8 +95,8 @@ public class RestProtocol extends AbstractProxyProtocol {
     protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
         String addr = getAddr(url);
         Class implClass = ApplicationModel.getProviderModel(url.getPathKey()).getServiceInstance().getClass();
-        RestServer server = servers.computeIfAbsent(addr, restServer -> {
-            RestServer s = serverFactory.createServer(url.getParameter(SERVER_KEY, DEFAULT_SERVER));
+        RestProtocolServer server = (RestProtocolServer) serverMap.computeIfAbsent(addr, restServer -> {
+            RestProtocolServer s = serverFactory.createServer(url.getParameter(SERVER_KEY, DEFAULT_SERVER));
             s.start(url);
             return s;
         });
@@ -128,7 +126,7 @@ public class RestProtocol extends AbstractProxyProtocol {
 
         server.deploy(resourceDef, impl, contextPath);
 
-        final RestServer s = server;
+        final RestProtocolServer s = server;
         return () -> {
             // TODO due to dubbo's current architecture,
             // it will be called from registry protocol in the shutdown process and won't appear in logs
@@ -213,17 +211,17 @@ public class RestProtocol extends AbstractProxyProtocol {
             connectionMonitor.shutdown();
         }
 
-        for (Map.Entry<String, RestServer> entry : servers.entrySet()) {
+        for (Map.Entry<String, ProtocolServer> entry : serverMap.entrySet()) {
             try {
                 if (logger.isInfoEnabled()) {
                     logger.info("Closing the rest server at " + entry.getKey());
                 }
-                entry.getValue().stop();
+                entry.getValue().close();
             } catch (Throwable t) {
                 logger.warn("Error closing rest server", t);
             }
         }
-        servers.clear();
+        serverMap.clear();
 
         if (logger.isInfoEnabled()) {
             logger.info("Closing rest clients");
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
similarity index 91%
rename from dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServer.java
rename to dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
index 7b2f1e1..fe16f46 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServer.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
@@ -17,8 +17,9 @@
 package org.apache.dubbo.rpc.protocol.rest;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.ProtocolServer;
 
-public interface RestServer {
+public interface RestProtocolServer extends ProtocolServer {
 
     void start(URL url);
 
@@ -29,5 +30,4 @@ public interface RestServer {
 
     void undeploy(Class resourceDef);
 
-    void stop();
 }
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
index 1e5262c..6de7ba1 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
@@ -31,12 +31,12 @@ public class RestServerFactory {
         this.httpBinder = httpBinder;
     }
 
-    public RestServer createServer(String name) {
+    public RestProtocolServer createServer(String name) {
         // TODO move names to Constants
         if ("servlet".equalsIgnoreCase(name) || "jetty".equalsIgnoreCase(name) || "tomcat".equalsIgnoreCase(name)) {
             return new DubboHttpServer(httpBinder);
         } else if ("netty".equalsIgnoreCase(name)) {
-            return new NettyServer();
+            return new NettyRestProtocolServer();
         } else {
             throw new IllegalArgumentException("Unrecognized server name: " + name);
         }
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
index da8bec6..b5c492e 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
@@ -19,9 +19,11 @@ package org.apache.dubbo.rpc.protocol.thrift;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.Transporter;
 import org.apache.dubbo.remoting.exchange.ExchangeChannel;
 import org.apache.dubbo.remoting.exchange.ExchangeClient;
@@ -32,6 +34,7 @@ import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
@@ -41,8 +44,6 @@ import org.apache.dubbo.rpc.protocol.dubbo.DubboExporter;
 import java.util.ArrayList;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
 
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
@@ -59,10 +60,6 @@ public class ThriftProtocol extends AbstractProtocol {
 
     public static final String NAME = "thrift";
 
-    // ip:port -> ExchangeServer
-    private final ConcurrentMap<String, ExchangeServer> serverMap =
-            new ConcurrentHashMap<String, ExchangeServer>();
-
     private ExchangeHandler handler = new ExchangeHandlerAdapter() {
 
         @Override
@@ -146,9 +143,10 @@ public class ThriftProtocol extends AbstractProtocol {
 
         for (String key : new ArrayList<String>(serverMap.keySet())) {
 
-            ExchangeServer server = serverMap.remove(key);
+            ProtocolServer protocolServer = serverMap.remove(key);
 
-            if (server != null) {
+            if (protocolServer != null) {
+                RemotingServer server = protocolServer.getRemotingServer();
                 try {
                     if (logger.isInfoEnabled()) {
                         logger.info("Close dubbo server: " + server.getLocalAddress());
@@ -203,7 +201,7 @@ public class ThriftProtocol extends AbstractProtocol {
 
     }
 
-    private ExchangeServer getServer(URL url) {
+    private ProtocolServer getServer(URL url) {
         // enable sending readonly event when server closes by default
         url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
         String str = url.getParameter(Constants.SERVER_KEY, org.apache.dubbo.rpc.Constants.DEFAULT_REMOTING_SERVER);
@@ -225,7 +223,47 @@ public class ThriftProtocol extends AbstractProtocol {
                 throw new RpcException("Unsupported client type: " + str);
             }
         }
-        return server;
+        return new ThriftProtocolServer(server);
+    }
+
+    private class ThriftProtocolServer implements ProtocolServer {
+
+        private ExchangeServer server;
+        private String address;
+
+        public ThriftProtocolServer(ExchangeServer server) {
+            this.server = server;
+        }
+
+        @Override
+        public RemotingServer getRemotingServer() {
+            return server;
+        }
+
+        @Override
+        public String getAddress() {
+            return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress();
+        }
+
+        @Override
+        public void setAddress() {
+            this.address = address;
+        }
+
+        @Override
+        public URL getUrl() {
+            return server.getUrl();
+        }
+
+        @Override
+        public void reset(URL url) {
+            server.reset(url);
+        }
+
+        @Override
+        public void close() {
+            server.close();
+        }
     }
 
 }
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java b/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
index 08dc57c..8fda4ba 100644
--- a/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
@@ -18,10 +18,11 @@ package org.apache.dubbo.rpc.protocol.webservice;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.http.HttpBinder;
 import org.apache.dubbo.remoting.http.HttpHandler;
-import org.apache.dubbo.remoting.http.HttpServer;
 import org.apache.dubbo.remoting.http.servlet.DispatcherServlet;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
@@ -45,8 +46,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.net.SocketTimeoutException;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
@@ -58,8 +57,6 @@ public class WebServiceProtocol extends AbstractProxyProtocol {
 
     public static final int DEFAULT_PORT = 80;
 
-    private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<String, HttpServer>();
-
     private final ExtensionManagerBus bus = new ExtensionManagerBus();
 
     private final HTTPTransportFactory transportFactory = new HTTPTransportFactory();
@@ -83,10 +80,10 @@ public class WebServiceProtocol extends AbstractProxyProtocol {
     @Override
     protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
         String addr = getAddr(url);
-        HttpServer httpServer = serverMap.get(addr);
-        if (httpServer == null) {
-            httpServer = httpBinder.bind(url, new WebServiceHandler());
-            serverMap.put(addr, httpServer);
+        ProtocolServer protocolServer = serverMap.get(addr);
+        if (protocolServer == null) {
+            RemotingServer remotingServer = httpBinder.bind(url, new WebServiceHandler());
+            serverMap.put(addr, new ProxyProtocolServer(remotingServer));
         }
         final ServerFactoryBean serverFactoryBean = new ServerFactoryBean();
         serverFactoryBean.setAddress(url.getAbsolutePath());
diff --git a/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java b/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
index 83b36cd..0e492fd 100644
--- a/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
@@ -17,9 +17,10 @@
 package org.apache.dubbo.xml.rpc.protocol.xmlrpc;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingServer;
 import org.apache.dubbo.remoting.http.HttpBinder;
 import org.apache.dubbo.remoting.http.HttpHandler;
-import org.apache.dubbo.remoting.http.HttpServer;
+import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
@@ -47,8 +48,6 @@ public class XmlRpcProtocol extends AbstractProxyProtocol {
     public static final String ACCESS_CONTROL_ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods";
     public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
 
-    private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<>();
-
     private final Map<String, XmlRpcServletServer> skeletonMap = new ConcurrentHashMap<>();
 
     private HttpBinder httpBinder;
@@ -105,10 +104,10 @@ public class XmlRpcProtocol extends AbstractProxyProtocol {
     protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
         final URL httpUrl = url.setProtocol("http");
         String addr = httpUrl.getIp() + ":" + httpUrl.getPort();
-        HttpServer server = serverMap.get(addr);
-        if (server == null) {
-            server = httpBinder.bind(httpUrl, new InternalHandler(httpUrl.getParameter("cors", false)));
-            serverMap.put(addr, server);
+        ProtocolServer protocolServer = serverMap.get(addr);
+        if (protocolServer == null) {
+            RemotingServer remotingServer = httpBinder.bind(httpUrl, new InternalHandler(httpUrl.getParameter("cors", false)));
+            serverMap.put(addr, new ProxyProtocolServer(remotingServer));
         }
         final String path = httpUrl.getAbsolutePath();
 
@@ -181,7 +180,7 @@ public class XmlRpcProtocol extends AbstractProxyProtocol {
     public void destroy() {
         super.destroy();
         for (String key : new ArrayList<>(serverMap.keySet())) {
-            HttpServer server = serverMap.remove(key);
+            ProtocolServer server = serverMap.remove(key);
             if (server != null) {
                 try {
                     if (logger.isInfoEnabled()) {