diff --git a/docs/en/setup/backend/dynamic-config.md b/docs/en/setup/backend/dynamic-config.md
index 159134be3258082475f4513fbe230a38c1343c15..c38b2c1130c4815a47137ef1f7a650abbbd30a93 100644
--- a/docs/en/setup/backend/dynamic-config.md
+++ b/docs/en/setup/backend/dynamic-config.md
@@ -33,7 +33,7 @@ configuration:
## Dynamic Configuration Apollo Implementation
-[Apollo](https://github.com/ctripcorp/apollo/) is also supported in DCS, to use it, just configured as follows:
+[Apollo](https://github.com/ctripcorp/apollo/) is also supported as DCC(Dynamic Configuration Center), to use it, just configured as follows:
```yaml
configuration:
@@ -47,7 +47,7 @@ configuration:
## Dynamic Configuration Nacos Implementation
-[Nacos](https://github.com/alibaba/nacos) is also supported in DCS, to use it, please configure as follows:
+[Nacos](https://github.com/alibaba/nacos) is also supported as DCC(Dynamic Configuration Center), to use it, please configure as follows:
```yaml
configuration:
@@ -64,8 +64,24 @@ configuration:
clusterName: "default"
```
+
+## Dynamic Configuration Zookeeper Implementation
+
+[Zookeeper](https://github.com/apache/zookeeper) is also supported as DCC(Dynamic Configuration Center), to use it, please configure as follows:
+
+```yaml
+configuration:
+ zookeeper:
+ period : 60 # Unit seconds, sync period. Default fetch every 60 seconds.
+ nameSpace: /default
+ hostPort: localhost:2181
+ #Retry Policy
+ baseSleepTimeMs: 1000 # initial amount of time to wait between retries
+ maxRetries: 3 # max number of times to retry
+```
+
## 3rd party Configuration Center
We are welcome contributions to implement this module provider to support popular configuration center,
-such as Zookeeper, etcd, Consul. Submit issue to discuss.
+such as Consul. Submit issue to discuss.
diff --git a/oap-server/pom.xml b/oap-server/pom.xml
index 47afc3ab71f28f58d7cb288e6d744b746bfe357e..9ed66e55028bfa91ce0b2040fb42a421b2b8e0d7 100644
--- a/oap-server/pom.xml
+++ b/oap-server/pom.xml
@@ -79,6 +79,8 @@
1.4.00.30.01.0.0
+ 4.0.1
+ 2.12.02.17.0v3.2.3
@@ -378,6 +380,33 @@
etcd4j${etcd4j.version}
+
+ org.apache.curator
+ curator-x-discovery
+ ${curator.version}
+
+
+ com.google.guava
+ guava
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+ org.apache.curator
+ curator-test
+ ${curator-test.version}
+
+
+ com.google.guava
+ guava
+
+
+ test
+
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml
index 7dccd366904509b9472317a7ce397d3a04d1bf04..5994d6a613184dcdbe4d05bcbb2016d7f0a573c9 100644
--- a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml
@@ -30,7 +30,6 @@
UTF-8
- 4.0.1
@@ -46,30 +45,10 @@
org.apache.curatorcurator-x-discovery
- ${curator.version}
-
-
- com.google.guava
- guava
-
-
- org.slf4j
- slf4j-api
-
- org.apache.curatorcurator-test
- 2.12.0
-
-
-
- com.google.guava
- guava
-
-
- test
\ No newline at end of file
diff --git a/oap-server/server-configuration/configuration-zookeeper/pom.xml b/oap-server/server-configuration/configuration-zookeeper/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..161b1b0ce4f1b4bf4962a218fdfc6ef820071800
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/pom.xml
@@ -0,0 +1,146 @@
+
+
+
+
+
+ server-configuration
+ org.apache.skywalking
+ 6.2.0-SNAPSHOT
+
+ 4.0.0
+
+ configuration-zookeeper
+
+
+ 3.5
+
+
+
+
+ org.apache.skywalking
+ configuration-api
+ ${project.version}
+
+
+ org.apache.skywalking
+ library-client
+ ${project.version}
+
+
+ org.apache.skywalking
+ cluster-zookeeper-plugin
+ ${project.version}
+
+
+
+
+
+ CI-with-IT
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+ all
+ default
+ true
+ true
+ IfNotPresent
+
+
+
+ prepare-zookeeper
+ pre-integration-test
+
+ start
+
+
+
+
+ zookeeper:${zookeeper.image.version}
+ zookeeper-dynamic-configuration-integration-test-zookeeper
+
+
+ zk-port:2181
+
+
+ binding to port
+
+
+
+
+
+
+
+
+ prepare-zookeeper-start
+ post-integration-test
+
+ stop
+
+
+
+
+
+ org.codehaus.gmaven
+ gmaven-plugin
+ ${gmaven-plugin.version}
+
+
+ add-default-properties
+ initialize
+
+ execute
+
+
+ 2.0
+
+ project.properties.setProperty('docker.hostname', 'localhost')
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ ${docker.hostname}:${zk-port}
+
+
+
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
+
+
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperConfigWatcherRegister.java b/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperConfigWatcherRegister.java
new file mode 100644
index 0000000000000000000000000000000000000000..08cf2791a48d7d81bc774037c476660069ccb344
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperConfigWatcherRegister.java
@@ -0,0 +1,58 @@
+/*
+ * 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.zookeeper;
+
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.PathChildrenCache;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
+import org.apache.skywalking.oap.server.configuration.api.ConfigWatcherRegister;
+
+import java.util.Set;
+
+/**
+ * @author zhaoyuguang
+ */
+public class ZookeeperConfigWatcherRegister extends ConfigWatcherRegister {
+ private final PathChildrenCache childrenCache;
+ private final String prefix;
+
+ public ZookeeperConfigWatcherRegister(ZookeeperServerSettings settings) throws Exception {
+ super(settings.getPeriod());
+ prefix = settings.getNameSpace() + "/";
+ RetryPolicy retryPolicy = new ExponentialBackoffRetry(settings.getBaseSleepTimeMs(), settings.getMaxRetries());
+ CuratorFramework client = CuratorFrameworkFactory.newClient(settings.getHostPort(), retryPolicy);
+ client.start();
+ this.childrenCache = new PathChildrenCache(client, settings.getNameSpace(), true);
+ this.childrenCache.start();
+ }
+
+ @Override
+ public ConfigTable readConfig(Set keys) {
+ ConfigTable table = new ConfigTable();
+ keys.forEach(s -> {
+ ChildData data = this.childrenCache.getCurrentData(this.prefix + s);
+ table.add(new ConfigTable.ConfigItem(s, data == null ? null : new String(data.getData())));
+ });
+ return table;
+ }
+}
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperConfigurationProvider.java b/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperConfigurationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba87d7bb170067a4ffa3c36c90d3fa45ae739737
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperConfigurationProvider.java
@@ -0,0 +1,64 @@
+/*
+ * 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.zookeeper;
+
+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 Zookeeper.
+ *
+ * @author zhaoyuguang
+ */
+public class ZookeeperConfigurationProvider extends AbstractConfigurationProvider {
+ private ZookeeperServerSettings settings;
+
+ public ZookeeperConfigurationProvider() {
+ settings = new ZookeeperServerSettings();
+ }
+
+ @Override
+ public String name() {
+ return "zookeeper";
+ }
+
+ @Override
+ public ModuleConfig createConfigBeanIfAbsent() {
+ return settings;
+ }
+
+ @Override
+ protected ConfigWatcherRegister initConfigReader() throws ModuleStartException {
+ if (Strings.isNullOrEmpty(settings.getHostPort())) {
+ throw new ModuleStartException("Zookeeper hostPort cannot be null or empty.");
+ }
+ if (Strings.isNullOrEmpty(settings.getNameSpace())) {
+ throw new ModuleStartException("Zookeeper nameSpace cannot be null or empty.");
+ }
+
+ try {
+ return new ZookeeperConfigWatcherRegister(settings);
+ } catch (Exception e) {
+ throw new ModuleStartException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperServerSettings.java b/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperServerSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..9247a645000f7375b4b3913dd38e8367ea9221c7
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/main/java/org/apache/skywalking/oap/server/configuration/zookeeper/ZookeeperServerSettings.java
@@ -0,0 +1,45 @@
+/*
+ * 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.zookeeper;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+
+/**
+ * @author zhaoyuguang
+ */
+@Getter
+@Setter
+public class ZookeeperServerSettings extends ModuleConfig {
+ private String nameSpace = "/default";
+ private String hostPort;
+ private int baseSleepTimeMs = 1000;
+ private int maxRetries = 3;
+ private int period = 60;
+
+ @Override
+ public String toString() {
+ return "ZookeeperServerSettings(nameSpace=" + this.getNameSpace()
+ + ", hostPort=" + this.getHostPort()
+ + ", baseSleepTimeMs=" + this.getBaseSleepTimeMs()
+ + ", maxRetries=" + this.getMaxRetries()
+ + ", period=" + this.getPeriod() + ")";
+ }
+}
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-configuration/configuration-zookeeper/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000000000000000000000000000000000000..171379ff530644f6c871ddd1f4db2e277809bc16
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,18 @@
+#
+# 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.zookeeper.ZookeeperConfigurationProvider
\ No newline at end of file
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/ITZookeeperConfigurationTest.java b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/ITZookeeperConfigurationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f05a4830decb950c32582a4d9b110c024b99f857
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/ITZookeeperConfigurationTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.zookeeper.it;
+
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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 zhaoyuguang
+ */
+public class ITZookeeperConfigurationTest {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ITZookeeperConfigurationTest.class);
+
+ private final Yaml yaml = new Yaml();
+
+ private MockZookeeperConfigurationProvider provider;
+
+ @Before
+ public void setUp() throws Exception {
+ final ApplicationConfiguration applicationConfiguration = new ApplicationConfiguration();
+ loadConfig(applicationConfiguration);
+
+ final ModuleManager moduleManager = new ModuleManager();
+ moduleManager.init(applicationConfiguration);
+
+ provider =
+ (MockZookeeperConfigurationProvider) moduleManager
+ .find(MockZookeeperConfigurationModule.NAME)
+ .provider();
+
+ assertNotNull(provider);
+ }
+
+ @SuppressWarnings("StatementWithEmptyBody")
+ @Test(timeout = 20000)
+ public void shouldReadUpdated() throws Exception {
+ String nameSpace = "/default";
+ String key = "test-module.default.testKey";
+ assertNull(provider.watcher.value());
+
+ String zkAddress = System.getProperty("zk.address");
+ LOGGER.info("zkAddress: " + zkAddress);
+
+ RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
+ CuratorFramework client = CuratorFrameworkFactory.newClient(zkAddress, retryPolicy);
+ client.start();
+
+ LOGGER.info("per path: " + nameSpace + "/" + key);
+
+ assertTrue(client.create().creatingParentsIfNeeded().forPath(nameSpace + "/" + key, "500".getBytes()) != null);
+
+ LOGGER.info("data: " + new String(client.getData().forPath(nameSpace + "/" + key)));
+
+ for (String v = provider.watcher.value(); v == null; v = provider.watcher.value()) {
+ }
+
+ assertTrue(client.delete().forPath(nameSpace + "/" + key) == null);
+
+ 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>> 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-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/MockZookeeperConfigurationModule.java b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/MockZookeeperConfigurationModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f9dcc764d29346a9fe2a39031bfae559a777851
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/MockZookeeperConfigurationModule.java
@@ -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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.configuration.zookeeper.it;
+
+import org.apache.skywalking.oap.server.library.module.ModuleDefine;
+
+/**
+ * @author zhaoyuguang
+ */
+public class MockZookeeperConfigurationModule extends ModuleDefine {
+ public static final String NAME = "test-module";
+
+ public MockZookeeperConfigurationModule() {
+ super(NAME);
+ }
+
+ @Override
+ public Class[] services() {
+ return new Class[0];
+ }
+}
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/MockZookeeperConfigurationProvider.java b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/MockZookeeperConfigurationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..5260d825e5b9082582e8bd891eb9b064649c2e95
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/it/MockZookeeperConfigurationProvider.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.zookeeper.it;
+
+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 zhaoyuguang
+ */
+public class MockZookeeperConfigurationProvider extends ModuleProvider {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MockZookeeperConfigurationProvider.class);
+
+ ConfigChangeWatcher watcher;
+
+ @Override
+ public String name() {
+ return "default";
+ }
+
+ @Override
+ public Class extends ModuleDefine> module() {
+ return MockZookeeperConfigurationModule.class;
+ }
+
+ @Override
+ public ModuleConfig createConfigBeanIfAbsent() {
+ return new ModuleConfig() {
+ };
+ }
+
+ @Override
+ public void prepare() throws ServiceNotProvidedException {
+ watcher = new ConfigChangeWatcher(MockZookeeperConfigurationModule.NAME, this, "testKey") {
+ private volatile String testValue;
+
+ @Override
+ public void notify(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 {
+ getManager().find(ConfigurationModule.NAME)
+ .provider()
+ .getService(DynamicConfigurationService.class)
+ .registerConfigChangeWatcher(watcher);
+ }
+
+ @Override
+ public void notifyAfterCompleted() throws ServiceNotProvidedException {
+
+ }
+
+ @Override
+ public String[] requiredModules() {
+ return new String[] {
+ ConfigurationModule.NAME
+ };
+ }
+}
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/ut/MockZookeeperConfigWatcherRegister.java b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/ut/MockZookeeperConfigWatcherRegister.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7fcfb05ffa814fe2d63b148ff6a89e19be58b19
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/ut/MockZookeeperConfigWatcherRegister.java
@@ -0,0 +1,51 @@
+/*
+ * 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.zookeeper.ut;
+
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.PathChildrenCache;
+import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
+import org.apache.skywalking.oap.server.configuration.api.ConfigWatcherRegister;
+import org.apache.skywalking.oap.server.configuration.zookeeper.ZookeeperServerSettings;
+
+import java.util.Set;
+
+/**
+ * @author zhaoyuguang
+ */
+
+public class MockZookeeperConfigWatcherRegister extends ConfigWatcherRegister {
+ private PathChildrenCache childrenCache;
+ private final String prefix;
+
+ public MockZookeeperConfigWatcherRegister(ZookeeperServerSettings settings) throws Exception {
+ super(settings.getPeriod());
+ prefix = settings.getNameSpace() + "/";
+ }
+
+ @Override
+ public ConfigTable readConfig(Set keys) {
+ ConfigTable table = new ConfigTable();
+ keys.forEach(s -> {
+ ChildData data = this.childrenCache.getCurrentData(this.prefix + s);
+ table.add(new ConfigTable.ConfigItem(s, data == null ? null : new String(data.getData())));
+ });
+ return table;
+ }
+}
\ No newline at end of file
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/ut/ZookeeperConfigWatcherRegisterTestCase.java b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/ut/ZookeeperConfigWatcherRegisterTestCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..fff9179b4c7ae6d1b1bc4a0d979ae1321eaf52eb
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/java/org/apache/skywalking/oap/server/configuration/zookeeper/ut/ZookeeperConfigWatcherRegisterTestCase.java
@@ -0,0 +1,57 @@
+/*
+ * 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.zookeeper.ut;
+
+import com.google.common.collect.Sets;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.PathChildrenCache;
+import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
+import org.apache.skywalking.oap.server.configuration.zookeeper.ZookeeperServerSettings;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.*;
+
+/**
+ * @author zhaoyuguang
+ */
+public class ZookeeperConfigWatcherRegisterTestCase {
+ @Test
+ public void TestCase() throws Exception {
+ final String nameSpace = "/default";
+ final String key = "receiver-trace.default.slowDBAccessThreshold";
+ final String value = "default:100,mongodb:50";
+
+ final ZookeeperServerSettings mockSettings = mock(ZookeeperServerSettings.class);
+ when(mockSettings.getNameSpace()).thenReturn(nameSpace);
+
+ final MockZookeeperConfigWatcherRegister mockRegister = spy(new MockZookeeperConfigWatcherRegister(mockSettings));
+ final PathChildrenCache mockPathChildrenCache = mock(PathChildrenCache.class);
+ when(mockPathChildrenCache.getCurrentData(nameSpace + "/" + key)).thenReturn(new ChildData(nameSpace + "/" + key, null, value.getBytes()));
+
+ Whitebox.setInternalState(mockRegister, "childrenCache", mockPathChildrenCache);
+
+ final ConfigTable configTable = mockRegister.readConfig(Sets.newHashSet(key));
+
+ assertEquals(1, configTable.getItems().size());
+ assertEquals(key, configTable.getItems().get(0).getName());
+ assertEquals(value, configTable.getItems().get(0).getValue());
+ }
+}
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine b/oap-server/server-configuration/configuration-zookeeper/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
new file mode 100644
index 0000000000000000000000000000000000000000..13042e3b0292ccf103f5da922f2aaf513833250c
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/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.zookeeper.it.MockZookeeperConfigurationModule
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-configuration/configuration-zookeeper/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000000000000000000000000000000000000..dbdba7418c2a3ece504c0368df134388db3462c0
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/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.zookeeper.it.MockZookeeperConfigurationProvider
\ No newline at end of file
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/resources/application.yml b/oap-server/server-configuration/configuration-zookeeper/src/test/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5981532b36740684f09354b50644bbfcbd03d15c
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/resources/application.yml
@@ -0,0 +1,27 @@
+# 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:
+ zookeeper:
+ period : 1 # Unit seconds, sync period. Default fetch every 60 seconds.
+ nameSpace: /default
+ hostPort: ${zk.address}
+ baseSleepTimeMs: 1000 # initial amount of time to wait between retries
+ maxRetries: 3 # max number of times to retry
diff --git a/oap-server/server-configuration/configuration-zookeeper/src/test/resources/log4j2.xml b/oap-server/server-configuration/configuration-zookeeper/src/test/resources/log4j2.xml
new file mode 100644
index 0000000000000000000000000000000000000000..89c81121eb842cc554470ae99acf38d2b7c48c85
--- /dev/null
+++ b/oap-server/server-configuration/configuration-zookeeper/src/test/resources/log4j2.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/oap-server/server-configuration/pom.xml b/oap-server/server-configuration/pom.xml
index 69f8f340ee5577ae48433e3eb64480c190758cc6..ff3111966bd31e2cd8c571504fc31817e18f980f 100644
--- a/oap-server/server-configuration/pom.xml
+++ b/oap-server/server-configuration/pom.xml
@@ -34,6 +34,7 @@
grpc-configuration-syncconfiguration-apolloconfiguration-nacos
+ configuration-zookeeperconfiguration-etcd
diff --git a/oap-server/server-starter/pom.xml b/oap-server/server-starter/pom.xml
index 1567c4991bbd77e55f3f76fce5450b63ae4aef8e..59c7defed99579aa920d2db6f7a45fc988e122f8 100644
--- a/oap-server/server-starter/pom.xml
+++ b/oap-server/server-starter/pom.xml
@@ -194,6 +194,11 @@
configuration-nacos${project.version}
+
+ org.apache.skywalking
+ configuration-zookeeper
+ ${project.version}
+ skywalking-oap
diff --git a/oap-server/server-starter/src/main/assembly/application.yml b/oap-server/server-starter/src/main/assembly/application.yml
index c009351cbed7c3adeabf9ee2b8cb5c5749edb82c..c5b01a363fd0ee5107b516a8ada176e37c32fff0 100644
--- a/oap-server/server-starter/src/main/assembly/application.yml
+++ b/oap-server/server-starter/src/main/assembly/application.yml
@@ -140,6 +140,13 @@ configuration:
# period : 60
# # the name of current cluster, set the name if you want to upstream system known.
# clusterName: "default"
+# zookeeper:
+# period : 60 # Unit seconds, sync period. Default fetch every 60 seconds.
+# nameSpace: /default
+# hostPort: localhost:2181
+# #Retry Policy
+# baseSleepTimeMs: 1000 # initial amount of time to wait between retries
+# maxRetries: 3 # max number of times to retry
#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 cb162e0248a7eb119c341e5ab87f8c687c3e61f3..7d513126c262bff00b8c07f12817b6a3cae40706 100644
--- a/oap-server/server-starter/src/main/resources/application.yml
+++ b/oap-server/server-starter/src/main/resources/application.yml
@@ -152,6 +152,13 @@ configuration:
# period : 5
# # the name of current cluster, set the name if you want to upstream system known.
# clusterName: "default"
+# zookeeper:
+# period : 60 # Unit seconds, sync period. Default fetch every 60 seconds.
+# nameSpace: /default
+# hostPort: localhost:2181
+# #Retry Policy
+# baseSleepTimeMs: 1000 # initial amount of time to wait between retries
+# maxRetries: 3 # max number of times to retry
#exporter:
# grpc: