You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/06/07 04:01:30 UTC

[skywalking] branch master updated: Provide Nacos dynamic configuration center implementation. fixes #2816 (#2817)

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

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 7f22770  Provide Nacos dynamic configuration center implementation. fixes #2816 (#2817)
7f22770 is described below

commit 7f2277091dcab2ee7c2cabb414622d4fd99064e8
Author: kezhenxu94 <ke...@163.com>
AuthorDate: Fri Jun 7 12:01:24 2019 +0800

    Provide Nacos dynamic configuration center implementation. fixes #2816 (#2817)
    
    * Provide Nacos dynamic configuration center implementation. fixes #2816
    
    * Add unit tests
    
    * Sync
    
    * Replace pull-mode with watch-mode
    
    * Fix ci
    
    * Unify dependency management
    
    * Add integration tests
    
    * Revert unexpected changes
    
    * Add more test cases
    
    * Revert unexpected changes
    
    * Suppress IDE warning
    
    * Correctify volumes position
    
    * Add license header
    
    * Remove Chinese comments
    
    * Sync
    
    * Sync
    
    * Sync
    
    * Sync
    
    * Revert unexpected changes
    
    * Rebase on refactored code and add missing config to docker
    
    * Fix unit test
    
    * Revert unnecessary changes
---
 docs/en/setup/backend/dynamic-config.md            |  24 ++-
 oap-server/pom.xml                                 |   8 +-
 .../cluster-nacos-plugin/pom.xml                   |   7 +-
 .../oap/server/configuration/api/ConfigTable.java  |   2 +
 .../configuration-nacos/pom.xml                    | 142 ++++++++++++++
 .../nacos/NacosConfigWatcherRegister.java          | 132 +++++++++++++
 .../nacos/NacosConfigurationProvider.java          |  68 +++++++
 .../configuration/nacos/NacosServerSettings.java   |  79 ++++++++
 ...alking.oap.server.library.module.ModuleProvider |  19 ++
 .../nacos/ITNacosConfigurationTest.java            | 113 +++++++++++
 .../nacos/NacosConfigWatcherRegisterTest.java      |  66 +++++++
 .../nacos/NacosConfigurationTestModule.java}       |  31 +--
 .../nacos/NacosConfigurationTestProvider.java      |  93 +++++++++
 ...ywalking.oap.server.library.module.ModuleDefine |  20 ++
 ...alking.oap.server.library.module.ModuleProvider |  19 ++
 .../src/test/resources/application.yml             |  37 ++++
 .../docker-entrypoint-initdb.d/nacos-mysql.sql     | 213 +++++++++++++++++++++
 oap-server/server-configuration/pom.xml            |   3 +-
 oap-server/server-starter/pom.xml                  |   5 +
 .../src/main/assembly/application.yml              |  11 ++
 .../src/main/resources/application.yml             |  12 ++
 21 files changed, 1075 insertions(+), 29 deletions(-)

