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 2020/12/03 15:36:53 UTC

[dubbo] branch 3.0 updated: Online&offline support app address (#6982)

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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 9351a41  Online&offline support app address (#6982)
9351a41 is described below

commit 9351a415e22ef9ec580f06987616cb101b96f350
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Dec 3 23:36:40 2020 +0800

    Online&offline support app address (#6982)
---
 .../apache/dubbo/rpc/cluster/ClusterInvoker.java   | 10 +++-
 .../org/apache/dubbo/rpc/cluster/Directory.java    |  8 ++-
 .../org/apache/dubbo/common/utils/UrlUtils.java    |  4 ++
 dubbo-dependencies-bom/pom.xml                     |  1 -
 .../impl/{Offline.java => BaseOffline.java}        | 32 ++++++-----
 .../command/impl/{Online.java => BaseOnline.java}  | 30 +++++------
 .../org/apache/dubbo/qos/command/impl/Offline.java | 56 +++----------------
 .../apache/dubbo/qos/command/impl/OfflineApp.java  | 41 ++++++--------
 .../dubbo/qos/command/impl/OfflineInterface.java   | 42 ++++++---------
 .../org/apache/dubbo/qos/command/impl/Online.java  | 62 ++++------------------
 .../apache/dubbo/qos/command/impl/OnlineApp.java   | 32 +++++------
 .../dubbo/qos/command/impl/OnlineInterface.java    | 37 +++++--------
 .../org.apache.dubbo.qos.command.BaseCommand       |  4 ++
 .../dubbo/registry/ListenerRegistryWrapper.java    | 13 ++---
 .../dubbo/registry/RegistryServiceListener.java    |  8 +--
 .../registry/client/ServiceDiscoveryRegistry.java  |  6 ++-
 .../client/ServiceDiscoveryRegistryDirectory.java  |  5 ++
 .../registry/integration/RegistryDirectory.java    |  5 ++
 .../dubbo/registry/RegistryFactoryWrapperTest.java | 17 +++---
 .../dubbo/registry/RegistryServiceListener1.java   | 16 +++---
 .../dubbo/registry/RegistryServiceListener2.java   | 16 +++---
 21 files changed, 179 insertions(+), 266 deletions(-)

diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterInvoker.java
index 94237e2..32187e6 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterInvoker.java
@@ -39,11 +39,19 @@ public interface ClusterInvoker<T> extends Invoker<T> {
 
     boolean isDestroyed();
 
+    default boolean isServiceDiscovery() {
+        Directory<T> directory = getDirectory();
+        if (directory == null) {
+            return false;
+        }
+        return directory.isServiceDiscovery();
+    }
+
     default boolean hasProxyInvokers() {
         Directory<T> directory = getDirectory();
         if (directory == null) {
             return false;
         }
-        return directory.hasInvokers();
+        return !directory.isEmpty();
     }
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
index 958cbde..9fd3ca2 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
@@ -54,8 +54,12 @@ public interface Directory<T> extends Node {
 
     boolean isDestroyed();
 
-    default boolean hasInvokers() {
-        return CollectionUtils.isNotEmpty(getAllInvokers());
+    default boolean isEmpty() {
+        return CollectionUtils.isEmpty(getAllInvokers());
+    }
+
+    default boolean isServiceDiscovery() {
+        return false;
     }
 
     void discordAddresses();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
index 17ce7ad..eb645f3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
@@ -654,4 +654,8 @@ public class UrlUtils {
         return new URL(protocol, username, password, host, port, path, parameters);
     }
 
+    public static boolean isConsumer(URL url) {
+        return url.getProtocol().equalsIgnoreCase("consumer") || url.getPort() == 0;
+    }
+
 }
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 9c40c96..634586d 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -757,5 +757,4 @@
             </build>
         </profile>
     </profiles>
-
 </project>
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java
similarity index 69%
copy from dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
copy to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java
index 4fd15e1..4323c04 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java
@@ -21,8 +21,6 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.qos.command.BaseCommand;
 import org.apache.dubbo.qos.command.CommandContext;
-import org.apache.dubbo.qos.command.annotation.Cmd;
-import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
@@ -31,14 +29,10 @@ import org.apache.dubbo.rpc.model.ServiceRepository;
 import java.util.Collection;
 import java.util.List;
 
-@Cmd(name = "offline", summary = "offline dubbo", example = {
-        "offline dubbo",
-        "offline xx.xx.xxx.service"
-})
-public class Offline implements BaseCommand {
-    private Logger logger = LoggerFactory.getLogger(Offline.class);
-    private static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    private static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+public class BaseOffline implements BaseCommand {
+    private Logger logger = LoggerFactory.getLogger(OfflineInterface.class);
+    public static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
+    public static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
 
     @Override
     public String execute(CommandContext commandContext, String[] args) {
@@ -48,7 +42,7 @@ public class Offline implements BaseCommand {
             servicePattern = args[0];
         }
 
-        boolean hasService = offline(servicePattern);
+        boolean hasService = doExecute(servicePattern);
 
         if (hasService) {
             return "OK";
@@ -57,19 +51,21 @@ public class Offline implements BaseCommand {
         }
     }
 
-    public static boolean offline(String servicePattern) {
+    protected boolean doExecute(String servicePattern) {
+        return this.offline(servicePattern);
+    }
+
+    public boolean offline(String servicePattern) {
         boolean hasService = false;
 
         Collection<ProviderModel> providerModelList = serviceRepository.getExportedServices();
         for (ProviderModel providerModel : providerModelList) {
-            if (providerModel.getServiceMetadata().getDisplayServiceKey().matches(servicePattern)) {
+            if (providerModel.getServiceMetadata().getServiceKey().matches(servicePattern)) {
                 hasService = true;
                 List<ProviderModel.RegisterStatedURL> statedUrls = providerModel.getStatedUrl();
                 for (ProviderModel.RegisterStatedURL statedURL : statedUrls) {
                     if (statedURL.isRegistered()) {
-                        Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
-                        registry.unregister(statedURL.getProviderUrl());
-                        statedURL.setRegistered(false);
+                        doUnexport(statedURL);
                     }
                 }
             }
@@ -77,4 +73,6 @@ public class Offline implements BaseCommand {
 
         return hasService;
     }
-}
+
+    protected void doUnexport(ProviderModel.RegisterStatedURL statedURL) {}
+}
\ No newline at end of file
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java
similarity index 72%
copy from dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
copy to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java
index c04f184..bd1f276 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java
@@ -22,8 +22,6 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ArrayUtils;
 import org.apache.dubbo.qos.command.BaseCommand;
 import org.apache.dubbo.qos.command.CommandContext;
-import org.apache.dubbo.qos.command.annotation.Cmd;
-import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
@@ -32,14 +30,10 @@ import org.apache.dubbo.rpc.model.ServiceRepository;
 import java.util.Collection;
 import java.util.List;
 
-@Cmd(name = "online", summary = "online dubbo", example = {
-        "online dubbo",
-        "online xx.xx.xxx.service"
-})
-public class Online implements BaseCommand {
+public class BaseOnline implements BaseCommand {
     private static final Logger logger = LoggerFactory.getLogger(Online.class);
-    private static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    private static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+    public static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
+    public static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
 
     @Override
     public String execute(CommandContext commandContext, String[] args) {
@@ -49,7 +43,7 @@ public class Online implements BaseCommand {
             servicePattern = "" + args[0];
         }
 
-        boolean hasService = online(servicePattern);
+        boolean hasService = doExecute(servicePattern);
         if (hasService) {
             return "OK";
         } else {
@@ -57,19 +51,17 @@ public class Online implements BaseCommand {
         }
     }
 
-    public static boolean online(String servicePattern) {
+    public boolean online(String servicePattern) {
         boolean hasService = false;
 
         Collection<ProviderModel> providerModelList = serviceRepository.getExportedServices();
         for (ProviderModel providerModel : providerModelList) {
-            if (providerModel.getServiceMetadata().getDisplayServiceKey().matches(servicePattern)) {
+            if (providerModel.getServiceMetadata().getServiceKey().matches(servicePattern)) {
                 hasService = true;
                 List<ProviderModel.RegisterStatedURL> statedUrls = providerModel.getStatedUrl();
                 for (ProviderModel.RegisterStatedURL statedURL : statedUrls) {
                     if (!statedURL.isRegistered()) {
-                        Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
-                        registry.register(statedURL.getProviderUrl());
-                        statedURL.setRegistered(true);
+                        doExport(statedURL);
                     }
                 }
             }
@@ -77,4 +69,12 @@ public class Online implements BaseCommand {
 
         return hasService;
     }
+
+    protected boolean doExecute(String servicePattern) {
+        return this.online(servicePattern);
+    }
+
+    protected void doExport(ProviderModel.RegisterStatedURL statedURL) {
+
+    }
 }
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
index 4fd15e1..6b95a17 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
@@ -16,65 +16,25 @@
  */
 package org.apache.dubbo.qos.command.impl;
 
-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.qos.command.BaseCommand;
-import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
-import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.RegistryFactory;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ProviderModel;
-import org.apache.dubbo.rpc.model.ServiceRepository;
-
-import java.util.Collection;
-import java.util.List;
 
 @Cmd(name = "offline", summary = "offline dubbo", example = {
         "offline dubbo",
         "offline xx.xx.xxx.service"
 })
-public class Offline implements BaseCommand {
+public class Offline extends BaseOffline {
     private Logger logger = LoggerFactory.getLogger(Offline.class);
-    private static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    private static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
-
-    @Override
-    public String execute(CommandContext commandContext, String[] args) {
-        logger.info("receive offline command");
-        String servicePattern = ".*";
-        if (args != null && args.length > 0) {
-            servicePattern = args[0];
-        }
 
-        boolean hasService = offline(servicePattern);
+    private static OfflineInterface offlineInterface = new OfflineInterface();
+    private static OfflineApp offlineApp = new OfflineApp();
 
-        if (hasService) {
-            return "OK";
-        } else {
-            return "service not found";
-        }
+    @Override
+    protected boolean doExecute(String servicePattern) {
+        boolean r1 = offlineInterface.offline(servicePattern);
+        boolean r2 = offlineApp.offline(servicePattern);
+        return r1 && r2;
     }
 
-    public static boolean offline(String servicePattern) {
-        boolean hasService = false;
-
-        Collection<ProviderModel> providerModelList = serviceRepository.getExportedServices();
-        for (ProviderModel providerModel : providerModelList) {
-            if (providerModel.getServiceMetadata().getDisplayServiceKey().matches(servicePattern)) {
-                hasService = true;
-                List<ProviderModel.RegisterStatedURL> statedUrls = providerModel.getStatedUrl();
-                for (ProviderModel.RegisterStatedURL statedURL : statedUrls) {
-                    if (statedURL.isRegistered()) {
-                        Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
-                        registry.unregister(statedURL.getProviderUrl());
-                        statedURL.setRegistered(false);
-                    }
-                }
-            }
-        }
-
-        return hasService;
-    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OfflineApp.java
similarity index 51%
copy from dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
copy to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OfflineApp.java
index c0f6927..5920e03 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OfflineApp.java
@@ -14,33 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.dubbo.qos.command.impl;
 
-package org.apache.dubbo.registry;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Activate;
-
-@Activate(order = 2)
-public class RegistryServiceListener2 implements RegistryServiceListener {
-    static RegistryServiceListener delegate;
-
-    @Override
-    public void onRegister(URL url) {
-        delegate.onRegister(url);
-    }
-
-    @Override
-    public void onUnregister(URL url) {
-        delegate.onUnregister(url);
-    }
-
-    @Override
-    public void onSubscribe(URL url) {
-        delegate.onSubscribe(url);
-    }
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.qos.command.annotation.Cmd;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.model.ProviderModel;
 
+@Cmd(name = "offlineApp", summary = "offline app addresses", example = {
+        "offlineApp",
+        "offlineApp xx.xx.xxx.service"
+})
+public class OfflineApp extends BaseOffline {
     @Override
-    public void onUnsubscribe(URL url) {
-        delegate.onUnsubscribe(url);
+    protected void doUnexport(ProviderModel.RegisterStatedURL statedURL) {
+        if (UrlUtils.isServiceDiscoveryRegistryType(statedURL.getRegistryUrl())) {
+            Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
+            registry.unregister(statedURL.getProviderUrl());
+            statedURL.setRegistered(false);
+        }
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OfflineInterface.java
similarity index 50%
copy from dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
copy to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OfflineInterface.java
index c0f6927..d4f959d 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OfflineInterface.java
@@ -14,33 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.dubbo.qos.command.impl;
 
-package org.apache.dubbo.registry;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.qos.command.annotation.Cmd;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.model.ProviderModel;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Activate;
-
-@Activate(order = 2)
-public class RegistryServiceListener2 implements RegistryServiceListener {
-    static RegistryServiceListener delegate;
-
-    @Override
-    public void onRegister(URL url) {
-        delegate.onRegister(url);
-    }
-
-    @Override
-    public void onUnregister(URL url) {
-        delegate.onUnregister(url);
-    }
-
-    @Override
-    public void onSubscribe(URL url) {
-        delegate.onSubscribe(url);
-    }
-
-    @Override
-    public void onUnsubscribe(URL url) {
-        delegate.onUnsubscribe(url);
+@Cmd(name = "offlineInterface", summary = "offline dubbo", example = {
+        "offlineInterface dubbo",
+        "offlineInterface xx.xx.xxx.service"
+})
+public class OfflineInterface extends BaseOffline {
+    protected void doUnexport(ProviderModel.RegisterStatedURL statedURL) {
+        if (!UrlUtils.isServiceDiscoveryRegistryType(statedURL.getRegistryUrl())) {
+            Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
+            registry.unregister(statedURL.getProviderUrl());
+            statedURL.setRegistered(false);
+        }
     }
 }
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
index c04f184..e5f39d8 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
@@ -16,65 +16,23 @@
  */
 package org.apache.dubbo.qos.command.impl;
 
-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.ArrayUtils;
-import org.apache.dubbo.qos.command.BaseCommand;
-import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
-import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.RegistryFactory;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ProviderModel;
-import org.apache.dubbo.rpc.model.ServiceRepository;
 
-import java.util.Collection;
-import java.util.List;
-
-@Cmd(name = "online", summary = "online dubbo", example = {
-        "online dubbo",
-        "online xx.xx.xxx.service"
+@Cmd(name = "onlineAPp", summary = "offline app addresses", example = {
+        "offlineApp dubbo",
+        "offlineApp xx.xx.xxx.service"
 })
-public class Online implements BaseCommand {
+public class Online extends BaseOnline {
     private static final Logger logger = LoggerFactory.getLogger(Online.class);
-    private static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    private static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+    private static final OnlineInterface onlineInteface = new OnlineInterface();
+    private static final OnlineApp onlineApp = new OnlineApp();
 
     @Override
-    public String execute(CommandContext commandContext, String[] args) {
-        logger.info("receive online command");
-        String servicePattern = ".*";
-        if (ArrayUtils.isNotEmpty(args)) {
-            servicePattern = "" + args[0];
-        }
-
-        boolean hasService = online(servicePattern);
-        if (hasService) {
-            return "OK";
-        } else {
-            return "service not found";
-        }
-    }
-
-    public static boolean online(String servicePattern) {
-        boolean hasService = false;
-
-        Collection<ProviderModel> providerModelList = serviceRepository.getExportedServices();
-        for (ProviderModel providerModel : providerModelList) {
-            if (providerModel.getServiceMetadata().getDisplayServiceKey().matches(servicePattern)) {
-                hasService = true;
-                List<ProviderModel.RegisterStatedURL> statedUrls = providerModel.getStatedUrl();
-                for (ProviderModel.RegisterStatedURL statedURL : statedUrls) {
-                    if (!statedURL.isRegistered()) {
-                        Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
-                        registry.register(statedURL.getProviderUrl());
-                        statedURL.setRegistered(true);
-                    }
-                }
-            }
-        }
-
-        return hasService;
+    protected boolean doExecute(String servicePattern) {
+        boolean r1 = onlineInteface.online(servicePattern);
+        boolean r2 = onlineApp.online(servicePattern);
+        return r1 && r2;
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OnlineApp.java
similarity index 57%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
copy to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OnlineApp.java
index 3f88f6e..799b72e 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OnlineApp.java
@@ -14,28 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.dubbo.qos.command.impl;
 
-package org.apache.dubbo.registry;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-
-@SPI
-public interface RegistryServiceListener {
-    default void onRegister(URL url) {
-
-    }
-
-
-    default void onUnregister(URL url) {
-
-    }
-
-    default void onSubscribe(URL url) {
-
-    }
-
-    default void onUnsubscribe(URL url) {
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.model.ProviderModel;
 
+public class OnlineApp extends BaseOnline {
+    @Override
+    protected void doExport(ProviderModel.RegisterStatedURL statedURL) {
+        if (!UrlUtils.isServiceDiscoveryRegistryType(statedURL.getRegistryUrl())) {
+            Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
+            registry.register(statedURL.getProviderUrl());
+            statedURL.setRegistered(true);
+        }
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OnlineInterface.java
similarity index 57%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
copy to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OnlineInterface.java
index 3f88f6e..91e8eb6 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/OnlineInterface.java
@@ -14,28 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.dubbo.registry;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-
-@SPI
-public interface RegistryServiceListener {
-    default void onRegister(URL url) {
-
-    }
-
-
-    default void onUnregister(URL url) {
-
-    }
-
-    default void onSubscribe(URL url) {
-
-    }
-
-    default void onUnsubscribe(URL url) {
-
+package org.apache.dubbo.qos.command.impl;
+
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.model.ProviderModel;
+
+public class OnlineInterface extends BaseOnline {
+    @Override
+    protected void doExport(ProviderModel.RegisterStatedURL statedURL) {
+        if (!UrlUtils.isServiceDiscoveryRegistryType(statedURL.getRegistryUrl())) {
+            Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl());
+            registry.register(statedURL.getProviderUrl());
+            statedURL.setRegistered(true);
+        }
     }
 }
diff --git a/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.command.BaseCommand b/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.command.BaseCommand
index b92b6b2..b4f0322 100644
--- a/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.command.BaseCommand
+++ b/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.command.BaseCommand
@@ -1,8 +1,12 @@
 online=org.apache.dubbo.qos.command.impl.Online
+onlineApp=org.apache.dubbo.qos.command.impl.OnlineApp
+onlineInterface=org.apache.dubbo.qos.command.impl.OnlineInterface
 help=org.apache.dubbo.qos.command.impl.Help
 quit=org.apache.dubbo.qos.command.impl.Quit
 ls=org.apache.dubbo.qos.command.impl.Ls
 offline=org.apache.dubbo.qos.command.impl.Offline
+offlineApp=org.apache.dubbo.qos.command.impl.OfflineApp
+offlineInterface=org.apache.dubbo.qos.command.impl.OfflineInterface
 ready=org.apache.dubbo.qos.command.impl.Ready
 version=org.apache.dubbo.qos.command.impl.Version
 publish-metadata=org.apache.dubbo.qos.command.impl.PublishMetadata
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/ListenerRegistryWrapper.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/ListenerRegistryWrapper.java
index a15a5fe..63d0dfc 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/ListenerRegistryWrapper.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/ListenerRegistryWrapper.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
 
 import java.util.List;
 
@@ -56,12 +57,12 @@ public class ListenerRegistryWrapper implements Registry {
         try {
             registry.register(url);
         } finally {
-            if (CollectionUtils.isNotEmpty(listeners)) {
+            if (CollectionUtils.isNotEmpty(listeners) && !UrlUtils.isConsumer(url)) {
                 RuntimeException exception = null;
                 for (RegistryServiceListener listener : listeners) {
                     if (listener != null) {
                         try {
-                            listener.onRegister(url);
+                            listener.onRegister(url, registry);
                         } catch (RuntimeException t) {
                             logger.error(t.getMessage(), t);
                             exception = t;
@@ -80,12 +81,12 @@ public class ListenerRegistryWrapper implements Registry {
         try {
             registry.unregister(url);
         } finally {
-            if (CollectionUtils.isNotEmpty(listeners)) {
+            if (CollectionUtils.isNotEmpty(listeners) && !UrlUtils.isConsumer(url)) {
                 RuntimeException exception = null;
                 for (RegistryServiceListener listener : listeners) {
                     if (listener != null) {
                         try {
-                            listener.onUnregister(url);
+                            listener.onUnregister(url, registry);
                         } catch (RuntimeException t) {
                             logger.error(t.getMessage(), t);
                             exception = t;
@@ -109,7 +110,7 @@ public class ListenerRegistryWrapper implements Registry {
                 for (RegistryServiceListener registryListener : listeners) {
                     if (registryListener != null) {
                         try {
-                            registryListener.onSubscribe(url);
+                            registryListener.onSubscribe(url, registry);
                         } catch (RuntimeException t) {
                             logger.error(t.getMessage(), t);
                             exception = t;
@@ -133,7 +134,7 @@ public class ListenerRegistryWrapper implements Registry {
                 for (RegistryServiceListener registryListener : listeners) {
                     if (registryListener != null) {
                         try {
-                            registryListener.onUnsubscribe(url);
+                            registryListener.onUnsubscribe(url, registry);
                         } catch (RuntimeException t) {
                             logger.error(t.getMessage(), t);
                             exception = t;
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
index 3f88f6e..283d7ee 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryServiceListener.java
@@ -22,20 +22,20 @@ import org.apache.dubbo.common.extension.SPI;
 
 @SPI
 public interface RegistryServiceListener {
-    default void onRegister(URL url) {
+    default void onRegister(URL url, Registry registry) {
 
     }
 
 
-    default void onUnregister(URL url) {
+    default void onUnregister(URL url, Registry registry) {
 
     }
 
-    default void onSubscribe(URL url) {
+    default void onSubscribe(URL url, Registry registry) {
 
     }
 
-    default void onUnsubscribe(URL url) {
+    default void onUnsubscribe(URL url, Registry registry) {
 
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
index d7caa18..4cd058d 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
@@ -288,8 +288,10 @@ public class ServiceDiscoveryRegistry implements Registry {
         writableMetadataService.unsubscribeURL(url);
         String protocolServiceKey = url.getServiceKey() + GROUP_CHAR_SEPARATOR + url.getParameter(PROTOCOL_KEY, DUBBO);
         String serviceNamesKey = serviceToAppsMapping.remove(protocolServiceKey);
-        ServiceInstancesChangedListener instancesChangedListener = serviceListeners.get(serviceNamesKey);
-        instancesChangedListener.removeListener(protocolServiceKey);
+        if (serviceNamesKey != null) {
+            ServiceInstancesChangedListener instancesChangedListener = serviceListeners.get(serviceNamesKey);
+            instancesChangedListener.removeListener(protocolServiceKey);
+        }
     }
 
     @Override
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java
index 8dfb934..c41e028 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java
@@ -96,6 +96,11 @@ public class ServiceDiscoveryRegistryDirectory<T> extends DynamicDirectory<T> im
         refreshInvoker(instanceUrls);
     }
 
+    @Override
+    public boolean isServiceDiscovery() {
+        return true;
+    }
+
     private void refreshInvoker(List<URL> invokerUrls) {
         Assert.notNull(invokerUrls, "invokerUrls should not be null, use empty url list to clear address.");
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 1b95b53..16303cb 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -145,6 +145,11 @@ public class RegistryDirectory<T> extends DynamicDirectory<T> implements NotifyL
         refreshOverrideAndInvoker(providerURLs);
     }
 
+    @Override
+    public boolean isServiceDiscovery() {
+        return false;
+    }
+
     private String judgeCategory(URL url) {
         if (UrlUtils.isConfigurator(url)) {
             return CONFIGURATORS_CATEGORY;
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryFactoryWrapperTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryFactoryWrapperTest.java
index 01d310d..d791391 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryFactoryWrapperTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryFactoryWrapperTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.registry;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
+
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
@@ -36,20 +37,20 @@ public class RegistryFactoryWrapperTest {
         URL url = URL.valueOf("dubbo://localhost:8081/simple.service");
         registry.register(url);
 
-        Mockito.verify(listener1, Mockito.times(1)).onRegister(url);
-        Mockito.verify(listener2, Mockito.times(1)).onRegister(url);
+        Mockito.verify(listener1, Mockito.times(1)).onRegister(url, null);
+        Mockito.verify(listener2, Mockito.times(1)).onRegister(url, null);
 
         registry.unregister(url);
-        Mockito.verify(listener1, Mockito.times(1)).onUnregister(url);
-        Mockito.verify(listener2, Mockito.times(1)).onUnregister(url);
+        Mockito.verify(listener1, Mockito.times(1)).onUnregister(url, null);
+        Mockito.verify(listener2, Mockito.times(1)).onUnregister(url, null);
 
         registry.subscribe(url, Mockito.mock(NotifyListener.class));
-        Mockito.verify(listener1, Mockito.times(1)).onSubscribe(url);
-        Mockito.verify(listener2, Mockito.times(1)).onSubscribe(url);
+        Mockito.verify(listener1, Mockito.times(1)).onSubscribe(url, null);
+        Mockito.verify(listener2, Mockito.times(1)).onSubscribe(url, null);
 
         registry.unsubscribe(url, Mockito.mock(NotifyListener.class));
-        Mockito.verify(listener1, Mockito.times(1)).onUnsubscribe(url);
-        Mockito.verify(listener2, Mockito.times(1)).onUnsubscribe(url);
+        Mockito.verify(listener1, Mockito.times(1)).onUnsubscribe(url, null);
+        Mockito.verify(listener2, Mockito.times(1)).onUnsubscribe(url, null);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener1.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener1.java
index 0584a78..3132ade 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener1.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener1.java
@@ -25,22 +25,22 @@ public class RegistryServiceListener1 implements RegistryServiceListener {
     static RegistryServiceListener delegate;
 
     @Override
-    public void onRegister(URL url) {
-        delegate.onRegister(url);
+    public void onRegister(URL url, Registry registry) {
+        delegate.onRegister(url, registry);
     }
 
     @Override
-    public void onUnregister(URL url) {
-        delegate.onUnregister(url);
+    public void onUnregister(URL url, Registry registry) {
+        delegate.onUnregister(url, registry);
     }
 
     @Override
-    public void onSubscribe(URL url) {
-        delegate.onSubscribe(url);
+    public void onSubscribe(URL url, Registry registry) {
+        delegate.onSubscribe(url, registry);
     }
 
     @Override
-    public void onUnsubscribe(URL url) {
-        delegate.onUnsubscribe(url);
+    public void onUnsubscribe(URL url, Registry registry) {
+        delegate.onUnsubscribe(url, registry);
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
index c0f6927..8f1f318 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/RegistryServiceListener2.java
@@ -25,22 +25,22 @@ public class RegistryServiceListener2 implements RegistryServiceListener {
     static RegistryServiceListener delegate;
 
     @Override
-    public void onRegister(URL url) {
-        delegate.onRegister(url);
+    public void onRegister(URL url, Registry registry) {
+        delegate.onRegister(url, registry);
     }
 
     @Override
-    public void onUnregister(URL url) {
-        delegate.onUnregister(url);
+    public void onUnregister(URL url, Registry registry) {
+        delegate.onUnregister(url, registry);
     }
 
     @Override
-    public void onSubscribe(URL url) {
-        delegate.onSubscribe(url);
+    public void onSubscribe(URL url, Registry registry) {
+        delegate.onSubscribe(url, registry);
     }
 
     @Override
-    public void onUnsubscribe(URL url) {
-        delegate.onUnsubscribe(url);
+    public void onUnsubscribe(URL url, Registry registry) {
+        delegate.onUnsubscribe(url, registry);
     }
 }