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 acb96d4  【3.0】Enhance and fix check config (#8483)
acb96d4 is described below

commit acb96d40d1a85533f22c0e0f51d70736d65e3a85
Author: huazhongming <[email protected]>
AuthorDate: Mon Aug 23 14:41:12 2021 +0800

    【3.0】Enhance and fix check config (#8483)
---
 .../apache/dubbo/config/ConfigCenterConfig.java    | 74 ++++++++++++++--------
 .../apache/dubbo/config/MetadataReportConfig.java  | 37 +++++++++--
 .../dubbo/config/bootstrap/DubboBootstrap.java     | 19 +++++-
 .../bootstrap/builders/MetadataReportBuilder.java  | 36 +++++++++--
 .../src/main/resources/META-INF/dubbo.xsd          |  8 ++-
 .../metadata/report/MetadataReportInstance.java    | 13 ++--
 .../support/AbstractMetadataReportFactory.java     | 34 ++++++++--
 .../dubbo/registry/ListenerRegistryWrapper.java    |  8 ++-
 .../metadata/store/RemoteMetadataServiceImpl.java  |  2 +-
 .../registry/integration/RegistryProtocol.java     | 14 ++--
 .../registry/support/AbstractRegistryFactory.java  | 53 ++++++++++------
 .../zookeeper/ZookeeperServiceDiscovery.java       |  9 +--
 .../zookeeper/util/CuratorFrameworkUtils.java      | 39 +++++++-----
 13 files changed, 240 insertions(+), 106 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java 
b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index 8735af3..412122e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -41,51 +41,69 @@ import static 
org.apache.dubbo.config.Constants.ZOOKEEPER_PROTOCOL;
  * ConfigCenterConfig
  */
 public class ConfigCenterConfig extends AbstractConfig {
-    private AtomicBoolean inited = new AtomicBoolean(false);
+    private final AtomicBoolean initialized = new AtomicBoolean(false);
 
     private String protocol;
     private String address;
     private Integer port;
 
-    /* The config center cluster, it's real meaning may very on different 
Config Center products. */
+    /**
+     * The config center cluster, it's real meaning may very on different 
Config Center products.
+     */
     private String cluster;
 
-    /* The namespace of the config center, generally it's used for 
multi-tenant,
-    but it's real meaning depends on the actual Config Center you use.
-    */
+    /**
+     * The namespace of the config center, generally it's used for 
multi-tenant,
+     * but it's real meaning depends on the actual Config Center you use.
+     * The default value is CommonConstants.DUBBO
+     */
+    private String namespace;
 
-    private String namespace; // CommonConstants.DUBBO;
-    /* The group of the config center, generally it's used to identify an 
isolated space for a batch of config items,
-    but it's real meaning depends on the actual Config Center you use.
-    */
-    private String group; // CommonConstants.DUBBO;
+    /**
+     * The group of the config center, generally it's used to identify an 
isolated space for a batch of config items,
+     * but it's real meaning depends on the actual Config Center you use.
+     * The default value is CommonConstants.DUBBO
+     */
+    private String group;
     private String username;
     private String password;
-    private Long timeout; // 3000L;
+
+    /**
+     * The default value is 3000L;
+     */
+    private Long timeout;
 
     /**
      * If the Config Center is given the highest priority, it will override 
all the other configurations
+     * The default value is true
      * @deprecated no longer used
      */
-    private Boolean highestPriority; // true;
+    private Boolean highestPriority;
 
-    // Decide the behaviour when initial connection try fails, 'true' means 
interrupt the whole process once fail.
-    private Boolean check; // true;
+    /**
+     * Decide the behaviour when initial connection try fails, 'true' means 
interrupt the whole process once fail.
+     * The default value is true
+     */
+    private Boolean check;
 
-    /* Used to specify the key that your properties file mapping to, most of 
the time you do not need to change this parameter.
-    Notice that for Apollo, this parameter is meaningless, set the 'namespace' 
is enough.
-    */
-    private String configFile; // CommonConstants.DEFAULT_DUBBO_PROPERTIES;
+    /**
+     * Used to specify the key that your properties file mapping to, most of 
the time you do not need to change this parameter.
+     * Notice that for Apollo, this parameter is meaningless, set the 
'namespace' is enough.
+     * The default value is CommonConstants.DEFAULT_DUBBO_PROPERTIES
+     */
+    private String configFile;
 
-    /* the .properties file under 'configFile' is global shared while 
.properties under this one is limited only to this application
-    */
+    /**
+     * the properties file under 'configFile' is global shared while 
.properties under this one is limited only to this application
+     */
     private String appConfigFile;
 
-    /* If the Config Center product you use have some special parameters that 
is not covered by this class, you can add it to here.
-    For example, with XML:
-      <dubbo:config-center>
-           <dubbo:parameter key="{your key}" value="{your value}" />
-      </dubbo:config-center>
+    /**
+     * If the Config Center product you use have some special parameters that 
is not covered by this class, you can add it to here.
+     * For example, with XML:
+     *    <dubbo:config-center>
+     *       <dubbo:parameter key="{your key}" value="{your value}" />
+     *    </dubbo:config-center>
      */
     private Map<String, String> parameters;
 
@@ -127,15 +145,15 @@ public class ConfigCenterConfig extends AbstractConfig {
             address = ANYHOST_VALUE;
         }
         map.put(PATH_KEY, ConfigCenterConfig.class.getSimpleName());
-        // use 'zookeeper' as the default configcenter.
+        // use 'zookeeper' as the default config center.
         if (StringUtils.isEmpty(map.get(PROTOCOL_KEY))) {
             map.put(PROTOCOL_KEY, ZOOKEEPER_PROTOCOL);
         }
         return UrlUtils.parseURL(address, map);
     }
 
-    public boolean checkOrUpdateInited() {
-        return inited.compareAndSet(false, true);
+    public boolean checkOrUpdateInitialized(boolean update) {
+        return initialized.compareAndSet(false, update);
     }
 
     public Map<String, String> getExternalConfiguration() {
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java 
b/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java
index 6704ff5..239d11c 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java
@@ -40,7 +40,9 @@ public class MetadataReportConfig extends AbstractConfig {
 
     private String protocol;
 
-    // metadata center address
+    /**
+     * metadata center address
+     */
     private String address;
 
     /**
@@ -48,13 +50,19 @@ public class MetadataReportConfig extends AbstractConfig {
      */
     private Integer port;
 
-    // Username to login metadata center
+    /**
+     * Username to login metadata center
+     */
     private String username;
 
-    // Password to login metadata center
+    /**
+     * Password to login metadata center
+     */
     private String password;
 
-    // Request timeout in milliseconds for metadata center
+    /**
+     * Request timeout in milliseconds for metadata center
+     */
     private Integer timeout;
 
     /**
@@ -62,14 +70,16 @@ public class MetadataReportConfig extends AbstractConfig {
      */
     private String group;
 
-    // Customized parameters
+    /**
+     * Customized parameters
+     */
     private Map<String, String> parameters;
 
     private Integer retryTimes;
 
     private Integer retryPeriod;
     /**
-     * By default the metadatastore will store full metadata repeatedly every 
day .
+     * By default the metadata store will store full metadata repeatedly every 
day .
      */
     private Boolean cycleReport;
 
@@ -93,6 +103,13 @@ public class MetadataReportConfig extends AbstractConfig {
      */
     private String file;
 
+    /**
+     * Decide the behaviour when initial connection try fails,
+     * 'true' means interrupt the whole process once fail.
+     * The default value is true
+     */
+    private Boolean check;
+
 
     public MetadataReportConfig() {
     }
@@ -280,4 +297,12 @@ public class MetadataReportConfig extends AbstractConfig {
             this.parameters.putAll(parameters);
         }
     }
+
+    public Boolean isCheck() {
+        return check;
+    }
+
+    public void setCheck(Boolean check) {
+        this.check = check;
+    }
 }
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
index 1b43f05..3d4dec9 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
@@ -1099,7 +1099,7 @@ public class DubboBootstrap {
      */
     public synchronized DubboBootstrap start() {
         // avoid re-entry start method multiple times in same thread
-        if (isCurrentlyInStart){
+        if (isCurrentlyInStart) {
             return this;
         }
 
@@ -1330,10 +1330,23 @@ public class DubboBootstrap {
 
     private DynamicConfiguration prepareEnvironment(ConfigCenterConfig 
configCenter) {
         if (configCenter.isValid()) {
-            if (!configCenter.checkOrUpdateInited()) {
+            if (!configCenter.checkOrUpdateInitialized(true)) {
                 return null;
             }
-            DynamicConfiguration dynamicConfiguration = 
getDynamicConfiguration(configCenter.toUrl());
+
+            DynamicConfiguration dynamicConfiguration = null;
+            try {
+                dynamicConfiguration = 
getDynamicConfiguration(configCenter.toUrl());
+            } catch (Exception e) {
+                if (!configCenter.isCheck()) {
+                    logger.warn("The configuration center failed to 
initialize", e);
+                    configCenter.checkOrUpdateInitialized(false);
+                    return null;
+                } else {
+                    throw new IllegalStateException(e);
+                }
+            }
+
             String configContent = 
dynamicConfiguration.getProperties(configCenter.getConfigFile(), 
configCenter.getGroup());
 
             String appGroup = getApplication().getName();
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/MetadataReportBuilder.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/MetadataReportBuilder.java
index 0e36eca..10c43c0 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/MetadataReportBuilder.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/MetadataReportBuilder.java
@@ -27,16 +27,24 @@ import java.util.Map;
  */
 public class MetadataReportBuilder extends 
AbstractBuilder<MetadataReportConfig, MetadataReportBuilder> {
 
-    // Register center address
+    /**
+     * Register center address
+     */
     private String address;
 
-    // Username to login register center
+    /**
+     * Username to login register center
+     */
     private String username;
 
-    // Password to login register center
+    /**
+     * Password to login register center
+     */
     private String password;
 
-    // Request timeout in milliseconds for register center
+    /**
+     * Request timeout in milliseconds for register center
+     */
     private Integer timeout;
 
     /**
@@ -44,14 +52,16 @@ public class MetadataReportBuilder extends 
AbstractBuilder<MetadataReportConfig,
      */
     private String group;
 
-    // Customized parameters
+    /**
+     * Customized parameters
+     */
     private Map<String, String> parameters;
 
     private Integer retryTimes;
 
     private Integer retryPeriod;
     /**
-     * By default the metadatastore will store full metadata repeatedly every 
day .
+     * By default the metadata store will store full metadata repeatedly every 
day .
      */
     private Boolean cycleReport;
 
@@ -60,6 +70,13 @@ public class MetadataReportBuilder extends 
AbstractBuilder<MetadataReportConfig,
      */
     private Boolean syncReport;
 
+    /**
+     * Decide the behaviour when initial connection try fails,
+     * 'true' means interrupt the whole process once fail.
+     * The default value is true
+     */
+    private Boolean check;
+
     public static MetadataReportBuilder newBuilder() {
         return new MetadataReportBuilder();
     }
@@ -119,6 +136,12 @@ public class MetadataReportBuilder extends 
AbstractBuilder<MetadataReportConfig,
         return getThis();
     }
 
+    public MetadataReportBuilder check(Boolean check) {
+        this.check = check;
+        return getThis();
+    }
+
+    @Override
     public MetadataReportConfig build() {
         MetadataReportConfig metadataReport = new MetadataReportConfig();
         super.build(metadataReport);
@@ -133,6 +156,7 @@ public class MetadataReportBuilder extends 
AbstractBuilder<MetadataReportConfig,
         metadataReport.setRetryPeriod(retryPeriod);
         metadataReport.setCycleReport(cycleReport);
         metadataReport.setSyncReport(syncReport);
+        metadataReport.setCheck(check);
 
         return metadataReport;
     }
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 7f9ed80..8c6a4ae 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
@@ -583,7 +583,7 @@
         </xsd:attribute>
         <xsd:attribute name="check" type="xsd:string">
             <xsd:annotation>
-                <xsd:documentation><![CDATA[ Check registry status on stratup. 
]]></xsd:documentation>
+                <xsd:documentation><![CDATA[ Check registry status on startup. 
]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
         <xsd:attribute name="dynamic" type="xsd:string">
@@ -737,6 +737,12 @@
                 <xsd:documentation><![CDATA[ The metadata report file store. 
]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="check" type="xsd:boolean" use="optional">
+            <xsd:annotation>
+                <xsd:documentation>
+                    <![CDATA[ The policy to apply when connecting to metadata 
center fails. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="configCenterType">
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
index 7f05844..08040ee 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
@@ -49,15 +49,18 @@ public class MetadataReportInstance {
         if (METADATA_REPORT_KEY.equals(url.getProtocol())) {
             String protocol = url.getParameter(METADATA_REPORT_KEY, 
DEFAULT_DIRECTORY);
             url = URLBuilder.from(url)
-                    .setProtocol(protocol)
-                    .removeParameter(METADATA_REPORT_KEY)
-                    .build();
+                .setProtocol(protocol)
+                .removeParameter(METADATA_REPORT_KEY)
+                .build();
         }
         url = url.addParameterIfAbsent(APPLICATION_KEY, 
ApplicationModel.getApplicationConfig().getName());
         String relatedRegistryId = config.getRegistry() == null ? DEFAULT_KEY 
: config.getRegistry();
 //        RegistryConfig registryConfig = 
ApplicationModel.getConfigManager().getRegistry(relatedRegistryId)
 //                .orElseThrow(() -> new IllegalStateException("Registry id " 
+ relatedRegistryId + " does not exist."));
-        metadataReports.put(relatedRegistryId, 
metadataReportFactory.getMetadataReport(url));
+        MetadataReport metadataReport = 
metadataReportFactory.getMetadataReport(url);
+        if (metadataReport != null) {
+            metadataReports.put(relatedRegistryId, metadataReport);
+        }
         init.set(true);
     }
 
@@ -80,7 +83,7 @@ public class MetadataReportInstance {
 
     private static void checkInit() {
         if (!init.get()) {
-            throw new IllegalStateException("the metadata report was not 
inited.");
+            throw new IllegalStateException("the metadata report was not 
initialized.");
         }
     }
 
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
index 4e162d3..29f21d8 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
@@ -26,22 +26,30 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
 
+import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
+
 public abstract class AbstractMetadataReportFactory implements 
MetadataReportFactory {
 
     private static final Logger logger = 
LoggerFactory.getLogger(AbstractMetadataReportFactory.class);
     private static final String EXPORT_KEY = "export";
     private static final String REFER_KEY = "refer";
 
-    // The lock for the acquisition process of the registry
+    /**
+     * The lock for the acquisition process of the registry
+     */
     private static final ReentrantLock LOCK = new ReentrantLock();
 
-    // Registry Collection Map<metadataAddress, MetadataReport>
-    private static final Map<String, MetadataReport> SERVICE_STORE_MAP = new 
ConcurrentHashMap<String, MetadataReport>();
+    /**
+     * Registry Collection Map<metadataAddress, MetadataReport>
+     */
+    private static final Map<String, MetadataReport> SERVICE_STORE_MAP = new 
ConcurrentHashMap<>();
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(AbstractMetadataReportFactory.class);
 
     @Override
     public MetadataReport getMetadataReport(URL url) {
         url = url.setPath(MetadataReport.class.getName())
-                .removeParameters(EXPORT_KEY, REFER_KEY);
+            .removeParameters(EXPORT_KEY, REFER_KEY);
         String key = url.toServiceString();
 
         MetadataReport metadataReport = SERVICE_STORE_MAP.get(key);
@@ -56,11 +64,23 @@ public abstract class AbstractMetadataReportFactory 
implements MetadataReportFac
             if (metadataReport != null) {
                 return metadataReport;
             }
-            metadataReport = createMetadataReport(url);
-            if (metadataReport == null) {
+            boolean check = url.getParameter(CHECK_KEY, true) && url.getPort() 
!= 0;
+            try {
+                metadataReport = createMetadataReport(url);
+            } catch (Exception e) {
+                if (!check) {
+                    LOGGER.warn("The metadata reporter failed to initialize", 
e);
+                } else {
+                    throw e;
+                }
+            }
+
+            if (check && metadataReport == null) {
                 throw new IllegalStateException("Can not create metadata 
Report " + url);
             }
-            SERVICE_STORE_MAP.put(key, metadataReport);
+            if (metadataReport != null) {
+                SERVICE_STORE_MAP.put(key, metadataReport);
+            }
             return metadataReport;
         } finally {
             // Release the lock
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 63d0dfc..7e0aea1 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
@@ -55,7 +55,9 @@ public class ListenerRegistryWrapper implements Registry {
     @Override
     public void register(URL url) {
         try {
-            registry.register(url);
+            if (registry != null) {
+                registry.register(url);
+            }
         } finally {
             if (CollectionUtils.isNotEmpty(listeners) && 
!UrlUtils.isConsumer(url)) {
                 RuntimeException exception = null;
@@ -103,7 +105,9 @@ public class ListenerRegistryWrapper implements Registry {
     @Override
     public void subscribe(URL url, NotifyListener listener) {
         try {
-            registry.subscribe(url, listener);
+            if (registry != null) {
+                registry.subscribe(url, listener);
+            }
         } finally {
             if (CollectionUtils.isNotEmpty(listeners)) {
                 RuntimeException exception = null;
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
index 4b926fa..a073674 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
@@ -103,7 +103,7 @@ public class RemoteMetadataServiceImpl {
 
     private void checkRemoteConfigured() {
         if (getMetadataReports().size() == 0) {
-            String msg = "Remote Metadata Report Server not hasn't been 
configured. Unable to get Metadata from remote!";
+            String msg = "Remote Metadata Report Server not hasn't been 
configured or unavailable . Unable to get Metadata from remote!";
             logger.error(msg);
             throw new IllegalStateException(msg);
         }
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 e4ff7c4..f11cafb 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
@@ -804,12 +804,14 @@ public class RegistryProtocol implements Protocol {
                 logger.warn(t.getMessage(), t);
             }
             try {
-                NotifyListener listener = 
RegistryProtocol.this.overrideListeners.remove(subscribeUrl);
-                registry.unsubscribe(subscribeUrl, listener);
-                if 
(ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, 
org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
-                    
ExtensionLoader.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
-                        .removeListener(subscribeUrl.getServiceKey() + 
CONFIGURATORS_SUFFIX,
-                            
serviceConfigurationListeners.get(subscribeUrl.getServiceKey()));
+                if (subscribeUrl != null) {
+                    NotifyListener listener = 
RegistryProtocol.this.overrideListeners.remove(subscribeUrl);
+                    registry.unsubscribe(subscribeUrl, listener);
+                    if 
(ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, 
org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
+                        
ExtensionLoader.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
+                            .removeListener(subscribeUrl.getServiceKey() + 
CONFIGURATORS_SUFFIX,
+                                
serviceConfigurationListeners.get(subscribeUrl.getServiceKey()));
+                    }
                 }
             } catch (Throwable t) {
                 logger.warn(t.getMessage(), t);
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 deda9ac..169b51e 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
@@ -39,6 +39,7 @@ import java.util.stream.Collectors;
 
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
 
@@ -49,13 +50,16 @@ import static 
org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
  */
 public abstract class AbstractRegistryFactory implements RegistryFactory {
 
-    // Log output
     private static final Logger LOGGER = 
LoggerFactory.getLogger(AbstractRegistryFactory.class);
 
-    // The lock for the acquisition process of the registry
+    /**
+     * The lock for the acquisition process of the registry
+     */
     protected static final ReentrantLock LOCK = new ReentrantLock();
 
-    // Registry Collection Map<RegistryAddress, Registry>
+    /**
+     * Registry Collection Map<RegistryAddress, Registry>
+     */
     protected static final Map<String, Registry> REGISTRIES = new HashMap<>();
 
     private static final AtomicBoolean destroyed = new AtomicBoolean(false);
@@ -75,11 +79,11 @@ public abstract class AbstractRegistryFactory implements 
RegistryFactory {
 
     public static List<ServiceDiscovery> getServiceDiscoveries() {
         return AbstractRegistryFactory.getRegistries()
-                .stream()
-                .filter(registry -> registry instanceof 
ServiceDiscoveryRegistry)
-                .map(registry -> (ServiceDiscoveryRegistry) registry)
-                .map(ServiceDiscoveryRegistry::getServiceDiscovery)
-                .collect(Collectors.toList());
+            .stream()
+            .filter(registry -> registry instanceof ServiceDiscoveryRegistry)
+            .map(registry -> (ServiceDiscoveryRegistry) registry)
+            .map(ServiceDiscoveryRegistry::getServiceDiscovery)
+            .collect(Collectors.toList());
     }
 
     /**
@@ -121,7 +125,7 @@ public abstract class AbstractRegistryFactory implements 
RegistryFactory {
     private Registry getDefaultNopRegistryIfDestroyed() {
         if (destroyed.get()) {
             LOGGER.warn("All registry instances have been destroyed, failed to 
fetch any instance. " +
-                    "Usually, this means no need to try to do unnecessary 
redundant resource clearance, all registries has been taken care of.");
+                "Usually, this means no need to try to do unnecessary 
redundant resource clearance, all registries has been taken care of.");
             return DEFAULT_NOP_REGISTRY;
         }
         return null;
@@ -136,11 +140,13 @@ public abstract class AbstractRegistryFactory implements 
RegistryFactory {
         }
 
         url = URLBuilder.from(url)
-                .setPath(RegistryService.class.getName())
-                .addParameter(INTERFACE_KEY, RegistryService.class.getName())
-                .removeParameters(EXPORT_KEY, REFER_KEY, TIMESTAMP_KEY)
-                .build();
+            .setPath(RegistryService.class.getName())
+            .addParameter(INTERFACE_KEY, RegistryService.class.getName())
+            .removeParameters(EXPORT_KEY, REFER_KEY, TIMESTAMP_KEY)
+            .build();
         String key = createRegistryCacheKey(url);
+        Registry registry = null;
+        boolean check = url.getParameter(CHECK_KEY, true) && url.getPort() != 
0;
         // Lock the registry access process to ensure a single instance of the 
registry
         LOCK.lock();
         try {
@@ -150,22 +156,31 @@ public abstract class AbstractRegistryFactory implements 
RegistryFactory {
             if (null != defaultNopRegistry) {
                 return defaultNopRegistry;
             }
-
-            Registry registry = REGISTRIES.get(key);
+            registry = REGISTRIES.get(key);
             if (registry != null) {
                 return registry;
             }
             //create registry by spi/ioc
             registry = createRegistry(url);
-            if (registry == null) {
-                throw new IllegalStateException("Can not create registry " + 
url);
+        } catch (Exception e) {
+            if (check) {
+                throw new RuntimeException("Can not create registry " + url, 
e);
+            } else {
+                LOGGER.warn("Failed to obtain or create registry ", e);
             }
-            REGISTRIES.put(key, registry);
-            return registry;
         } finally {
             // Release the lock
             LOCK.unlock();
         }
+
+        if (check && registry == null) {
+            throw new IllegalStateException("Can not create registry " + url);
+        }
+
+        if (registry != null) {
+            REGISTRIES.put(key, registry);
+        }
+        return registry;
     }
 
     /**
diff --git 
a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
 
b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
index dc696db..45da52c 100644
--- 
a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
+++ 
b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
@@ -85,6 +85,7 @@ public class ZookeeperServiceDiscovery extends 
AbstractServiceDiscovery {
         return registryURL;
     }
 
+    @Override
     public void doDestroy() throws Exception {
         serviceDiscovery.close();
     }
@@ -153,13 +154,7 @@ public class ZookeeperServiceDiscovery extends 
AbstractServiceDiscovery {
                 }
 
                 if (healthyOnly) {
-                    Iterator<ServiceInstance> instanceIterator = 
serviceInstances.iterator();
-                    while (instanceIterator.hasNext()) {
-                        ServiceInstance instance = instanceIterator.next();
-                        if (!instance.isHealthy()) {
-                            instanceIterator.remove();
-                        }
-                    }
+                    serviceInstances.removeIf(instance -> 
!instance.isHealthy());
                 }
             } catch (KeeperException.NoNodeException e) {
                 logger.warn(p + " path not exist.", e);
diff --git 
a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
 
b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
index cb532bd..d9e137c 100644
--- 
a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
+++ 
b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.registry.zookeeper.util;
 
+import org.apache.curator.framework.imps.CuratorFrameworkState;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
@@ -51,19 +52,27 @@ public abstract class CuratorFrameworkUtils {
     public static ServiceDiscovery<ZookeeperInstance> 
buildServiceDiscovery(CuratorFramework curatorFramework,
                                                                             
String basePath) {
         return ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)
-                .client(curatorFramework)
-                .basePath(basePath)
-                .build();
+            .client(curatorFramework)
+            .basePath(basePath)
+            .build();
     }
 
     public static CuratorFramework buildCuratorFramework(URL connectionURL) 
throws Exception {
         CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
-                .connectString(connectionURL.getBackupAddress())
-                .retryPolicy(buildRetryPolicy(connectionURL))
-                .build();
+            .connectString(connectionURL.getBackupAddress())
+            .retryPolicy(buildRetryPolicy(connectionURL))
+            .build();
         curatorFramework.start();
         
curatorFramework.blockUntilConnected(BLOCK_UNTIL_CONNECTED_WAIT.getParameterValue(connectionURL),
-                BLOCK_UNTIL_CONNECTED_UNIT.getParameterValue(connectionURL));
+            BLOCK_UNTIL_CONNECTED_UNIT.getParameterValue(connectionURL));
+
+        if 
(!curatorFramework.getState().equals(CuratorFrameworkState.STARTED)) {
+            throw new IllegalStateException("zookeeper client initialization 
failed");
+        }
+
+        if (!curatorFramework.getZookeeperClient().isConnected()) {
+            throw new IllegalStateException("failed to connect to zookeeper 
server");
+        }
         return curatorFramework;
     }
 
@@ -76,7 +85,7 @@ public abstract class CuratorFrameworkUtils {
 
 
     public static List<ServiceInstance> 
build(Collection<org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance>>
-                                                      instances) {
+                                                  instances) {
         return 
instances.stream().map(CuratorFrameworkUtils::build).collect(Collectors.toList());
     }
 
@@ -91,7 +100,7 @@ public abstract class CuratorFrameworkUtils {
     }
 
     public static 
org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> 
build(ServiceInstance serviceInstance) {
-        ServiceInstanceBuilder builder = null;
+        ServiceInstanceBuilder builder;
         String serviceName = serviceInstance.getServiceName();
         String host = serviceInstance.getHost();
         int port = serviceInstance.getPort();
@@ -100,18 +109,18 @@ public abstract class CuratorFrameworkUtils {
         ZookeeperInstance zookeeperInstance = new ZookeeperInstance(null, 
serviceName, metadata);
         try {
             builder = builder()
-                    .id(id)
-                    .name(serviceName)
-                    .address(host)
-                    .port(port)
-                    .payload(zookeeperInstance);
+                .id(id)
+                .name(serviceName)
+                .address(host)
+                .port(port)
+                .payload(zookeeperInstance);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
         return builder.build();
     }
 
-    public static final String generateId(String host, int port) {
+    public static String generateId(String host, int port) {
         return host + ":" + port;
     }
 }

Reply via email to