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

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


The following commit(s) were added to refs/heads/3.1 by this push:
     new 213363422e Add mapping retry (#11265)
213363422e is described below

commit 213363422e0981b1f227af61a01876b8adcadfda
Author: Albumen Kevin <[email protected]>
AuthorDate: Wed Jan 11 10:47:37 2023 +0800

    Add mapping retry (#11265)
---
 .../org/apache/dubbo/config/ApplicationConfig.java | 29 +++++--
 .../org/apache/dubbo/config/ServiceConfig.java     | 64 ++++++++++-----
 .../org/apache/dubbo/config/ServiceConfigTest.java | 94 ++++++++++++++++++++--
 .../src/main/resources/META-INF/dubbo.xsd          |  5 ++
 4 files changed, 158 insertions(+), 34 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java 
b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index 33852d430a..3eb3b50b14 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@ -16,6 +16,14 @@
  */
 package org.apache.dubbo.config;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.dubbo.common.compiler.support.AdaptiveCompiler;
 import org.apache.dubbo.common.infra.InfraAdapter;
 import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
@@ -25,14 +33,6 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import static 
org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY;
@@ -198,6 +198,11 @@ public class ApplicationConfig extends AbstractConfig {
      */
     private Integer metadataServicePort;
 
+    /**
+     * The retry interval of service name mapping
+     */
+    private Integer mappingRetryInterval;
+
     /**
      * used to set extensions of probe in qos
      */
@@ -564,6 +569,14 @@ public class ApplicationConfig extends AbstractConfig {
         this.metadataServicePort = metadataServicePort;
     }
 
+    public Integer getMappingRetryInterval() {
+        return mappingRetryInterval;
+    }
+
+    public void setMappingRetryInterval(Integer mappingRetryInterval) {
+        this.mappingRetryInterval = mappingRetryInterval;
+    }
+
     @Parameter(key = METADATA_SERVICE_PROTOCOL_KEY)
     public String getMetadataServiceProtocol() {
         return metadataServiceProtocol;
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index f4e087df2c..4fb4056d75 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -16,6 +16,18 @@
  */
 package org.apache.dubbo.config;
 
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.Version;
@@ -24,6 +36,7 @@ import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
+import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
 import org.apache.dubbo.common.url.component.ServiceConfigURL;
 import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.CollectionUtils;
@@ -49,17 +62,6 @@ import org.apache.dubbo.rpc.model.ScopeModel;
 import org.apache.dubbo.rpc.model.ServiceDescriptor;
 import org.apache.dubbo.rpc.service.GenericService;
 
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
 import static 
org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
@@ -261,21 +263,41 @@ public class ServiceConfig<T> extends 
ServiceConfigBase<T> {
         exportedURLs.forEach(url -> {
             if (url.getParameters().containsKey(SERVICE_NAME_MAPPING_KEY)) {
                 ServiceNameMapping serviceNameMapping = 
ServiceNameMapping.getDefaultExtension(getScopeModel());
-                try {
-                    boolean succeeded = serviceNameMapping.map(url);
-                    if (succeeded) {
-                        logger.info("Successfully registered interface 
application mapping for service " + url.getServiceKey());
-                    } else {
-                        logger.error(CONFIG_SERVER_DISCONNECTED, 
"configuration server disconnected", "", "Failed register interface application 
mapping for service " + url.getServiceKey());
-                    }
-                } catch (Exception e) {
-                    logger.error(CONFIG_SERVER_DISCONNECTED, "configuration 
server disconnected", "", "Failed register interface application mapping for 
service " + url.getServiceKey(), e);
-                }
+                ScheduledExecutorService scheduledExecutor = 
getScopeModel().getBeanFactory()
+                    
.getBean(FrameworkExecutorRepository.class).getSharedScheduledExecutor();
+                mapServiceName(url, serviceNameMapping, scheduledExecutor);
             }
         });
         onExported();
     }
 
+    protected void mapServiceName(URL url, ServiceNameMapping 
serviceNameMapping, ScheduledExecutorService scheduledExecutor) {
+        if (!exported) {
+            return;
+        }
+        logger.info("Try to register interface application mapping for service 
" + url.getServiceKey());
+        boolean succeeded = false;
+        try {
+            succeeded = serviceNameMapping.map(url);
+            if (succeeded) {
+                logger.info("Successfully registered interface application 
mapping for service " + url.getServiceKey());
+            } else {
+                logger.error(CONFIG_SERVER_DISCONNECTED, "configuration server 
disconnected", "", "Failed register interface application mapping for service " 
+ url.getServiceKey());
+            }
+        } catch (Exception e) {
+            logger.error(CONFIG_SERVER_DISCONNECTED, "configuration server 
disconnected", "", "Failed register interface application mapping for service " 
+ url.getServiceKey(), e);
+        }
+        if (!succeeded) {
+            scheduleToMapping(scheduledExecutor, serviceNameMapping, url);
+        }
+    }
+
+    private void scheduleToMapping(ScheduledExecutorService scheduledExecutor, 
ServiceNameMapping serviceNameMapping, URL url) {
+        Integer mappingRetryInterval = 
getApplication().getMappingRetryInterval();
+        scheduledExecutor.schedule(() -> mapServiceName(url, 
serviceNameMapping, scheduledExecutor),
+            mappingRetryInterval == null ? 5000 : mappingRetryInterval, 
TimeUnit.MILLISECONDS);
+    }
+
     private void checkAndUpdateSubConfigs() {
 
         // Use default configs defined explicitly with global scope
diff --git 
a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
 
b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
index 36acb7ed91..0e676ba427 100644
--- 
a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
+++ 
b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
@@ -17,6 +17,14 @@
 
 package org.apache.dubbo.config;
 
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.config.api.DemoService;
@@ -27,22 +35,22 @@ import org.apache.dubbo.config.mock.MockRegistryFactory2;
 import org.apache.dubbo.config.mock.MockServiceListener;
 import org.apache.dubbo.config.mock.TestProxyFactory;
 import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+import org.apache.dubbo.metadata.MappingListener;
+import org.apache.dubbo.metadata.ServiceNameMapping;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.apache.dubbo.rpc.service.GenericService;
-
-import com.google.common.collect.Lists;
 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.Mockito;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
+import com.google.common.collect.Lists;
 
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
@@ -59,6 +67,7 @@ import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
 import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
 import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
+import static org.awaitility.Awaitility.await;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
@@ -529,4 +538,79 @@ class ServiceConfigTest {
             service.export();
         });
     }
+
+    @Test
+    void testMappingRetry() {
+        FrameworkModel frameworkModel = new FrameworkModel();
+        ApplicationModel applicationModel = frameworkModel.newApplication();
+        ServiceConfig<DemoService> serviceConfig = new 
ServiceConfig<>(applicationModel.newModule());
+        ScheduledExecutorService scheduledExecutorService = 
Executors.newScheduledThreadPool(1);
+        AtomicInteger count = new AtomicInteger(0);
+        ServiceNameMapping serviceNameMapping = new ServiceNameMapping() {
+            @Override
+            public boolean map(URL url) {
+                if (count.incrementAndGet() < 5) {
+                    throw new RuntimeException();
+                }
+                return count.get() > 10;
+            }
+
+            @Override
+            public void initInterfaceAppMapping(URL subscribedURL) {
+
+            }
+
+            @Override
+            public Set<String> getAndListen(URL registryURL, URL 
subscribedURL, MappingListener listener) {
+                return null;
+            }
+
+            @Override
+            public MappingListener stopListen(URL subscribeURL, 
MappingListener listener) {
+                return null;
+            }
+
+            @Override
+            public void putCachedMapping(String serviceKey, Set<String> apps) {
+
+            }
+
+            @Override
+            public Set<String> getCachedMapping(String mappingKey) {
+                return null;
+            }
+
+            @Override
+            public Set<String> getCachedMapping(URL consumerURL) {
+                return null;
+            }
+
+            @Override
+            public Set<String> getRemoteMapping(URL consumerURL) {
+                return null;
+            }
+
+            @Override
+            public Map<String, Set<String>> getCachedMapping() {
+                return null;
+            }
+
+            @Override
+            public Set<String> removeCachedMapping(String serviceKey) {
+                return null;
+            }
+
+            @Override
+            public void $destroy() {
+
+            }
+        };
+        ApplicationConfig applicationConfig = new ApplicationConfig("app");
+        applicationConfig.setMappingRetryInterval(10);
+        serviceConfig.setApplication(applicationConfig);
+        serviceConfig.mapServiceName(URL.valueOf(""), serviceNameMapping, 
scheduledExecutorService);
+
+        await().until(() -> count.get() > 10);
+        scheduledExecutorService.shutdown();
+    }
 }
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 c840300cf8..7b6e60e9e7 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
@@ -456,6 +456,11 @@
                 <xsd:documentation><![CDATA[ The preferred protocol to use, 
set protocol name. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="mapping-retry-interval" type="xsd:integer">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The retry interval of service 
name mapping. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="moduleType">

Reply via email to