You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by ra...@apache.org on 2021/11/08 03:37:13 UTC

[dubbo-admin] branch develop updated: GovernanceConfiguration use dubbo instead DynamicConfiguration (#840)

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

ranke pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git


The following commit(s) were added to refs/heads/develop by this push:
     new 906e871  GovernanceConfiguration use dubbo instead DynamicConfiguration (#840)
906e871 is described below

commit 906e87122f39527c54086db0d66fb04bcf746ba6
Author: haoyann <10...@qq.com>
AuthorDate: Mon Nov 8 11:37:07 2021 +0800

    GovernanceConfiguration use dubbo instead DynamicConfiguration (#840)
    
    * GovernanceConfiguration use dubbo instead DynamicConfiguration
    
    * remove useless change
---
 .../apache/dubbo/admin/common/util/Constants.java  |   3 +-
 .../apache/dubbo/admin/config/ConfigCenter.java    |   6 +-
 .../registry/config/GovernanceConfiguration.java   |   7 +-
 .../registry/config/impl/ApolloConfiguration.java  | 160 -----------------
 .../registry/config/impl/ConsulConfiguration.java  | 115 ------------
 .../config/impl/MultiDynamicConfiguration.java     | 109 +++++++++++
 .../registry/config/impl/NacosConfiguration.java   | 199 ---------------------
 .../registry/config/impl/NoOpConfiguration.java    |   8 +-
 .../config/impl/ZookeeperConfiguration.java        | 164 -----------------
 .../admin/service/impl/ManagementServiceImpl.java  |   3 +-
 .../admin/service/impl/MeshRouteServiceImpl.java   |   2 +-
 .../admin/service/impl/OverrideServiceImpl.java    |   4 +-
 .../dubbo/admin/service/impl/RouteServiceImpl.java |   6 +-
 ...o.admin.registry.config.GovernanceConfiguration |   5 +-
 .../admin/controller/ManagementControllerTest.java |  17 +-
 .../config/impl/ZookeeperConfigurationTest.java    |  16 +-
 16 files changed, 135 insertions(+), 689 deletions(-)

diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index aa694b7..0116da5 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -26,6 +26,7 @@ public class Constants {
     public static final String REGISTRY_ADDRESS = "dubbo.registry.address";
     public static final String METADATA_ADDRESS = "dubbo.metadata-report.address";
     public static final String DEFAULT_ROOT = "dubbo";
+    public static final String DEFAULT_GROUP = "dubbo";
     public static final String PATH_SEPARATOR = "/";
     public static final String GROUP_KEY = "group";
     public static final String NAMESPACE_KEY = "namespace";
@@ -74,7 +75,7 @@ public class Constants {
     public static final String CONSUMERS_CATEGORY = "consumers";
     public static final String SPECIFICATION_VERSION_KEY = "release";
     public static final String GLOBAL_CONFIG = "global";
-    public static final String GLOBAL_CONFIG_PATH = "config/dubbo/dubbo.properties";
+    public static final String GLOBAL_CONFIG_PATH = "dubbo.properties";
     public static final String METRICS_PORT = "metrics.port";
     public static final String METRICS_PROTOCOL = "metrics.protocol";
     public static final Set<String> CONFIGS = new HashSet<>();
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
index 2ca8958..8c39771 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -103,10 +103,10 @@ public class ConfigCenter {
 
         if (StringUtils.isNotEmpty(configCenter)) {
             configCenterUrl = formUrl(configCenter, configCenterGroup, configCenterGroupNameSpace, username, password);
-            dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(configCenterUrl.getProtocol());
+            dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getDefaultExtension();
             dynamicConfiguration.setUrl(configCenterUrl);
             dynamicConfiguration.init();
-            String config = dynamicConfiguration.getConfig(Constants.GLOBAL_CONFIG_PATH);
+            String config = dynamicConfiguration.getConfig(Constants.DUBBO_PROPERTY);
 
             if (StringUtils.isNotEmpty(config)) {
                 Arrays.stream(config.split("\n")).forEach(s -> {
@@ -122,7 +122,7 @@ public class ConfigCenter {
         if (dynamicConfiguration == null) {
             if (StringUtils.isNotEmpty(registryAddress)) {
                 registryUrl = formUrl(registryAddress, registryGroup, registryNameSpace, username, password);
-                dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(registryUrl.getProtocol());
+                dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getDefaultExtension();
                 dynamicConfiguration.setUrl(registryUrl);
                 dynamicConfiguration.init();
                 logger.warn("you are using dubbo.registry.address, which is not recommend, please refer to: https://github.com/apache/incubator-dubbo-admin/wiki/Dubbo-Admin-configuration");
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
index 21e739b..70ce83a 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
@@ -21,20 +21,21 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
 
 
-@SPI("zookeeper")
+@SPI("multi")
 public interface GovernanceConfiguration {
     void init();
 
     void setUrl(URL url);
 
     URL getUrl();
-    String setConfig(String key, String value);
+
+    boolean setConfig(String key, String value);
 
     String getConfig(String key);
 
     boolean deleteConfig(String key);
 
-    String setConfig(String group, String key, String value);
+    boolean setConfig(String group, String key, String value);
 
     String getConfig(String group, String key);
 
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
deleted file mode 100644
index 528df20..0000000
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dubbo.admin.registry.config.impl;
-
-import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient;
-import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
-
-import org.apache.dubbo.admin.common.util.Constants;
-import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.springframework.beans.factory.annotation.Value;
-
-import java.util.Arrays;
-import java.util.stream.Collectors;
-
-import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
-
-@SPI("apollo")
-public class ApolloConfiguration implements GovernanceConfiguration {
-
-    private static final String APOLLO_ENV_KEY = "env";
-    private static final String CLUSTER_KEY = "cluster";
-    private static final String TOKEN_KEY = "token";
-    private static final String APOLLO_APPID_KEY = "app.id";
-    private static final String APOLLO_PROTOCOL_PREFIX = "http://";
-
-    @Value("${admin.apollo.token:}")
-    private String configToken;
-
-    @Value("${admin.apollo.cluster:}")
-    private String configCluster;
-
-    @Value("${admin.apollo.namespace:}")
-    private String configNamespace;
-
-    @Value("${admin.apollo.env:}")
-    private String configEnv;
-
-    @Value("${admin.apollo.appId:}")
-    private String configAppId;
-
-    private String token;
-    private String cluster;
-    private String namespace;
-    private String env;
-    private String appId;
-    private URL url;
-    private ApolloOpenApiClient client;
-
-
-    @Override
-    public void setUrl(URL url) {
-       this.url = url;
-    }
-
-    @Override
-    public URL getUrl() {
-        return url;
-    }
-
-    @Override
-    public void init() {
-        token = url.getParameter(TOKEN_KEY, configToken);
-        cluster = url.getParameter(CLUSTER_KEY, configCluster);
-        namespace = url.getParameter(Constants.NAMESPACE_KEY, configNamespace);
-        env = url.getParameter(APOLLO_ENV_KEY, configEnv);
-        appId = url.getParameter(APOLLO_APPID_KEY, configAppId);
-        String address = getAddressWithProtocolPrefix(url);
-        client = ApolloOpenApiClient.newBuilder().withPortalUrl(address).withToken(token).build();
-    }
-    private String getAddressWithProtocolPrefix(URL url) {
-        String address = url.getBackupAddress();
-        if (StringUtils.isNotEmpty(address)) {
-            address = Arrays.stream(COMMA_SPLIT_PATTERN.split(address))
-                    .map(addr -> {
-                        if (addr.startsWith(APOLLO_PROTOCOL_PREFIX)) {
-                            return addr;
-                        }
-                        return APOLLO_PROTOCOL_PREFIX + addr;
-                    })
-                    .collect(Collectors.joining(","));
-        }
-        return address;
-    }
-    @Override
-    public String setConfig(String key, String value) {
-        return setConfig(null, key, value);
-    }
-
-    @Override
-    public String getConfig(String key) {
-        return getConfig(null, key);
-    }
-
-    @Override
-    public boolean deleteConfig(String key) {
-        return deleteConfig(null, key);
-    }
-
-    @Override
-    public String setConfig(String group, String key, String value) {
-        if (group == null) {
-            group = namespace;
-        }
-        OpenItemDTO openItemDTO = new OpenItemDTO();
-        openItemDTO.setKey(key);
-        openItemDTO.setValue(value);
-        client.createItem(appId, env, cluster, group, openItemDTO);
-        return value;
-    }
-
-    @Override
-    public String getConfig(String group, String key) {
-        if (group == null) {
-            group = namespace;
-        }
-        OpenItemDTO openItemDTO =  client.getItem(appId, env, cluster, group, key);
-        if (openItemDTO != null) {
-            return openItemDTO.getValue();
-        }
-        return null;
-    }
-
-    @Override
-    public boolean deleteConfig(String group, String key) {
-        if (group == null) {
-            group = namespace;
-        }
-        //TODO user login user name as the operator
-        client.removeItem(appId, env, cluster, group, key, "admin");
-        return true;
-    }
-
-    @Override
-    public String getPath(String key) {
-        return null;
-    }
-
-    @Override
-    public String getPath(String group, String key) {
-        return null;
-    }
-}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java
deleted file mode 100644
index 7c48fa7..0000000
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dubbo.admin.registry.config.impl;
-
-import com.ecwid.consul.v1.ConsulClient;
-import com.ecwid.consul.v1.Response;
-import com.ecwid.consul.v1.kv.model.GetValue;
-import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-
-public class ConsulConfiguration implements GovernanceConfiguration {
-	private static final Logger logger = LoggerFactory.getLogger(ConsulConfiguration.class);
-	private static final int DEFAULT_PORT = 8500;
-	private static final String SLASH = "/";
-	private URL url;
-	private ConsulClient client;
-
-	@Override
-	public void init() {
-		String host = this.url.getHost();
-		int port = this.url.getPort() != 0 ? url.getPort() : DEFAULT_PORT;
-		this.client = new ConsulClient(host, port);
-	}
-
-	@Override
-	public void setUrl(URL url) {
-		this.url = url;
-	}
-
-	@Override
-	public URL getUrl() {
-		return url;
-	}
-
-	@Override
-	public String setConfig(String key, String value) {
-		return setConfig(null, key, value);
-	}
-
-	@Override
-	public String getConfig(String key) {
-		return getConfig(null, key);
-	}
-
-	@Override
-	public boolean deleteConfig(String key) {
-		return deleteConfig(null, key);
-	}
-
-	@Override
-	public String setConfig(String group, String key, String value) {
-		if (group == null) {
-			client.setKVValue(key, value);
-			return value;
-		}
-		client.setKVValue(group + SLASH + key, value);
-		return value;
-	}
-
-	@Override
-	public String getConfig(String group, String key) {
-		if (group == null) {
-			Response<GetValue> response = client.getKVValue(key);
-			if (response.getValue() == null) {
-				return null;
-			}
-			return response.getValue().getDecodedValue();
-		}
-		Response<GetValue> response = client.getKVValue(group + SLASH + key);
-		return response.getValue() == null ? null : response.getValue().getDecodedValue();
-	}
-
-	@Override
-	public boolean deleteConfig(String group, String key) {
-		try {
-			if (group == null) {
-				client.deleteKVValue(key);
-				return true;
-			}
-			client.deleteKVValue(group + SLASH + key);
-		} catch (Exception e) {
-			logger.error(e.getMessage(), e);
-			return false;
-		}
-		return true;
-	}
-
-	@Override
-	public String getPath(String key) {
-		return null;
-	}
-
-	@Override
-	public String getPath(String group, String key) {
-		return null;
-	}
-
-}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java
new file mode 100644
index 0000000..ed870a8
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.registry.config.impl;
+
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+
+/**
+ * Use {@link org.apache.dubbo.common.config.configcenter.DynamicConfiguration} adaptation Configuration Center
+ */
+public class MultiDynamicConfiguration implements GovernanceConfiguration {
+
+    private URL url;
+
+    private DynamicConfiguration dynamicConfiguration;
+
+    private String group;
+
+    @Override
+    public void init() {
+        if (url == null) {
+            throw new IllegalStateException("server url is null, cannot init");
+        }
+        DynamicConfigurationFactory dynamicConfigurationFactory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class)
+                .getOrDefaultExtension(url.getProtocol());
+        dynamicConfiguration = dynamicConfigurationFactory.getDynamicConfiguration(url);
+        // group must be consistent with dubbo
+        group = url.getParameter(Constants.GROUP_KEY, Constants.DEFAULT_GROUP);
+    }
+
+    @Override
+    public void setUrl(URL url) {
+        this.url = url;
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    @Override
+    public boolean setConfig(String key, String value) {
+        return setConfig(group, key, value);
+    }
+
+    @Override
+    public String getConfig(String key) {
+        return getConfig(group, key);
+    }
+
+    @Override
+    public boolean deleteConfig(String key) {
+        return deleteConfig(group, key);
+    }
+
+    @Override
+    public boolean setConfig(String group, String key, String value) {
+        if (key == null || value == null) {
+            throw new IllegalArgumentException("key or value cannot be null");
+        }
+        return dynamicConfiguration.publishConfig(key, group, value);
+    }
+
+    @Override
+    public String getConfig(String group, String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key cannot be null");
+        }
+        return dynamicConfiguration.getConfig(key, group);
+    }
+
+    @Override
+    public boolean deleteConfig(String group, String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key cannot be null");
+        }
+        return dynamicConfiguration.removeConfig(key, group);
+    }
+
+    @Override
+    public String getPath(String key) {
+        return null;
+    }
+
+    @Override
+    public String getPath(String group, String key) {
+        return null;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java
deleted file mode 100644
index 18e82cb..0000000
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dubbo.admin.registry.config.impl;
-
-import org.apache.dubbo.admin.common.util.Constants;
-import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
-
-import com.alibaba.nacos.api.NacosFactory;
-import com.alibaba.nacos.api.PropertyKeyConst;
-import com.alibaba.nacos.api.config.ConfigService;
-import com.alibaba.nacos.api.exception.NacosException;
-import org.apache.commons.lang3.StringUtils;
-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.StringConstantFieldValuePredicate;
-
-import java.util.Map;
-import java.util.Properties;
-
-import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
-import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
-
-public class NacosConfiguration implements GovernanceConfiguration {
-    private static final Logger logger = LoggerFactory.getLogger(NacosConfiguration.class);
-
-    private ConfigService configService;
-    private String group;
-    private URL url;
-
-    @Override
-    public void init() {
-        group = url.getParameter(Constants.GROUP_KEY, "DEFAULT_GROUP");
-        configService = buildConfigService(url);
-    }
-
-    private ConfigService buildConfigService(URL url) {
-        Properties nacosProperties = buildNacosProperties(url);
-        try {
-            configService = NacosFactory.createConfigService(nacosProperties);
-        } catch (NacosException e) {
-            if (logger.isErrorEnabled()) {
-                logger.error(e.getErrMsg(), e);
-            }
-            throw new IllegalStateException(e);
-        }
-        return configService;
-    }
-
-    private Properties buildNacosProperties(URL url) {
-        Properties properties = new Properties();
-        setServerAddr(url, properties);
-        setNamespace(url, properties);
-        Map<String, String> parameters = url.getParameters(
-                StringConstantFieldValuePredicate.of(PropertyKeyConst.class));
-        properties.putAll(parameters);
-        return properties;
-    }
-
-    private void setServerAddr(URL url, Properties properties) {
-
-        String serverAddr = url.getHost() + // Host
-                ":" +
-                url.getPort() // Port
-                ;
-        properties.put(SERVER_ADDR, serverAddr);
-    }
-
-    private void setNamespace(URL url, Properties properties) {
-        String namespace = url.getParameter(NAMESPACE);
-        if (StringUtils.isNotBlank(namespace)) {
-            properties.put(NAMESPACE, namespace);
-        }
-    }
-
-
-    @Override
-    public void setUrl(URL url) {
-        this.url = url;
-    }
-
-    @Override
-    public URL getUrl() {
-        return url;
-    }
-
-    @Override
-    public String setConfig(String key, String value) {
-        return setConfig(group, key, value);
-    }
-
-    @Override
-    public String getConfig(String key) {
-        return getConfig(group, key);
-    }
-
-    @Override
-    public boolean deleteConfig(String key) {
-        return deleteConfig(group, key);
-    }
-
-    @Override
-    public String setConfig(String group, String key, String value) {
-        String[] groupAndDataId = parseGroupAndDataId(key, group);
-        if (null == groupAndDataId) {
-            return null;
-        }
-
-        try {
-            configService.publishConfig(groupAndDataId[1], groupAndDataId[0], value);
-            return value;
-        } catch (NacosException e) {
-            logger.error(e.getMessage(), e);
-
-        }
-        return null;
-    }
-
-    @Override
-    public String getConfig(String group, String key) {
-        String[] groupAndDataId = parseGroupAndDataId(key, group);
-        if (null == groupAndDataId) {
-            return null;
-        }
-        try {
-            return configService.getConfig(groupAndDataId[1], groupAndDataId[0],1000 * 10);
-        } catch (NacosException e) {
-            logger.error(e.getMessage(), e);
-        }
-        return null;
-    }
-
-    @Override
-    public boolean deleteConfig(String group, String key) {
-        String[] groupAndDataId = parseGroupAndDataId(key, group);
-        if (null == groupAndDataId) {
-            return false;
-        }
-        try {
-           return configService.removeConfig(groupAndDataId[1], groupAndDataId[0]);
-        } catch (NacosException e) {
-            logger.error(e.getMessage(), e);
-        }
-        return false;
-    }
-
-    @Override
-    public String getPath(String key) {
-        return null;
-    }
-
-    @Override
-    public String getPath(String group, String key) {
-        return null;
-    }
-
-    private String[] parseGroupAndDataId(String key, String group) {
-        if (StringUtils.isBlank(key) || StringUtils.isBlank(group)) {
-            if (logger.isWarnEnabled()) {
-                logger.warn("key or group is blank");
-                return null;
-            }
-        }
-
-        String[] groupAndDataId = new String[2];
-        String[] split = key.split("/");
-        if (split.length != 3) {
-            return null;
-        }
-        if (Constants.DUBBO_PROPERTY.equals(split[2])) {
-
-            if (this.group.equals(split[1])) {
-                groupAndDataId[0] = this.group;
-            } else {
-                groupAndDataId[0] = split[1];
-            }
-            groupAndDataId[1] = split[2];
-        } else {
-            groupAndDataId[0] = group;
-            groupAndDataId[1] = split[2];
-        }
-        return groupAndDataId;
-    }
-}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
index 5c4fd18..e5cead7 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
@@ -38,8 +38,8 @@ public class NoOpConfiguration implements GovernanceConfiguration {
     }
 
     @Override
-    public String setConfig(String key, String value) {
-        return null;
+    public boolean setConfig(String key, String value) {
+        return false;
     }
 
     @Override
@@ -53,8 +53,8 @@ public class NoOpConfiguration implements GovernanceConfiguration {
     }
 
     @Override
-    public String setConfig(String group, String key, String value) {
-        return null;
+    public boolean setConfig(String group, String key, String value) {
+        return false;
     }
 
     @Override
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
deleted file mode 100644
index 362dd26..0000000
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dubbo.admin.registry.config.impl;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.apache.dubbo.admin.common.util.Constants;
-import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-
-public class ZookeeperConfiguration implements GovernanceConfiguration {
-    private static final Logger logger = LoggerFactory.getLogger(ZookeeperConfiguration.class);
-    private CuratorFramework zkClient;
-    private URL url;
-    private String root;
-
-    @Override
-    public void setUrl(URL url) {
-        this.url = url;
-    }
-
-    @Override
-    public URL getUrl() {
-        return url;
-    }
-
-    @Override
-    public void init() {
-        if (url == null) {
-            throw new IllegalStateException("server url is null, cannot init");
-        }
-        CuratorFrameworkFactory.Builder zkClientBuilder = CuratorFrameworkFactory.builder().
-                connectString(url.getAddress()).
-                retryPolicy(new ExponentialBackoffRetry(1000, 3));
-        if (StringUtils.isNotEmpty(url.getUsername()) && StringUtils.isNotEmpty(url.getPassword())) {
-            // add authorization
-            String auth = url.getUsername() + ":" + url.getPassword();
-            zkClientBuilder.authorization("digest", auth.getBytes());
-        }
-        zkClient = zkClientBuilder.build();
-        String group = url.getParameter(Constants.GROUP_KEY, Constants.DEFAULT_ROOT);
-        if (!group.startsWith(Constants.PATH_SEPARATOR)) {
-            group = Constants.PATH_SEPARATOR + group;
-        }
-        root = group;
-        zkClient.start();
-    }
-
-    @Override
-    public String setConfig(String key, String value) {
-        return setConfig(null, key, value);
-    }
-
-    @Override
-    public String getConfig(String key) {
-        return getConfig(null, key);
-    }
-
-    @Override
-    public boolean deleteConfig(String key) {
-        return deleteConfig(null, key);
-    }
-
-    @Override
-    public String setConfig(String group, String key, String value) {
-        if (key == null || value == null) {
-            throw new IllegalArgumentException("key or value cannot be null");
-        }
-        String path = getNodePath(key, group);
-        try {
-            if (zkClient.checkExists().forPath(path) == null) {
-                zkClient.create().creatingParentsIfNeeded().forPath(path);
-            }
-            zkClient.setData().forPath(path, value.getBytes());
-            return value;
-        } catch (Exception e) {
-            logger.error(e.getMessage(), e);
-        }
-        return null;
-    }
-
-    @Override
-    public String getConfig(String group, String key) {
-        if (key == null) {
-            throw new IllegalArgumentException("key cannot be null");
-        }
-        String path = getNodePath(key, group);
-
-        try {
-            if (zkClient.checkExists().forPath(path) == null) {
-                return null;
-            }
-            return new String(zkClient.getData().forPath(path));
-        } catch (Exception e) {
-            logger.error(e.getMessage(), e);
-        }
-        return null;
-    }
-
-    @Override
-    public boolean deleteConfig(String group, String key) {
-        if (key == null) {
-            throw new IllegalArgumentException("key cannot be null");
-        }
-        String path = getNodePath(key, group);
-        try {
-            zkClient.delete().forPath(path);
-        } catch (Exception e) {
-            logger.error(e.getMessage(), e);
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String getPath(String key) {
-        return getNodePath(key, null);
-    }
-
-    @Override
-    public String getPath(String group, String key) {
-        return getNodePath(key, group);
-    }
-
-    private String getNodePath(String path, String group) {
-        if (path == null) {
-            throw new IllegalArgumentException("path cannot be null");
-        }
-        return toRootDir(group) + path;
-    }
-
-    private String toRootDir(String group) {
-        if (group != null) {
-            if (!group.startsWith(Constants.PATH_SEPARATOR)) {
-                root = Constants.PATH_SEPARATOR + group;
-            } else {
-                root = group;
-            }
-        }
-        if (root.equals(Constants.PATH_SEPARATOR)) {
-            return root;
-        }
-        return root + Constants.PATH_SEPARATOR;
-    }
-}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
index a1668fd..40ba258 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
@@ -73,8 +73,7 @@ public class ManagementServiceImpl extends AbstractService implements Management
     }
 
     private String getPath(String key) {
-        return Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR
-                + Constants.DUBBO_PROPERTY;
+        return  key + Constants.PATH_SEPARATOR + Constants.DUBBO_PROPERTY;
     }
 
 }
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
index b234eaf..fd591bd 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
@@ -84,7 +84,7 @@ public class MeshRouteServiceImpl extends AbstractService implements MeshRouteSe
     }
 
     private String getPath(String id) {
-        return Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + id + Constants.MESH_RULE_SUFFIX;
+        return id + Constants.MESH_RULE_SUFFIX;
     }
 
 }
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
index 1bc018e..361122a 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
@@ -42,7 +42,6 @@ import java.util.Map;
 
 @Component
 public class OverrideServiceImpl extends AbstractService implements OverrideService {
-    private String prefix = Constants.CONFIG_KEY;
 
     @java.lang.Override
     public void saveOverride(DynamicConfigDTO override) {
@@ -528,9 +527,10 @@ public class OverrideServiceImpl extends AbstractService implements OverrideServ
         }
         return result;
     }
+
     private String getPath(String key) {
         key = key.replace("/", "*");
-        return prefix + Constants.PATH_SEPARATOR + key + Constants.CONFIGURATOR_RULE_SUFFIX;
+        return key + Constants.CONFIGURATOR_RULE_SUFFIX;
     }
 
     private void unregisterWeight(WeightDTO weightDTO) {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
index ed28d64..4856a5f 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
@@ -39,8 +39,6 @@ import java.util.List;
 @Component
 public class RouteServiceImpl extends AbstractService implements RouteService {
 
-    private String prefix = Constants.CONFIG_KEY;
-
     @Override
     public void createConditionRoute(ConditionRouteDTO conditionRoute) {
         String id = ConvertUtil.getIdFromDTO(conditionRoute);
@@ -362,9 +360,9 @@ public class RouteServiceImpl extends AbstractService implements RouteService {
     private String getPath(String key, String type) {
         key = key.replace("/", "*");
         if (type.equals(Constants.CONDITION_ROUTE)) {
-            return prefix + Constants.PATH_SEPARATOR + key + Constants.CONDITION_RULE_SUFFIX;
+            return key + Constants.CONDITION_RULE_SUFFIX;
         } else {
-            return prefix + Constants.PATH_SEPARATOR + key + Constants.TAG_RULE_SUFFIX;
+            return key + Constants.TAG_RULE_SUFFIX;
         }
     }
 
diff --git a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration
index 14b6b02..88d69fe 100644
--- a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration
+++ b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration
@@ -1,4 +1 @@
-zookeeper=org.apache.dubbo.admin.registry.config.impl.ZookeeperConfiguration
-apollo=org.apache.dubbo.admin.registry.config.impl.ApolloConfiguration
-nacos=org.apache.dubbo.admin.registry.config.impl.NacosConfiguration
-consul=org.apache.dubbo.admin.registry.config.impl.ConsulConfiguration
+multi=org.apache.dubbo.admin.registry.config.impl.MultiDynamicConfiguration
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java
index 462285b..e31a798 100644
--- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java
@@ -31,6 +31,7 @@ import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
@@ -63,12 +64,6 @@ public class ManagementControllerTest extends AbstractSpringIntegrationTest {
     );
     assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED);
     assertEquals(responseEntity.getBody(), true);
-
-    byte[] bytes = zkClient.getData().forPath(getPath(""));
-    String config = new String(bytes);
-    assertEquals(configDTO.getConfig(), config);
-
-    zkClient.delete().forPath(getPath(""));
   }
 
   @Test
@@ -83,10 +78,6 @@ public class ManagementControllerTest extends AbstractSpringIntegrationTest {
     );
     assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED);
     assertEquals(responseEntity.getBody(), true);
-
-    byte[] bytes = zkClient.getData().forPath(getPath(application));
-    String config = new String(bytes);
-    assertEquals(configDTO.getConfig(), config);
   }
 
   @Test
@@ -104,11 +95,11 @@ public class ManagementControllerTest extends AbstractSpringIntegrationTest {
   @Test
   public void shouldUpdateConfigSpecifiedKey() throws Exception {
     String key = "shouldUpdateConfigSpecifiedKey";
+    String path = getPath(key);
+    zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+    zkClient.setData().forPath(path, "key1=val1\nkey2=val2".getBytes(StandardCharsets.UTF_8));
     ConfigDTO configDTO = new ConfigDTO();
     configDTO.setKey(key);
-    configDTO.setConfig("key1=val1\nkey2=val2");
-    restTemplate.postForEntity(url("/api/{env}/manage/config"), configDTO, Boolean.class, env);
-
     configDTO.setConfig("key1=updatedVal1\nkey2=updatedVal2");
     ResponseEntity<Void> responseEntity = restTemplate.exchange(
         url("/api/{env}/manage/config/{key}"), HttpMethod.PUT,
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java
index 7f15836..57aa1ff 100644
--- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java
@@ -33,7 +33,7 @@ import static org.junit.Assert.fail;
 public class ZookeeperConfigurationTest {
 
     private TestingServer zkServer;
-    private ZookeeperConfiguration configuration;
+    private MultiDynamicConfiguration configuration;
     private URL registryUrl;
 
     @Before
@@ -42,7 +42,7 @@ public class ZookeeperConfigurationTest {
         zkServer = new TestingServer(zkServerPort, true);
         registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort);
 
-        configuration = new ZookeeperConfiguration();
+        configuration = new MultiDynamicConfiguration();
         try {
             configuration.init();
             fail("init should fail before setting registryUrl");
@@ -79,13 +79,11 @@ public class ZookeeperConfigurationTest {
 
     @Test
     public void testDeleteConfig() {
-        assertEquals(false, configuration.deleteConfig("not_exist_key"));
         configuration.setConfig("test_delete", "test_value");
         assertEquals("test_value", configuration.getConfig("test_delete"));
         configuration.deleteConfig("test_delete");
         assertEquals(null, configuration.getConfig("test_delete"));
 
-        assertEquals(false, configuration.deleteConfig("test_group", "not_exist_key"));
         configuration.setConfig("test_group", "test_delete", "test_value");
         assertEquals("test_value", configuration.getConfig("test_group", "test_delete"));
         configuration.deleteConfig("test_group", "test_delete");
@@ -98,16 +96,6 @@ public class ZookeeperConfigurationTest {
         }
     }
 
-    @Test
-    public void testGetPath() {
-        assertEquals(Constants.PATH_SEPARATOR + Constants.DEFAULT_ROOT + Constants.PATH_SEPARATOR + "test_key",
-                configuration.getPath("test_key"));
-        try {
-            configuration.getPath(null);
-            fail("should throw IllegalArgumentException for null path");
-        } catch (IllegalArgumentException e) {
-        }
-    }
 
     @After
     public void tearDown() throws IOException {