diff --git a/docs/en/setup/backend/dynamic-config.md b/docs/en/setup/backend/dynamic-config.md index de13691fcaa153249e9d6feff889f1b7781f5681..c9b31678eec485d54b52c8fb3cd8eeffed1a64d6 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 f6e4752348d0c24289a911a5728e6531a1315c54..6a1ea521bb7e59dc6ddf38e7179b3f83b17c9334 100644 --- a/oap-server/pom.xml +++ b/oap-server/pom.xml @@ -78,6 +78,7 @@ 0.6.0 0.28.0 + 1.0.0 @@ -359,6 +360,11 @@ simpleclient ${simpleclient.version} + + com.alibaba.nacos + nacos-client + ${nacos.version} + @@ -396,4 +402,4 @@ - \ No newline at end of file + 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 15889ad145a862ccfc824ffe17a066880a62c1ac..3f6ee6056d6a362b36bbdd0c371f89d79ed8122d 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 @@ 4.0.0 cluster-nacos-plugin - - 1.0.0 - + org.apache.skywalking @@ -39,7 +37,6 @@ com.alibaba.nacos nacos-client - ${nacos.version} org.slf4j @@ -68,4 +65,4 @@ - \ No newline at end of file + 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 742f44f4a87775f0aad6928711f25122d889da67..c8988cbb82a23d059024d4f671cba7c37bf72063 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 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 0000000000000000000000000000000000000000..8c8816def6189558fad8ca4af34d519e566a109b --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/pom.xml @@ -0,0 +1,142 @@ + + + + + + server-configuration + org.apache.skywalking + 6.2.0-SNAPSHOT + + 4.0.0 + + configuration-nacos + + + + org.apache.skywalking + configuration-api + ${project.version} + + + org.apache.skywalking + library-client + ${project.version} + + + com.alibaba.nacos + nacos-client + + + + + + + io.fabric8 + docker-maven-plugin + + all + true + default + true + Always + true + + + mysql:5.7 + nacos-dynamic-configuration-integration-test-mysql + + + test-network + mysql + + + 127.0.0.1 + yes + + none + + 3307:3306 + + + + + src/test/resources/docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d + + + + + ready for connections + + + + + + nacos/nacos-server:${nacos.version} + nacos-dynamic-configuration-integration-test-nacos + + + test-network + nacos + + + standalone + mysql + test + 3307 + + none + + nacos-dynamic-configuration-integration-test-mysql + + + nacos-dynamic-configuration-integration-test-mysql + + + 8848:8848 + + + Nacos started successfully + + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + + 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 0000000000000000000000000000000000000000..561e974cd08d068c433d6a1c3a321ed3bb4e044b --- /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> configItemKeyedByName; + private final Map 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 keys) { + removeUninterestedKeys(keys); + registerKeyListeners(keys); + + final ConfigTable table = new ConfigTable(); + + for (Map.Entry> entry : configItemKeyedByName.entrySet()) { + final String key = entry.getKey(); + final Optional 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 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 interestedKeys) { + final String group = settings.getGroup(); + + final Set 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 0000000000000000000000000000000000000000..74ecb4dfa5dd61c2f80cfab6f4b88b848dc1645e --- /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 0000000000000000000000000000000000000000..74ab960401316cf84b5292eaa1088024d673f74f --- /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 0000000000000000000000000000000000000000..d3fbbfc8d2162a5b375c8587d32a6d697a31f9ed --- /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 0000000000000000000000000000000000000000..97f711e364bf8edfe7d4348028372195df3b2b1a --- /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>> 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 0000000000000000000000000000000000000000..897a324879748aa61609c6561461be202c4412bd --- /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 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-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.java b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.java new file mode 100644 index 0000000000000000000000000000000000000000..3990c93cf772cbadcd681fb9b833fffc7a75cf36 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.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.nacos; + +import org.apache.skywalking.oap.server.library.module.ModuleDefine; + +/** + * @author kezhenxu94 + */ +public class NacosConfigurationTestModule extends ModuleDefine { + public static final String NAME = "test-module"; + + public NacosConfigurationTestModule() { + super(NAME); + } + + @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 0000000000000000000000000000000000000000..14342029c5f4b880f4adcba80c0af227859bf96e --- /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 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 0000000000000000000000000000000000000000..9448151e6733701fc283e166fbe4a67b77dbb666 --- /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 0000000000000000000000000000000000000000..72ce82e5f79f27253c47c075ab18e61c8a71a4a7 --- /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 0000000000000000000000000000000000000000..b1e120fdbc5bf7145620fd4d4797c2c14b04de80 --- /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 0000000000000000000000000000000000000000..46b19c347a2e59f63278ef76da475237a6e254d4 --- /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 b161e518520308594151a21b22e2cc941c635769..60eefcd62ec9db8baf650b476c5007d218123ead 100644 --- a/oap-server/server-configuration/pom.xml +++ b/oap-server/server-configuration/pom.xml @@ -32,6 +32,7 @@ configuration-api grpc-configuration-sync + configuration-nacos - \ No newline at end of file + diff --git a/oap-server/server-starter/pom.xml b/oap-server/server-starter/pom.xml index c80be5b5f49efcca0a9373b2fef560646d9f4e22..b4fed322303148ef79ef7e9c412594053eaf8652 100644 --- a/oap-server/server-starter/pom.xml +++ b/oap-server/server-starter/pom.xml @@ -178,6 +178,11 @@ grpc-configuration-sync ${project.version} + + org.apache.skywalking + configuration-nacos + ${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 e0c0c16ccd9320adc4d8b7551d9e331fdca0a03b..f6b0133351c4dffa28cf3a634dd025aa232847e7 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 e1940f6cb349cd8f3f6e3a4c07e928f90693aa2c..ac640b029226672e70d3e2d81fb5d0ac317b5abc 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}