You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/09/12 15:44:22 UTC

[dubbo] branch 3.0 updated: Refactor Destroy Listener for ScopeModel (#8779)

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

albumenj 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 675aead  Refactor Destroy Listener for ScopeModel (#8779)
675aead is described below

commit 675aead1e578cc783f58f7ce480b0872d259e2b4
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Sun Sep 12 23:44:07 2021 +0800

    Refactor Destroy Listener for ScopeModel (#8779)
    
    * Refactor Destroy Listener for ScopeModel
    
    * Fix ut
---
 .../apache/dubbo/rpc/model/ApplicationModel.java   | 15 ++++++++--
 .../org/apache/dubbo/rpc/model/FrameworkModel.java | 10 +++++--
 .../org/apache/dubbo/rpc/model/ModuleModel.java    |  5 ++--
 .../org/apache/dubbo/rpc/model/ScopeModel.java     | 33 +++++++++++++++++++---
 .../registry/CacheableFallbackRegistryTest.java    |  2 ++
 .../client/ServiceDiscoveryRegistryTest.java       |  7 +++++
 .../metadata/MetadataServiceNameMappingTest.java   |  4 +--
 .../client/metadata/MetadataUtilsTest.java         | 15 +++++++---
 .../store/InMemoryMetadataServiceTest.java         |  2 ++
 .../client/migration/model/MigrationRuleTest.java  |  9 +++---
 10 files changed, 81 insertions(+), 21 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
index a08d39b..ad6e309 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
@@ -189,7 +189,7 @@ public class ApplicationModel extends ScopeModel {
     }
 
     @Override
-    public void destroy() {
+    public void onDestroy() {
         // TODO destroy application resources
         for (ModuleModel moduleModel : new ArrayList<>(moduleModels)) {
             moduleModel.destroy();
@@ -202,6 +202,9 @@ public class ApplicationModel extends ScopeModel {
         } else {
             frameworkModel.removeApplication(this);
         }
+
+        notifyDestroy();
+
         if (environment != null) {
             environment.destroy();
             environment = null;
@@ -214,7 +217,6 @@ public class ApplicationModel extends ScopeModel {
             serviceRepository.destroy();
             serviceRepository = null;
         }
-        super.destroy();
     }
 
     public FrameworkModel getFrameworkModel() {
@@ -316,4 +318,13 @@ public class ApplicationModel extends ScopeModel {
             environment.refreshClassLoaders();
         }
     }
+
+    @Override
+    protected boolean checkIfClassLoaderCanRemoved(ClassLoader classLoader) {
+        return !containsClassLoader(classLoader);
+    }
+
+    protected boolean containsClassLoader(ClassLoader classLoader) {
+        return moduleModels.stream().anyMatch(moduleModel -> moduleModel.getClassLoaders().contains(classLoader));
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
index a23386e..53ee49c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
@@ -68,7 +68,7 @@ public class FrameworkModel extends ScopeModel {
     }
 
     @Override
-    public void destroy() {
+    public void onDestroy() {
         //TODO destroy framework model
         for (ApplicationModel applicationModel : new ArrayList<>(applicationModels)) {
             applicationModel.destroy();
@@ -80,7 +80,8 @@ public class FrameworkModel extends ScopeModel {
                 defaultInstance = null;
             }
         }
-        super.destroy();
+
+        notifyDestroy();
     }
 
     public static FrameworkModel defaultModel() {
@@ -124,4 +125,9 @@ public class FrameworkModel extends ScopeModel {
     public FrameworkServiceRepository getServiceRepository() {
         return serviceRepository;
     }
+
+    @Override
+    protected boolean checkIfClassLoaderCanRemoved(ClassLoader classLoader) {
+        return applicationModels.stream().noneMatch(applicationModel -> applicationModel.containsClassLoader(classLoader));
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
index 494a987..81e9114 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
@@ -64,7 +64,7 @@ public class ModuleModel extends ScopeModel {
     }
 
     @Override
-    public void destroy() {
+    public void onDestroy() {
         if (serviceRepository != null) {
             List<ConsumerModel> consumerModels = serviceRepository.getReferredServices();
 
@@ -97,9 +97,8 @@ public class ModuleModel extends ScopeModel {
             serviceRepository = null;
         }
 
-        // TODO destroy module resources
+        notifyDestroy();
         applicationModel.removeModule(this);
-        super.destroy();
     }
 
     public ApplicationModel getApplicationModel() {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
index aec14b7..4b1d9ed 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
@@ -23,11 +23,13 @@ import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.utils.ConcurrentHashSet;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 public abstract class ScopeModel implements ExtensionAccessor {
 
@@ -43,6 +45,7 @@ public abstract class ScopeModel implements ExtensionAccessor {
     private List<ScopeModelDestroyListener> destroyListeners;
 
     private Map<String, Object> attribute;
+    private AtomicBoolean destroyed = new AtomicBoolean(false);
 
     public ScopeModel(ScopeModel parent, ExtensionScope scope) {
         this.parent = parent;
@@ -74,11 +77,27 @@ public abstract class ScopeModel implements ExtensionAccessor {
     }
 
     public void destroy() {
+        if (destroyed.compareAndSet(false, true)) {
+            try {
+                HashSet<ClassLoader> copyOfClassLoaders = new HashSet<>(classLoaders);
+                for (ClassLoader classLoader : copyOfClassLoaders) {
+                    removeClassLoader(classLoader);
+                }
+                onDestroy();
+            }catch (Throwable t) {
+                t.printStackTrace();
+            }
+        }
+    }
+
+    protected void notifyDestroy() {
         for (ScopeModelDestroyListener destroyListener : destroyListeners) {
             destroyListener.onDestroy(this);
         }
     }
 
+    public abstract void onDestroy();
+
     public final void addDestroyListener(ScopeModelDestroyListener listener) {
         destroyListeners.add(listener);
     }
@@ -124,11 +143,17 @@ public abstract class ScopeModel implements ExtensionAccessor {
     }
 
     public void removeClassLoader(ClassLoader classLoader) {
-        this.classLoaders.remove(classLoader);
-        if (parent != null) {
-            parent.removeClassLoader(classLoader);
+        if (checkIfClassLoaderCanRemoved(classLoader)) {
+            this.classLoaders.remove(classLoader);
+            if (parent != null) {
+                parent.removeClassLoader(classLoader);
+            }
+            extensionDirector.removeAllCachedLoader();
         }
-        extensionDirector.removeAllCachedLoader();
+    }
+
+    protected boolean checkIfClassLoaderCanRemoved(ClassLoader classLoader) {
+        return true;
     }
 
     public Set<ClassLoader> getClassLoaders() {
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/CacheableFallbackRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/CacheableFallbackRegistryTest.java
index f508ef6..6263cbe 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/CacheableFallbackRegistryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/CacheableFallbackRegistryTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLStrParser;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
@@ -40,6 +41,7 @@ public class CacheableFallbackRegistryTest {
     static void setProperty() {
         System.setProperty("dubbo.application.url.cache.task.interval", "0");
         System.setProperty("dubbo.application.url.cache.clear.waiting", "0");
+        FrameworkModel.destroyAll();
     }
 
     @BeforeEach
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java
index 6d4e855..87b8a1f 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java
@@ -23,7 +23,9 @@ import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.client.event.listener.MockServiceInstancesChangedListener;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -86,6 +88,11 @@ public class ServiceDiscoveryRegistryTest {
 
     }
 
+    @AfterEach
+    public void teardown() {
+        FrameworkModel.destroyAll();
+    }
+
     @BeforeEach
     public void init() {
         serviceDiscovery = mock(ServiceDiscovery.class);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java
index 870293f..78ec2d9 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java
@@ -60,7 +60,7 @@ public class MetadataServiceNameMappingTest {
         applicationModel = new ApplicationModel(FrameworkModel.defaultModel());
         configManager = mock(ConfigManager.class);
         metadataReport = mock(MetadataReport.class);
-        mapping = new MetadataServiceNameMapping(ApplicationModel.defaultModel());
+        mapping = new MetadataServiceNameMapping(applicationModel);
         mapping.setApplicationModel(applicationModel);
         url = URL.valueOf("dubbo://127.0.0.1:20880/TestService?version=1.0.0");
     }
@@ -72,7 +72,7 @@ public class MetadataServiceNameMappingTest {
 
     @Test
     public void testMap() {
-        ApplicationModel mockedApplicationModel = spy(ApplicationModel.defaultModel());
+        ApplicationModel mockedApplicationModel = spy(applicationModel);
 
         when(configManager.getMetadataConfigs()).thenReturn(Collections.emptyList());
         Mockito.when(mockedApplicationModel.getApplicationConfigManager()).thenReturn(configManager);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataUtilsTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataUtilsTest.java
index 17cbccd..d2e6b7f 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataUtilsTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataUtilsTest.java
@@ -27,8 +27,10 @@ import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.MockedStatic;
 import org.mockito.Mockito;
@@ -38,14 +40,19 @@ import java.util.HashMap;
 import java.util.Map;
 
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME;
-import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.any;
 
 public class MetadataUtilsTest {
 
+    @BeforeEach
+    public void setup() {
+        ApplicationModel.defaultModel().destroy();
+    }
+
     @AfterEach
     public void tearDown() throws IOException {
         Mockito.framework().clearInlineMocks();
@@ -121,7 +128,7 @@ public class MetadataUtilsTest {
         }
 
         MetadataUtils.destroyMetadataServiceProxy(serviceInstance);
-        applicationModel.destroy();
+        ApplicationModel.defaultModel().destroy();
     }
 
 
@@ -177,7 +184,7 @@ public class MetadataUtilsTest {
 
         Assertions.assertEquals(0, MetadataUtils.getMetadataServiceProxies().size());
         Assertions.assertEquals(0, MetadataUtils.getMetadataServiceInvokers().size());
-        applicationModel.destroy();
+        ApplicationModel.defaultModel().destroy();
     }
 
 
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java
index 8e99418..bd5dc81 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java
@@ -24,6 +24,7 @@ import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 import org.apache.dubbo.registry.MockLogger;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
@@ -53,6 +54,7 @@ public class InMemoryMetadataServiceTest {
 
     @BeforeAll
     public static void setUp() {
+        FrameworkModel.destroyAll();
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("demo-provider2");
         ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java
index 30ce073..e2ac70b 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java
@@ -75,10 +75,10 @@ public class MigrationRuleTest {
         assertEquals(false, migrationRule.getForce());
 
         URL url = Mockito.mock(URL.class);
-        ApplicationModel defaultModule = Mockito.spy(ApplicationModel.defaultModel());
-        Mockito.when(defaultModule.getDefaultExtension(ServiceNameMapping.class)).thenReturn(mapping);
+        ApplicationModel defaultModel = Mockito.spy(ApplicationModel.defaultModel());
+        Mockito.when(defaultModel.getDefaultExtension(ServiceNameMapping.class)).thenReturn(mapping);
 
-        Mockito.when(url.getScopeModel()).thenReturn(defaultModule);
+        Mockito.when(url.getScopeModel()).thenReturn(defaultModel);
         Mockito.when(url.getDisplayServiceKey()).thenReturn("DemoService:1.0.0");
         Mockito.when(url.getParameter(ArgumentMatchers.eq(REGISTRY_CLUSTER_TYPE_KEY), anyString())).thenReturn("default");
         Mockito.when(url.getParameter(ArgumentMatchers.eq(REGISTRY_CLUSTER_TYPE_KEY), anyString())).thenReturn("default");
@@ -100,7 +100,7 @@ public class MigrationRuleTest {
 
         Mockito.when(url.getDisplayServiceKey()).thenReturn("GreetingService:1.0.1");
         Mockito.when(url.getServiceInterface()).thenReturn("GreetingService");
-        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(defaultModule);
+        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(defaultModel);
         metadataService.putCachedMapping(ServiceNameMapping.buildMappingKey(url), Collections.singleton("TestApplication"));
 
         Set<String> services = new HashSet<>();
@@ -112,5 +112,6 @@ public class MigrationRuleTest {
         assertEquals(false, migrationRule.getForce(url));
         assertEquals(MigrationStep.FORCE_INTERFACE, migrationRule.getStep(url));
         metadataService.removeCachedMapping("GreetingService");
+        ApplicationModel.defaultModel().destroy();
     }
 }