diff --git a/docs/en/setup/backend/dynamic-config.md b/docs/en/setup/backend/dynamic-config.md
index de13691..c9b3167 100644
--- a/docs/en/setup/backend/dynamic-config.md
+++ b/docs/en/setup/backend/dynamic-config.md
@@ -31,9 +31,31 @@ configuration:
     #clusterName: "default" # the name of current cluster, set the name if you want to upstream system known.  
 ```
 
+## Nacos DCS
+
+[Nacos](https://github.com/alibaba/nacos) is also supported in DCS, to use it, please configure as follows:
+
+```yaml
+configuration:
+  nacos:
+    # Nacos Server Host
+    serverAddr: 127.0.0.1
+    # Nacos Server Port
+    port: 8848
+    # Nacos Configuration Group
+    group: 'skywalking'
+    # Dynamically configured keys
+    dataIds:
+      - receiver-trace.default.slowDBAccessThreshold
+      # - other-key
+    # Unit seconds, sync period. Default fetch every 60 seconds.
+    period : 60
+    # the name of current cluster, set the name if you want to upstream system known.
+    clusterName: "default"
+```
 
 ## 3rd party Configuration Center
 We are welcome contributions to implement this module provider to support popular configuration center, 
-such as Zookeeper, etcd, Consul, Nacos. Submit issue to discuss.
+such as Zookeeper, etcd, Consul. Submit issue to discuss.
 
 
diff --git a/oap-server/pom.xml b/oap-server/pom.xml
index f6e4752..6a1ea52 100644
--- a/oap-server/pom.xml
+++ b/oap-server/pom.xml
@@ -78,6 +78,7 @@
         <simpleclient.version>0.6.0</simpleclient.version>
 
         <maven-docker-plugin.version>0.28.0</maven-docker-plugin.version>
+        <nacos.version>1.0.0</nacos.version>
     </properties>
 
     <dependencies>
@@ -359,6 +360,11 @@
                 <artifactId>simpleclient</artifactId>
                 <version>${simpleclient.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.alibaba.nacos</groupId>
+                <artifactId>nacos-client</artifactId>
+                <version>${nacos.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
@@ -396,4 +402,4 @@
             </plugin>
         </plugins>
     </build>
-</project>
\ No newline at end of file
+</project>
diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml b/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml
index 15889ad..3f6ee60 100644
--- a/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml
+++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml
@@ -27,9 +27,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>cluster-nacos-plugin</artifactId>
-    <properties>
-        <nacos.version>1.0.0</nacos.version>
-    </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.skywalking</groupId>
@@ -39,7 +37,6 @@
         <dependency>
             <groupId>com.alibaba.nacos</groupId>
             <artifactId>nacos-client</artifactId>
-            <version>${nacos.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.slf4j</groupId>
@@ -68,4 +65,4 @@
             </exclusions>
         </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java b/oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java
index 742f44f..c8988cb 100644
--- a/oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java
+++ b/oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java
@@ -26,6 +26,7 @@ import lombok.*;
  *
  * @author wusheng
  */
+@ToString
 public class ConfigTable {
     @Getter
     private List<ConfigItem> items = new ArrayList<>();
@@ -36,6 +37,7 @@ public class ConfigTable {
 
     @Getter
     @Setter
+    @ToString
     public static class ConfigItem {
         private String name;
         private String value;
diff --git a/oap-server/server-configuration/configuration-nacos/pom.xml b/oap-server/server-configuration/configuration-nacos/pom.xml
new file mode 100644
index 0000000..8c8816d
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/pom.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>server-configuration</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.2.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>configuration-nacos</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>configuration-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>library-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.nacos</groupId>
+            <artifactId>nacos-client</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>io.fabric8</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <configuration>
+                    <sourceMode>all</sourceMode>
+                    <showLogs>true</showLogs>
+                    <logDate>default</logDate>
+                    <verbose>true</verbose>
+                    <imagePullPolicy>Always</imagePullPolicy>
+                    <autoCreateCustomNetworks>true</autoCreateCustomNetworks>
+                    <images>
+                        <image>
+                            <name>mysql:5.7</name>
+                            <alias>nacos-dynamic-configuration-integration-test-mysql</alias>
+                            <run>
+                                <network>
+                                    <name>test-network</name>
+                                    <alias>mysql</alias>
+                                </network>
+                                <env>
+                                    <MYSQL_MASTER_SERVICE_HOST>127.0.0.1</MYSQL_MASTER_SERVICE_HOST>
+                                    <MYSQL_ALLOW_EMPTY_PASSWORD>yes</MYSQL_ALLOW_EMPTY_PASSWORD>
+                                </env>
+                                <namingStrategy>none</namingStrategy>
+                                <ports>
+                                    <port>3307:3306</port>
+                                </ports>
+                                <volumes>
+                                    <bind>
+                                        <volume>
+                                            src/test/resources/docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
+                                        </volume>
+                                    </bind>
+                                </volumes>
+                                <wait>
+                                    <log>ready for connections</log>
+                                    <time>30000</time>
+                                </wait>
+                            </run>
+                        </image>
+                        <image>
+                            <name>nacos/nacos-server:${nacos.version}</name>
+                            <alias>nacos-dynamic-configuration-integration-test-nacos</alias>
+                            <run>
+                                <network>
+                                    <name>test-network</name>
+                                    <alias>nacos</alias>
+                                </network>
+                                <env>
+                                    <MODE>standalone</MODE>
+                                    <MYSQL_MASTER_SERVICE_HOST>mysql</MYSQL_MASTER_SERVICE_HOST>
+                                    <MYSQL_MASTER_SERVICE_DB_NAME>test</MYSQL_MASTER_SERVICE_DB_NAME>
+                                    <MYSQL_MASTER_SERVICE_PORT>3307</MYSQL_MASTER_SERVICE_PORT>
+                                </env>
+                                <namingStrategy>none</namingStrategy>
+                                <dependsOn>
+                                    <container>nacos-dynamic-configuration-integration-test-mysql</container>
+                                </dependsOn>
+                                <links>
+                                    <link>nacos-dynamic-configuration-integration-test-mysql</link>
+                                </links>
+                                <ports>
+                                    <port>8848:8848</port>
+                                </ports>
+                                <wait>
+                                    <log>Nacos started successfully</log>
+                                    <time>60000</time>
+                                </wait>
+                            </run>
+                        </image>
+                    </images>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>start</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>start</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>stop</id>
+                        <phase>post-integration-test</phase>
+                        <goals>
+                            <goal>stop</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegister.java b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegister.java
new file mode 100644
index 0000000..561e974
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegister.java
@@ -0,0 +1,132 @@
+/*
+ * 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.skywalking.oap.server.configuration.nacos;
+
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
+import org.apache.skywalking.oap.server.configuration.api.ConfigWatcherRegister;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+
+/**
+ * @author kezhenxu94
+ */
+public class NacosConfigWatcherRegister extends ConfigWatcherRegister {
+    private static final Logger LOGGER = LoggerFactory.getLogger(NacosConfigWatcherRegister.class);
+
+    private final NacosServerSettings settings;
+    private final ConfigService configService;
+    private final Map<String, Optional<String>> configItemKeyedByName;
+    private final Map<String, Listener> listenersByKey;
+
+    public NacosConfigWatcherRegister(NacosServerSettings settings) throws NacosException {
+        super(settings.getPeriod());
+
+        this.settings = settings;
+        this.configItemKeyedByName = new ConcurrentHashMap<>();
+        this.listenersByKey = new ConcurrentHashMap<>();
+
+        final int port = this.settings.getPort();
+        final String serverAddr = this.settings.getServerAddr();
+
+        final Properties properties = new Properties();
+        properties.put("serverAddr", serverAddr + ":" + port);
+        this.configService = NacosFactory.createConfigService(properties);
+    }
+
+    @Override
+    public ConfigTable readConfig(Set<String> keys) {
+        removeUninterestedKeys(keys);
+        registerKeyListeners(keys);
+
+        final ConfigTable table = new ConfigTable();
+
+        for (Map.Entry<String, Optional<String>> entry : configItemKeyedByName.entrySet()) {
+            final String key = entry.getKey();
+            final Optional<String> value = entry.getValue();
+
+            if (value.isPresent()) {
+                table.add(new ConfigTable.ConfigItem(key, value.get()));
+            } else {
+                table.add(new ConfigTable.ConfigItem(key, null));
+            }
+        }
+
+        return table;
+    }
+
+    private void registerKeyListeners(final Set<String> keys) {
+        final String group = settings.getGroup();
+
+        for (final String dataId : keys) {
+            if (listenersByKey.containsKey(dataId)) {
+                continue;
+            }
+            try {
+                listenersByKey.putIfAbsent(dataId, new Listener() {
+                    @Override
+                    public Executor getExecutor() {
+                        return null;
+                    }
+
+                    @Override
+                    public void receiveConfigInfo(String configInfo) {
+                        onDataIdValueChanged(dataId, configInfo);
+                    }
+                });
+                configService.addListener(dataId, group, listenersByKey.get(dataId));
+
+                // the key is newly added, read the config for the first time
+                final String config = configService.getConfig(dataId, group, 1000);
+                onDataIdValueChanged(dataId, config);
+            } catch (NacosException e) {
+                LOGGER.warn("Failed to register Nacos listener for dataId: {}", dataId);
+            }
+        }
+    }
+
+    private void removeUninterestedKeys(final Set<String> interestedKeys) {
+        final String group = settings.getGroup();
+
+        final Set<String> uninterestedKeys = new HashSet<>(listenersByKey.keySet());
+        uninterestedKeys.removeAll(interestedKeys);
+
+        uninterestedKeys.forEach(k -> {
+            final Listener listener = listenersByKey.remove(k);
+            if (listener != null) {
+                configService.removeListener(k, group, listener);
+            }
+        });
+    }
+
+    void onDataIdValueChanged(String dataId, String configInfo) {
+        if (LOGGER.isInfoEnabled()) {
+            LOGGER.info("Nacos config changed: {}: {}", dataId, configInfo);
+        }
+
+        configItemKeyedByName.put(dataId, Optional.ofNullable(configInfo));
+    }
+}
diff --git a/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationProvider.java b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationProvider.java
new file mode 100644
index 0000000..74ecb4d
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationProvider.java
@@ -0,0 +1,68 @@
+/*
+ * 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.skywalking.oap.server.configuration.nacos;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.google.common.base.Strings;
+import org.apache.skywalking.oap.server.configuration.api.AbstractConfigurationProvider;
+import org.apache.skywalking.oap.server.configuration.api.ConfigWatcherRegister;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+import org.apache.skywalking.oap.server.library.module.ModuleStartException;
+
+/**
+ * Get configuration from Nacos.
+ *
+ * @author kezhenxu94
+ */
+public class NacosConfigurationProvider extends AbstractConfigurationProvider {
+    private NacosServerSettings settings;
+
+    public NacosConfigurationProvider() {
+        settings = new NacosServerSettings();
+    }
+
+    @Override
+    public String name() {
+        return "nacos";
+    }
+
+    @Override
+    public ModuleConfig createConfigBeanIfAbsent() {
+        return settings;
+    }
+
+    @Override
+    protected ConfigWatcherRegister initConfigReader() throws ModuleStartException {
+        if (Strings.isNullOrEmpty(settings.getServerAddr())) {
+            throw new ModuleStartException("Nacos serverAddr cannot be null or empty.");
+        }
+        if (settings.getPort() <= 0) {
+            throw new ModuleStartException("Nacos port must be positive integer.");
+        }
+        if (Strings.isNullOrEmpty(settings.getGroup())) {
+            throw new ModuleStartException("Nacos group cannot be null or empty.");
+        }
+
+        try {
+            return new NacosConfigWatcherRegister(settings);
+        } catch (NacosException e) {
+            throw new ModuleStartException(e.getMessage(), e);
+        }
+    }
+}
diff --git a/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosServerSettings.java b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosServerSettings.java
new file mode 100644
index 0000000..74ab960
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosServerSettings.java
@@ -0,0 +1,79 @@
+/*
+ * 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.skywalking.oap.server.configuration.nacos;
+
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+
+/**
+ * @author kezhenxu94
+ */
+public class NacosServerSettings extends ModuleConfig {
+    private String clusterName = "default";
+    private String serverAddr;
+    private int port = 8848;
+    private String group;
+    private int period = 60;
+
+    public String getClusterName() {
+        return clusterName;
+    }
+
+    public void setClusterName(String clusterName) {
+        this.clusterName = clusterName;
+    }
+
+    public String getServerAddr() {
+        return serverAddr;
+    }
+
+    public void setServerAddr(String serverAddr) {
+        this.serverAddr = serverAddr;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+
+    public int getPeriod() {
+        return period;
+    }
+
+    public void setPeriod(int period) {
+        this.period = period;
+    }
+
+    public String toString() {
+        return "NacosServerSettings(clusterName=" + this.getClusterName()
+            + ", serverAddr=" + this.getServerAddr()
+            + ", group=" + this.getGroup()
+            + ", period=" + this.getPeriod() + ")";
+    }
+}
diff --git a/oap-server/server-configuration/configuration-nacos/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-configuration/configuration-nacos/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..d3fbbfc
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+#
+
+org.apache.skywalking.oap.server.configuration.nacos.NacosConfigurationProvider
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/ITNacosConfigurationTest.java b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/ITNacosConfigurationTest.java
new file mode 100644
index 0000000..97f711e
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/ITNacosConfigurationTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.skywalking.oap.server.configuration.nacos;
+
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+import org.apache.skywalking.apm.util.PropertyPlaceholderHelper;
+import org.apache.skywalking.oap.server.library.module.ApplicationConfiguration;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+import org.apache.skywalking.oap.server.library.util.ResourceUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author kezhenxu94
+ */
+public class ITNacosConfigurationTest {
+    private final Yaml yaml = new Yaml();
+
+    private NacosConfigurationTestProvider provider;
+
+    @Before
+    public void setUp() throws Exception {
+        final ApplicationConfiguration applicationConfiguration = new ApplicationConfiguration();
+        loadConfig(applicationConfiguration);
+
+        final ModuleManager moduleManager = new ModuleManager();
+        moduleManager.init(applicationConfiguration);
+
+        provider =
+            (NacosConfigurationTestProvider) moduleManager
+                .find(NacosConfigurationTestModule.NAME)
+                .provider();
+
+        assertNotNull(provider);
+    }
+
+    @SuppressWarnings("StatementWithEmptyBody")
+    @Test(timeout = 10000)
+    public void shouldReadUpdated() throws NacosException {
+        assertNull(provider.watcher.value());
+
+        final Properties properties = new Properties();
+        properties.put("serverAddr", "localhost:8848");
+        final ConfigService configService = NacosFactory.createConfigService(properties);
+        assertTrue(configService.publishConfig("test-module.default.testKey", "skywalking", "500"));
+
+        for (String v = provider.watcher.value(); v == null; v = provider.watcher.value()) {
+        }
+
+        assertEquals("500", provider.watcher.value());
+
+        assertTrue(configService.removeConfig("test-module.default.testKey", "skywalking"));
+
+        for (String v = provider.watcher.value(); v != null; v = provider.watcher.value()) {
+        }
+
+        assertNull(provider.watcher.value());
+    }
+
+    @SuppressWarnings("unchecked")
+    private void loadConfig(ApplicationConfiguration configuration) throws FileNotFoundException {
+        Reader applicationReader = ResourceUtils.read("application.yml");
+        Map<String, Map<String, Map<String, ?>>> moduleConfig = yaml.loadAs(applicationReader, Map.class);
+        if (CollectionUtils.isNotEmpty(moduleConfig)) {
+            moduleConfig.forEach((moduleName, providerConfig) -> {
+                if (providerConfig.size() > 0) {
+                    ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.addModule(moduleName);
+                    providerConfig.forEach((name, propertiesConfig) -> {
+                        Properties properties = new Properties();
+                        if (propertiesConfig != null) {
+                            propertiesConfig.forEach((key, value) -> {
+                                properties.put(key, value);
+                                final Object replaceValue = yaml.load(PropertyPlaceholderHelper.INSTANCE
+                                    .replacePlaceholders(value + "", properties));
+                                if (replaceValue != null) {
+                                    properties.replace(key, replaceValue);
+                                }
+                            });
+                        }
+                        moduleConfiguration.addProviderConfiguration(name, properties);
+                    });
+                }
+            });
+        }
+    }
+}
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegisterTest.java b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegisterTest.java
new file mode 100644
index 0000000..897a324
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegisterTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.skywalking.oap.server.configuration.nacos;
+
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.google.common.collect.Sets;
+import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.*;
+
+/**
+ * @author kezhenxu94
+ */
+public class NacosConfigWatcherRegisterTest {
+    @Test
+    public void shouldReadConfigs() throws NacosException {
+        final String group = "skywalking";
+        final String testKey1 = "receiver-trace.default.slowDBAccessThreshold";
+        final String testVal1 = "test";
+        final String testKey2 = "testKey";
+        final String testVal2 = "testVal";
+
+        final NacosServerSettings mockSettings = mock(NacosServerSettings.class);
+        when(mockSettings.getGroup()).thenReturn(group);
+
+        final NacosConfigWatcherRegister mockRegister = spy(new NacosConfigWatcherRegister(mockSettings));
+        final ConfigService mockConfigService = mock(ConfigService.class);
+        when(mockConfigService.getConfig(testKey1, group, 1000)).thenReturn(testVal1);
+        when(mockConfigService.getConfig(testKey2, group, 1000)).thenReturn(testVal2);
+
+        Whitebox.setInternalState(mockRegister, "configService", mockConfigService);
+
+        final ConfigTable configTable = mockRegister.readConfig(Sets.newHashSet(testKey1, testKey2));
+
+        assertEquals(2, configTable.getItems().size());
+        Map<String, String> kvs = new HashMap<>();
+        for (ConfigTable.ConfigItem item : configTable.getItems()) {
+            kvs.put(item.getName(), item.getValue());
+        }
+        assertEquals(testVal1, kvs.get(testKey1));
+        assertEquals(testVal2, kvs.get(testKey2));
+    }
+}
diff --git a/oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.java
similarity index 59%
copy from oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java
copy to oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.java
index 742f44f..3990c93 100644
--- a/oap-server/server-configuration/configuration-api/src/main/java/org/apache/skywalking/oap/server/configuration/api/ConfigTable.java
+++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.java
@@ -16,33 +16,22 @@
  *
  */
 
-package org.apache.skywalking.oap.server.configuration.api;
+package org.apache.skywalking.oap.server.configuration.nacos;
 
-import java.util.*;
-import lombok.*;
+import org.apache.skywalking.oap.server.library.module.ModuleDefine;
 
 /**
- * ConfigTable contains all config.
- *
- * @author wusheng
+ * @author kezhenxu94
  */
-public class ConfigTable {
-    @Getter
-    private List<ConfigItem> items = new ArrayList<>();
+public class NacosConfigurationTestModule extends ModuleDefine {
+    public static final String NAME = "test-module";
 
-    public void add(ConfigItem item) {
-        items.add(item);
+    public NacosConfigurationTestModule() {
+        super(NAME);
     }
 
-    @Getter
-    @Setter
-    public static class ConfigItem {
-        private String name;
-        private String value;
-
-        public ConfigItem(String name, String value) {
-            this.name = name;
-            this.value = value;
-        }
+    @Override
+    public Class[] services() {
+        return new Class[0];
     }
 }
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestProvider.java b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestProvider.java
new file mode 100644
index 0000000..1434202
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestProvider.java
@@ -0,0 +1,93 @@
+/*
+ * 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.skywalking.oap.server.configuration.nacos;
+
+import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
+import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
+import org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
+import org.apache.skywalking.oap.server.library.module.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author kezhenxu94
+ */
+public class NacosConfigurationTestProvider extends ModuleProvider {
+    private static final Logger LOGGER = LoggerFactory.getLogger(NacosConfigurationProvider.class);
+
+    ConfigChangeWatcher watcher;
+
+    @Override
+    public String name() {
+        return "default";
+    }
+
+    @Override
+    public Class<? extends ModuleDefine> module() {
+        return NacosConfigurationTestModule.class;
+    }
+
+    @Override
+    public ModuleConfig createConfigBeanIfAbsent() {
+        return new ModuleConfig() {
+        };
+    }
+
+    @Override
+    public void prepare() throws ServiceNotProvidedException, ModuleStartException {
+        watcher = new ConfigChangeWatcher(NacosConfigurationTestModule.NAME, this, "testKey") {
+            private volatile String testValue;
+
+            @Override
+            public void notify(ConfigChangeWatcher.ConfigChangeEvent value) {
+                LOGGER.info("ConfigChangeWatcher.ConfigChangeEvent: {}", value);
+                if (EventType.DELETE.equals(value.getEventType())) {
+                    testValue = null;
+                } else {
+                    testValue = value.getNewValue();
+                }
+            }
+
+            @Override
+            public String value() {
+                return testValue;
+            }
+        };
+    }
+
+    @Override
+    public void start() throws ServiceNotProvidedException, ModuleStartException {
+        getManager().find(ConfigurationModule.NAME)
+            .provider()
+            .getService(DynamicConfigurationService.class)
+            .registerConfigChangeWatcher(watcher);
+    }
+
+    @Override
+    public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException {
+
+    }
+
+    @Override
+    public String[] requiredModules() {
+        return new String[] {
+            ConfigurationModule.NAME
+        };
+    }
+}
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine b/oap-server/server-configuration/configuration-nacos/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
new file mode 100644
index 0000000..9448151
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+#
+
+org.apache.skywalking.oap.server.configuration.api.ConfigurationModule
+org.apache.skywalking.oap.server.configuration.nacos.NacosConfigurationTestModule
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-configuration/configuration-nacos/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..72ce82e
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+#
+
+org.apache.skywalking.oap.server.configuration.nacos.NacosConfigurationTestProvider
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/resources/application.yml b/oap-server/server-configuration/configuration-nacos/src/test/resources/application.yml
new file mode 100644
index 0000000..b1e120f
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/resources/application.yml
@@ -0,0 +1,37 @@
+# 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.
+
+test-module:
+  default:
+    testKey: 300
+
+
+configuration:
+  nacos:
+    # Nacos Server Host
+    serverAddr: localhost
+    # Nacos Server Port
+    port: 8848
+    # Nacos Configuration Group
+    group: 'skywalking'
+    # Dynamically configured keys
+    dataIds:
+      - test-module.default.testKey
+      # - other-key
+    # Unit seconds, sync period. Default fetch every 60 seconds.
+    period: 1
+    # the name of current cluster, set the name if you want to upstream system known.
+    clusterName: "default"
diff --git a/oap-server/server-configuration/configuration-nacos/src/test/resources/docker/docker-entrypoint-initdb.d/nacos-mysql.sql b/oap-server/server-configuration/configuration-nacos/src/test/resources/docker/docker-entrypoint-initdb.d/nacos-mysql.sql
new file mode 100644
index 0000000..46b19c3
--- /dev/null
+++ b/oap-server/server-configuration/configuration-nacos/src/test/resources/docker/docker-entrypoint-initdb.d/nacos-mysql.sql
@@ -0,0 +1,213 @@
+--
+-- 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.
+--
+
+CREATE DATABASE test DEFAULT CHARACTER SET = 'utf8';
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table_name = config_info   */
+/******************************************/
+CREATE TABLE `config_info` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `data_id` varchar(255) NOT NULL,
+  `group_id` varchar(255) DEFAULT NULL,
+  `content` longtext NOT NULL,
+  `md5` varchar(32) DEFAULT NULL,
+  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `src_user` text,
+  `src_ip` varchar(20) DEFAULT NULL,
+  `app_name` varchar(128) DEFAULT NULL,
+  `tenant_id` varchar(128) DEFAULT '',
+  `c_desc` varchar(256) DEFAULT NULL,
+  `c_use` varchar(64) DEFAULT NULL,
+  `effect` varchar(64) DEFAULT NULL,
+  `type` varchar(64) DEFAULT NULL,
+  `c_schema` text,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = config_info_aggr   */
+/******************************************/
+CREATE TABLE `config_info_aggr` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `data_id` varchar(255) NOT NULL,
+  `group_id` varchar(255) NOT NULL,
+  `datum_id` varchar(255) NOT NULL,
+  `content` longtext NOT NULL,
+  `gmt_modified` datetime NOT NULL,
+  `app_name` varchar(128) DEFAULT NULL,
+  `tenant_id` varchar(128) DEFAULT '',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = config_info_beta   */
+/******************************************/
+CREATE TABLE `config_info_beta` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `data_id` varchar(255) NOT NULL,
+  `group_id` varchar(128) NOT NULL,
+  `app_name` varchar(128) DEFAULT NULL,
+  `content` longtext NOT NULL,
+  `beta_ips` varchar(1024) DEFAULT NULL,
+  `md5` varchar(32) DEFAULT NULL,
+  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `src_user` text,
+  `src_ip` varchar(20) DEFAULT NULL,
+  `tenant_id` varchar(128) DEFAULT '',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = config_info_tag   */
+/******************************************/
+CREATE TABLE `config_info_tag` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `data_id` varchar(255) NOT NULL,
+  `group_id` varchar(128) NOT NULL,
+  `tenant_id` varchar(128) DEFAULT '',
+  `tag_id` varchar(128) NOT NULL,
+  `app_name` varchar(128) DEFAULT NULL,
+  `content` longtext NOT NULL,
+  `md5` varchar(32) DEFAULT NULL,
+  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `src_user` text,
+  `src_ip` varchar(20) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = config_tags_relation   */
+/******************************************/
+CREATE TABLE `config_tags_relation` (
+  `id` bigint(20) NOT NULL,
+  `tag_name` varchar(128) NOT NULL,
+  `tag_type` varchar(64) DEFAULT NULL,
+  `data_id` varchar(255) NOT NULL,
+  `group_id` varchar(128) NOT NULL,
+  `tenant_id` varchar(128) DEFAULT '',
+  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`nid`),
+  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
+  KEY `idx_tenant_id` (`tenant_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = group_capacity   */
+/******************************************/
+CREATE TABLE `group_capacity` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `group_id` varchar(128) NOT NULL DEFAULT '',
+  `quota` int(10) unsigned NOT NULL DEFAULT '0',
+  `usage` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_size` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0',
+  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_group_id` (`group_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = his_config_info   */
+/******************************************/
+CREATE TABLE `his_config_info` (
+  `id` bigint(64) unsigned NOT NULL,
+  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `data_id` varchar(255) NOT NULL,
+  `group_id` varchar(128) NOT NULL,
+  `app_name` varchar(128) DEFAULT NULL,
+  `content` longtext NOT NULL,
+  `md5` varchar(32) DEFAULT NULL,
+  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `src_user` text,
+  `src_ip` varchar(20) DEFAULT NULL,
+  `op_type` char(10) DEFAULT NULL,
+  `tenant_id` varchar(128) DEFAULT '',
+  PRIMARY KEY (`nid`),
+  KEY `idx_gmt_create` (`gmt_create`),
+  KEY `idx_gmt_modified` (`gmt_modified`),
+  KEY `idx_did` (`data_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+
+/******************************************/
+/*   database name = nacos_config   */
+/*   table name = tenant_capacity   */
+/******************************************/
+CREATE TABLE `tenant_capacity` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `tenant_id` varchar(128) NOT NULL DEFAULT '',
+  `quota` int(10) unsigned NOT NULL DEFAULT '0',
+  `usage` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_size` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0',
+  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0',
+  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+
+CREATE TABLE `tenant_info` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `kp` varchar(128) NOT NULL,
+  `tenant_id` varchar(128) default '',
+  `tenant_name` varchar(128) default '',
+  `tenant_desc` varchar(256) DEFAULT NULL,
+  `create_source` varchar(32) DEFAULT NULL,
+  `gmt_create` bigint(20) NOT NULL,
+  `gmt_modified` bigint(20) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
+  KEY `idx_tenant_id` (`tenant_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+CREATE TABLE users (
+	username varchar(50) NOT NULL PRIMARY KEY,
+	password varchar(500) NOT NULL,
+	enabled boolean NOT NULL
+);
+
+CREATE TABLE roles (
+	username varchar(50) NOT NULL,
+	role varchar(50) NOT NULL
+);
+
+INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
+
+INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
diff --git a/oap-server/server-configuration/pom.xml b/oap-server/server-configuration/pom.xml
index b161e51..60eefcd 100644
--- a/oap-server/server-configuration/pom.xml
+++ b/oap-server/server-configuration/pom.xml
@@ -32,6 +32,7 @@
     <modules>
         <module>configuration-api</module>
         <module>grpc-configuration-sync</module>
+        <module>configuration-nacos</module>
     </modules>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/oap-server/server-starter/pom.xml b/oap-server/server-starter/pom.xml
index c80be5b..b4fed32 100644
--- a/oap-server/server-starter/pom.xml
+++ b/oap-server/server-starter/pom.xml
@@ -178,6 +178,11 @@
             <artifactId>grpc-configuration-sync</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>configuration-nacos</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
     <build>
         <finalName>skywalking-oap</finalName>
diff --git a/oap-server/server-starter/src/main/assembly/application.yml b/oap-server/server-starter/src/main/assembly/application.yml
index e0c0c16..f6b0133 100644
--- a/oap-server/server-starter/src/main/assembly/application.yml
+++ b/oap-server/server-starter/src/main/assembly/application.yml
@@ -125,6 +125,17 @@ telemetry:
   none:
 configuration:
   none:
+#  nacos:
+#    # Nacos Server Host
+#    serverAddr: 127.0.0.1
+#    # Nacos Server Port
+#    port: 8848
+#    # Nacos Configuration Group
+#    group: 'skywalking'
+#    # Unit seconds, sync period. Default fetch every 60 seconds.
+#    period : 60
+#    # the name of current cluster, set the name if you want to upstream system known.
+#    clusterName: "default"
 #exporter:
 #  grpc:
 #    targetHost: ${SW_EXPORTER_GRPC_HOST:127.0.0.1}
diff --git a/oap-server/server-starter/src/main/resources/application.yml b/oap-server/server-starter/src/main/resources/application.yml
index e1940f6..ac640b0 100644
--- a/oap-server/server-starter/src/main/resources/application.yml
+++ b/oap-server/server-starter/src/main/resources/application.yml
@@ -131,6 +131,18 @@ telemetry:
     port: ${SW_TELEMETRY_PROMETHEUS_PORT:1234}
 configuration:
   none:
+#  nacos:
+#    # Nacos Server Host
+#    serverAddr: 127.0.0.1
+#    # Nacos Server Port
+#    port: 8848
+#    # Nacos Configuration Group
+#    group: 'skywalking'
+#    # Unit seconds, sync period. Default fetch every 60 seconds.
+#    period : 5
+#    # the name of current cluster, set the name if you want to upstream system known.
+#    clusterName: "default"
+
 #exporter:
 #  grpc:
 #    targetHost: ${SW_EXPORTER_GRPC_HOST:127.0.0.1}