diff --git a/dist-material/release-docs/LICENSE b/dist-material/release-docs/LICENSE index 6175b968d..7acf03e83 100755 --- a/dist-material/release-docs/LICENSE +++ b/dist-material/release-docs/LICENSE @@ -308,6 +308,7 @@ The text of each license is the standard Apache 2.0 license. kubernetes-client 8.0.0: https://github.com/kubernetes-client/java, Apache 2.0 proto files from istio/istio: https://github.com/istio/istio Apache 2.0 proto files from istio/api: https://github.com/istio/api Apache 2.0 + nacos 1.3.1: https://github.com/alibaba/nacos, Apache 2.0 consul-client 1.2.6: https://github.com/rickfast/consul-client, Apache 2.0 okhttp 3.9.0: https://github.com/square/okhttp, Apache 2.0 prometheus client_java 0.6.0: https://github.com/prometheus/client_java, Apache 2.0 diff --git a/docs/en/setup/backend/backend-cluster.md b/docs/en/setup/backend/backend-cluster.md index b3fdd85e5..1f7c75ff2 100644 --- a/docs/en/setup/backend/backend-cluster.md +++ b/docs/en/setup/backend/backend-cluster.md @@ -10,7 +10,7 @@ with each other. by using k8s native APIs to manage cluster. - [Consul](#consul). Use Consul as backend cluster management implementor, to coordinate backend instances. - [Etcd](#etcd). Use Etcd to coordinate backend instances. - +- [Nacos](#nacos). Use Nacos to coordinate backend instances. In the `application.yml`, there're default configurations for the aforementioned coordinators under the section `cluster`, you can specify one of them in the `selector` property to enable it. @@ -91,3 +91,12 @@ cluster: selector: ${SW_CLUSTER:etcd} # other configurations ``` + +## Nacos +Set the **cluster/selector** to **nacos** in the yml to enable. + +```yaml +cluster: + selector: ${SW_CLUSTER:nacos} + # other configurations +``` \ No newline at end of file diff --git a/docs/en/setup/backend/dynamic-config.md b/docs/en/setup/backend/dynamic-config.md index e87971dbe..47284f7fd 100755 --- a/docs/en/setup/backend/dynamic-config.md +++ b/docs/en/setup/backend/dynamic-config.md @@ -119,4 +119,25 @@ configuration: namespace: ${SW_CLUSTER_K8S_NAMESPACE:default} # Labelselector is used to locate specific configmap labelSelector: ${SW_CLUSTER_K8S_LABEL:app=collector,release=skywalking} +``` +## Dynamic Configuration Nacos Implementation + +[Nacos](https://github.com/alibaba/nacos) is also supported as DCC(Dynamic Configuration Center), to use it, please configure as follows: + +```yaml +configuration: + selector: ${SW_CONFIGURATION:nacos} + nacos: + # Nacos Server Host + serverAddr: ${SW_CONFIG_NACOS_SERVER_ADDR:127.0.0.1} + # Nacos Server Port + port: ${SW_CONFIG_NACOS_SERVER_PORT:8848} + # Nacos Configuration Group + group: ${SW_CONFIG_NACOS_SERVER_GROUP:skywalking} + # Nacos Configuration namespace + namespace: ${SW_CONFIG_NACOS_SERVER_NAMESPACE:} + # Unit seconds, sync period. Default fetch every 60 seconds. + period: ${SW_CONFIG_NACOS_PERIOD:60} + # the name of current cluster, set the name if you want to upstream system known. + clusterName: ${SW_CONFIG_NACOS_CLUSTER_NAME:default} ``` \ No newline at end of file diff --git a/oap-server/pom.xml b/oap-server/pom.xml index ee05cb482..ad72ef1e9 100755 --- a/oap-server/pom.xml +++ b/oap-server/pom.xml @@ -79,6 +79,7 @@ 1.4 0.6.0 1.4.0 + 1.3.1 0.30.0 4.0.1 2.12.0 @@ -379,13 +380,16 @@ simpleclient ${simpleclient.version} - com.ctrip.framework.apollo apollo-client ${apollo.version} - + + com.alibaba.nacos + nacos-client + ${nacos.version} + org.mousio etcd4j diff --git a/oap-server/server-bootstrap/pom.xml b/oap-server/server-bootstrap/pom.xml index 6fb72efdf..904db649b 100644 --- a/oap-server/server-bootstrap/pom.xml +++ b/oap-server/server-bootstrap/pom.xml @@ -68,6 +68,11 @@ cluster-etcd-plugin ${project.version} + + org.apache.skywalking + cluster-nacos-plugin + ${project.version} + @@ -200,6 +205,11 @@ configuration-k8s-configmap ${project.version} + + org.apache.skywalking + configuration-nacos + ${project.version} + diff --git a/oap-server/server-bootstrap/src/main/resources/application.yml b/oap-server/server-bootstrap/src/main/resources/application.yml index dd53b4f3e..352fbd7a6 100755 --- a/oap-server/server-bootstrap/src/main/resources/application.yml +++ b/oap-server/server-bootstrap/src/main/resources/application.yml @@ -41,6 +41,11 @@ cluster: serviceName: ${SW_SERVICE_NAME:"SkyWalking_OAP_Cluster"} # etcd cluster nodes, example: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379 hostPort: ${SW_CLUSTER_ETCD_HOST_PORT:localhost:2379} + nacos: + serviceName: ${SW_SERVICE_NAME:"SkyWalking_OAP_Cluster"} + hostPort: ${SW_CLUSTER_NACOS_HOST_PORT:localhost:8848} + # Nacos Configuration namespace + namespace: ${SW_CLUSTER_NACOS_NAMESPACE:"public"} core: selector: ${SW_CORE:default} @@ -268,6 +273,19 @@ configuration: period: ${SW_CONFIG_CONFIGMAP_PERIOD:60} namespace: ${SW_CLUSTER_K8S_NAMESPACE:default} labelSelector: ${SW_CLUSTER_K8S_LABEL:app=collector,release=skywalking} + nacos: + # Nacos Server Host + serverAddr: ${SW_CONFIG_NACOS_SERVER_ADDR:127.0.0.1} + # Nacos Server Port + port: ${SW_CONFIG_NACOS_SERVER_PORT:8848} + # Nacos Configuration Group + group: ${SW_CONFIG_NACOS_SERVER_GROUP:skywalking} + # Nacos Configuration namespace + namespace: ${SW_CONFIG_NACOS_SERVER_NAMESPACE:} + # Unit seconds, sync period. Default fetch every 60 seconds. + period: ${SW_CONFIG_NACOS_PERIOD:60} + # the name of current cluster, set the name if you want to upstream system known. + clusterName: ${SW_CONFIG_NACOS_CLUSTER_NAME:default} exporter: selector: ${SW_EXPORTER:-} diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml b/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml new file mode 100644 index 000000000..0c542880f --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/pom.xml @@ -0,0 +1,166 @@ + + + + + server-cluster-plugin + org.apache.skywalking + 8.1.0-SNAPSHOT + + 4.0.0 + + cluster-nacos-plugin + + + + org.apache.skywalking + server-core + ${project.version} + + + com.alibaba.nacos + nacos-client + + + org.slf4j + slf4j-api + + + org.apache.logging.log4j + log4j-core + + + org.apache.logging.log4j + log4j-slf4j-impl + + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + + + net.jcip + jcip-annotations + + + org.apache.httpcomponents + httpasyncclient + + + + + + + + CI-with-IT + + + + io.fabric8 + docker-maven-plugin + + all + true + default + true + IfNotPresent + + + nacos/nacos-server:${nacos.version} + cluster-nacos-plugin-integration-test-nacos + + + standalone + + + nacos.port:8848 + + + Nacos started successfully + + + + + + + + + start + pre-integration-test + + start + + + + stop + 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') + + log.info("Docker hostname is " + project.properties['docker.hostname']) + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + ${docker.hostname}:${nacos.port} + + + + + + + integration-test + verify + + + + + + + + + diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosConfig.java b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosConfig.java new file mode 100644 index 000000000..bbfe071c6 --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosConfig.java @@ -0,0 +1,35 @@ +/* + * 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.cluster.plugin.nacos; + +import lombok.Getter; +import lombok.Setter; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; + +public class ClusterModuleNacosConfig extends ModuleConfig { + @Setter + @Getter + private String serviceName; + @Setter + @Getter + private String hostPort; + @Setter + @Getter + private String namespace = "public"; +} diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosProvider.java b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosProvider.java new file mode 100644 index 000000000..c73bea1f9 --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosProvider.java @@ -0,0 +1,89 @@ +/* + * 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.cluster.plugin.nacos; + +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.naming.NamingFactory; +import com.alibaba.nacos.api.naming.NamingService; +import java.util.Properties; +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.cluster.ClusterModule; +import org.apache.skywalking.oap.server.core.cluster.ClusterNodesQuery; +import org.apache.skywalking.oap.server.core.cluster.ClusterRegister; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleDefine; +import org.apache.skywalking.oap.server.library.module.ModuleProvider; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException; + +public class ClusterModuleNacosProvider extends ModuleProvider { + + private final ClusterModuleNacosConfig config; + private NamingService namingService; + + public ClusterModuleNacosProvider() { + super(); + this.config = new ClusterModuleNacosConfig(); + } + + @Override + public String name() { + return "nacos"; + } + + @Override + public Class module() { + return ClusterModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return config; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + try { + Properties properties = new Properties(); + properties.put(PropertyKeyConst.SERVER_ADDR, config.getHostPort()); + properties.put(PropertyKeyConst.NAMESPACE, config.getNamespace()); + namingService = NamingFactory.createNamingService(properties); + } catch (Exception e) { + throw new ModuleStartException(e.getMessage(), e); + } + NacosCoordinator coordinator = new NacosCoordinator(namingService, config); + this.registerServiceImplementation(ClusterRegister.class, coordinator); + this.registerServiceImplementation(ClusterNodesQuery.class, coordinator); + } + + @Override + public void start() throws ServiceNotProvidedException { + + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException { + + } + + @Override + public String[] requiredModules() { + return new String[] {CoreModule.NAME}; + } +} diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/NacosCoordinator.java b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/NacosCoordinator.java new file mode 100644 index 000000000..4253d8f7c --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/NacosCoordinator.java @@ -0,0 +1,78 @@ +/* + * 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.cluster.plugin.nacos; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import java.util.ArrayList; +import java.util.List; +import org.apache.skywalking.oap.server.core.cluster.ClusterNodesQuery; +import org.apache.skywalking.oap.server.core.cluster.ClusterRegister; +import org.apache.skywalking.oap.server.core.cluster.RemoteInstance; +import org.apache.skywalking.oap.server.core.cluster.ServiceQueryException; +import org.apache.skywalking.oap.server.core.cluster.ServiceRegisterException; +import org.apache.skywalking.oap.server.core.remote.client.Address; +import org.apache.skywalking.oap.server.library.util.CollectionUtils; +import org.apache.skywalking.oap.server.telemetry.api.TelemetryRelatedContext; + +public class NacosCoordinator implements ClusterRegister, ClusterNodesQuery { + + private final NamingService namingService; + private final ClusterModuleNacosConfig config; + private volatile Address selfAddress; + + public NacosCoordinator(NamingService namingService, ClusterModuleNacosConfig config) { + this.namingService = namingService; + this.config = config; + } + + @Override + public List queryRemoteNodes() { + List result = new ArrayList<>(); + try { + List instances = namingService.selectInstances(config.getServiceName(), true); + if (CollectionUtils.isNotEmpty(instances)) { + instances.forEach(instance -> { + Address address = new Address(instance.getIp(), instance.getPort(), false); + if (address.equals(selfAddress)) { + address.setSelf(true); + } + result.add(new RemoteInstance(address)); + }); + } + } catch (NacosException e) { + throw new ServiceQueryException(e.getErrMsg()); + } + return result; + } + + @Override + public void registerRemote(RemoteInstance remoteInstance) throws ServiceRegisterException { + String host = remoteInstance.getAddress().getHost(); + int port = remoteInstance.getAddress().getPort(); + try { + namingService.registerInstance(config.getServiceName(), host, port); + } catch (Exception e) { + throw new ServiceRegisterException(e.getMessage()); + } + this.selfAddress = remoteInstance.getAddress(); + TelemetryRelatedContext.INSTANCE.setId(selfAddress.toString()); + } +} diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider new file mode 100644 index 000000000..1a1c0e89f --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/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.cluster.plugin.nacos.ClusterModuleNacosProvider \ No newline at end of file diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosProviderTest.java b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosProviderTest.java new file mode 100644 index 000000000..f489f93c0 --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ClusterModuleNacosProviderTest.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.cluster.plugin.nacos; + +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.naming.NamingFactory; +import com.alibaba.nacos.api.naming.NamingService; +import java.util.Properties; +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.cluster.ClusterModule; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(NamingFactory.class) +@PowerMockIgnore("javax.management.*") +public class ClusterModuleNacosProviderTest { + + private static final String SERVICE_NAME = "test-service_name"; + + private ClusterModuleNacosProvider provider = new ClusterModuleNacosProvider(); + + @Test + public void name() { + assertEquals("nacos", provider.name()); + } + + @Test + public void module() { + assertEquals(ClusterModule.class, provider.module()); + } + + @Test + public void createConfigBeanIfAbsent() { + ModuleConfig moduleConfig = provider.createConfigBeanIfAbsent(); + assertTrue(moduleConfig instanceof ClusterModuleNacosConfig); + } + + @Test(expected = ModuleStartException.class) + public void prepareWithNonHost() throws Exception { + provider.prepare(); + } + + @Test + public void prepare() throws Exception { + PowerMockito.mockStatic(NamingFactory.class); + ClusterModuleNacosConfig nacosConfig = new ClusterModuleNacosConfig(); + nacosConfig.setHostPort("10.0.0.1:1000,10.0.0.2:1001"); + nacosConfig.setServiceName(SERVICE_NAME); + Whitebox.setInternalState(provider, "config", nacosConfig); + NamingService namingService = mock(NamingService.class); + + Properties properties = new Properties(); + properties.put(PropertyKeyConst.SERVER_ADDR, "10.0.0.1:1000,10.0.0.2:1001"); + + PowerMockito.when(NamingFactory.createNamingService(properties)).thenReturn(namingService); + provider.prepare(); + ArgumentCaptor addressCaptor = ArgumentCaptor.forClass(Properties.class); + PowerMockito.verifyStatic(); + NamingFactory.createNamingService(addressCaptor.capture()); + Properties data = addressCaptor.getValue(); + assertEquals("10.0.0.1:1000,10.0.0.2:1001", data.getProperty(PropertyKeyConst.SERVER_ADDR)); + } + + @Test + public void start() { + provider.start(); + } + + @Test + public void notifyAfterCompleted() { + provider.notifyAfterCompleted(); + } + + @Test + public void requiredModules() { + String[] modules = provider.requiredModules(); + assertArrayEquals(new String[] {CoreModule.NAME}, modules); + } +} diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ITClusterModuleNacosProviderFunctionalTest.java b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ITClusterModuleNacosProviderFunctionalTest.java new file mode 100644 index 000000000..724f221da --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/ITClusterModuleNacosProviderFunctionalTest.java @@ -0,0 +1,194 @@ +/* + * 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.cluster.plugin.nacos; + +import com.alibaba.nacos.api.naming.NamingService; +import java.util.Collections; +import java.util.List; +import org.apache.skywalking.apm.util.StringUtil; +import org.apache.skywalking.oap.server.core.cluster.ClusterNodesQuery; +import org.apache.skywalking.oap.server.core.cluster.ClusterRegister; +import org.apache.skywalking.oap.server.core.cluster.RemoteInstance; +import org.apache.skywalking.oap.server.core.remote.client.Address; +import org.apache.skywalking.oap.server.library.module.ModuleProvider; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.junit.Before; +import org.junit.Test; +import org.powermock.reflect.Whitebox; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ITClusterModuleNacosProviderFunctionalTest { + + private String nacosAddress; + + @Before + public void before() { + nacosAddress = System.getProperty("nacos.address"); + assertFalse(StringUtil.isEmpty(nacosAddress)); + } + + @Test + public void registerRemote() throws Exception { + final String serviceName = "register_remote"; + ModuleProvider provider = createProvider(serviceName); + + Address selfAddress = new Address("127.0.0.1", 1000, true); + RemoteInstance instance = new RemoteInstance(selfAddress); + getClusterRegister(provider).registerRemote(instance); + + List remoteInstances = queryRemoteNodes(provider, 1); + assertEquals(1, remoteInstances.size()); + Address queryAddress = remoteInstances.get(0).getAddress(); + assertEquals(selfAddress, queryAddress); + assertTrue(queryAddress.isSelf()); + } + + @Test + public void registerRemoteOfReceiver() throws Exception { + final String serviceName = "register_remote_receiver"; + ModuleProvider providerA = createProvider(serviceName); + ModuleProvider providerB = createProvider(serviceName); + + // Mixed or Aggregator + Address selfAddress = new Address("127.0.0.3", 1000, true); + RemoteInstance instance = new RemoteInstance(selfAddress); + getClusterRegister(providerA).registerRemote(instance); + + // Receiver + List remoteInstances = queryRemoteNodes(providerB, 1); + assertEquals(1, remoteInstances.size()); + Address queryAddress = remoteInstances.get(0).getAddress(); + assertEquals(selfAddress, queryAddress); + assertFalse(queryAddress.isSelf()); + } + + @Test + public void registerRemoteOfCluster() throws Exception { + final String serviceName = "register_remote_cluster"; + ModuleProvider providerA = createProvider(serviceName); + ModuleProvider providerB = createProvider(serviceName); + + Address addressA = new Address("127.0.0.4", 1000, true); + Address addressB = new Address("127.0.0.5", 1000, true); + + RemoteInstance instanceA = new RemoteInstance(addressA); + RemoteInstance instanceB = new RemoteInstance(addressB); + + getClusterRegister(providerA).registerRemote(instanceA); + getClusterRegister(providerB).registerRemote(instanceB); + + List remoteInstancesOfA = queryRemoteNodes(providerA, 2); + validateServiceInstance(addressA, addressB, remoteInstancesOfA); + + List remoteInstancesOfB = queryRemoteNodes(providerB, 2); + validateServiceInstance(addressB, addressA, remoteInstancesOfB); + } + + @Test + public void deregisterRemoteOfCluster() throws Exception { + final String serviceName = "deregister_remote_cluster"; + ModuleProvider providerA = createProvider(serviceName); + ModuleProvider providerB = createProvider(serviceName); + + Address addressA = new Address("127.0.0.6", 1000, true); + Address addressB = new Address("127.0.0.7", 1000, true); + + RemoteInstance instanceA = new RemoteInstance(addressA); + RemoteInstance instanceB = new RemoteInstance(addressB); + + getClusterRegister(providerA).registerRemote(instanceA); + getClusterRegister(providerB).registerRemote(instanceB); + + List remoteInstancesOfA = queryRemoteNodes(providerA, 2); + validateServiceInstance(addressA, addressB, remoteInstancesOfA); + + List remoteInstancesOfB = queryRemoteNodes(providerB, 2); + validateServiceInstance(addressB, addressA, remoteInstancesOfB); + + // deregister A + ClusterRegister register = getClusterRegister(providerA); + NamingService namingServiceA = Whitebox.getInternalState(register, "namingService"); + namingServiceA.deregisterInstance(serviceName, addressA.getHost(), addressA.getPort()); + + // only B + remoteInstancesOfB = queryRemoteNodes(providerB, 1); + assertEquals(1, remoteInstancesOfB.size()); + Address address = remoteInstancesOfB.get(0).getAddress(); + assertEquals(addressB, address); + assertTrue(address.isSelf()); + } + + private ClusterModuleNacosProvider createProvider(String servicName) throws ModuleStartException { + ClusterModuleNacosProvider provider = new ClusterModuleNacosProvider(); + + ClusterModuleNacosConfig config = (ClusterModuleNacosConfig) provider.createConfigBeanIfAbsent(); + + config.setHostPort(nacosAddress); + config.setServiceName(servicName); + + provider.prepare(); + provider.start(); + provider.notifyAfterCompleted(); + return provider; + } + + private ClusterRegister getClusterRegister(ModuleProvider provider) { + return provider.getService(ClusterRegister.class); + } + + private ClusterNodesQuery getClusterNodesQuery(ModuleProvider provider) { + return provider.getService(ClusterNodesQuery.class); + } + + private List queryRemoteNodes(ModuleProvider provider, int goals) throws InterruptedException { + int i = 20; + do { + List instances = getClusterNodesQuery(provider).queryRemoteNodes(); + if (instances.size() == goals) { + return instances; + } else { + Thread.sleep(1000); + } + } + while (--i > 0); + return Collections.EMPTY_LIST; + } + + private void validateServiceInstance(Address selfAddress, Address otherAddress, List queryResult) { + assertEquals(2, queryResult.size()); + + boolean selfExist = false, otherExist = false; + + for (RemoteInstance instance : queryResult) { + Address queryAddress = instance.getAddress(); + if (queryAddress.equals(selfAddress) && queryAddress.isSelf()) { + selfExist = true; + } else if (queryAddress.equals(otherAddress) && !queryAddress.isSelf()) { + otherExist = true; + } + } + + assertTrue(selfExist); + assertTrue(otherExist); + } + +} diff --git a/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/NacosCoordinatorTest.java b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/NacosCoordinatorTest.java new file mode 100644 index 000000000..71acb749b --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-nacos-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/nacos/NacosCoordinatorTest.java @@ -0,0 +1,130 @@ +/* + * 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.cluster.plugin.nacos; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.apache.skywalking.oap.server.core.cluster.RemoteInstance; +import org.apache.skywalking.oap.server.core.remote.client.Address; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class NacosCoordinatorTest { + private NamingService namingService = mock(NamingService.class); + private ClusterModuleNacosConfig nacosConfig = new ClusterModuleNacosConfig(); + private NacosCoordinator coordinator; + + private Address remoteAddress = new Address("10.0.0.1", 1000, false); + private Address selfRemoteAddress = new Address("10.0.0.2", 1001, true); + + private static final String SERVICE_NAME = "test-service"; + + @Before + public void setUp() throws NacosException { + nacosConfig.setServiceName(SERVICE_NAME); + coordinator = new NacosCoordinator(namingService, nacosConfig); + } + + @Test + @SuppressWarnings("unchecked") + public void queryRemoteNodesWithNonOrEmpty() throws NacosException { + when(namingService.selectInstances(anyString(), anyBoolean())).thenReturn(null, Collections.emptyList()); + assertEquals(0, coordinator.queryRemoteNodes().size()); + } + + @Test + public void queryRemoteNodes() throws NacosException { + registerSelfRemote(); + List instances = mockInstance(); + when(namingService.selectInstances(anyString(), anyBoolean())).thenReturn(instances); + List remoteInstances = coordinator.queryRemoteNodes(); + assertEquals(2, remoteInstances.size()); + + RemoteInstance selfInstance = remoteInstances.get(0); + validate(selfRemoteAddress, selfInstance); + + RemoteInstance notSelfInstance = remoteInstances.get(1); + validate(remoteAddress, notSelfInstance); + } + + @Test + public void queryRemoteNodesWithNullSelf() throws NacosException { + List instances = mockInstance(); + when(namingService.selectInstances(anyString(), anyBoolean())).thenReturn(instances); + List remoteInstances = coordinator.queryRemoteNodes(); + assertEquals(remoteInstances.size(), instances.size()); + } + + @Test + public void registerRemote() throws NacosException { + registerRemote(remoteAddress); + } + + @Test + public void registerSelfRemote() throws NacosException { + registerRemote(selfRemoteAddress); + } + + private void validate(Address originArress, RemoteInstance instance) { + Address instanceAddress = instance.getAddress(); + assertEquals(originArress.getHost(), instanceAddress.getHost()); + assertEquals(originArress.getPort(), instanceAddress.getPort()); + } + + private void registerRemote(Address address) throws NacosException { + coordinator.registerRemote(new RemoteInstance(address)); + + ArgumentCaptor serviceNameArgumentCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor hostArgumentCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor portArgumentCaptor = ArgumentCaptor.forClass(Integer.class); + verify(namingService).registerInstance(serviceNameArgumentCaptor.capture(), hostArgumentCaptor.capture(), portArgumentCaptor + .capture()); + + assertEquals(SERVICE_NAME, serviceNameArgumentCaptor.getValue()); + assertEquals(address.getHost(), hostArgumentCaptor.getValue()); + assertEquals(Long.valueOf(address.getPort()), Long.valueOf(portArgumentCaptor.getValue())); + } + + private List mockInstance() { + Instance remoteInstance = new Instance(); + Instance selfInstance = new Instance(); + selfInstance.setIp(selfRemoteAddress.getHost()); + selfInstance.setPort(selfRemoteAddress.getPort()); + + remoteInstance.setIp(remoteAddress.getHost()); + remoteInstance.setPort(remoteAddress.getPort()); + + List instances = new ArrayList<>(); + instances.add(selfInstance); + instances.add(remoteInstance); + return instances; + } +} diff --git a/oap-server/server-cluster-plugin/pom.xml b/oap-server/server-cluster-plugin/pom.xml index e55fdc9f5..b29da27a0 100644 --- a/oap-server/server-cluster-plugin/pom.xml +++ b/oap-server/server-cluster-plugin/pom.xml @@ -33,6 +33,7 @@ cluster-kubernetes-plugin cluster-consul-plugin cluster-etcd-plugin + cluster-nacos-plugin 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 000000000..ccd9c789c --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/pom.xml @@ -0,0 +1,145 @@ + + + + + + server-configuration + org.apache.skywalking + 8.1.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 + + + + + + CI-with-IT + + + + io.fabric8 + docker-maven-plugin + + all + true + default + true + IfNotPresent + + + nacos/nacos-server:${nacos.version} + nacos-dynamic-configuration-integration-test-nacos + + + standalone + + + nacos.port:8848 + + + Nacos started successfully + + + + + + + + + start + pre-integration-test + + start + + + + stop + 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') + + log.info("Docker hostname is " + project.properties['docker.hostname']) + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + ${docker.hostname} + + + ${nacos.port} + + + + + + + integration-test + verify + + + + + + + + + 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 000000000..0101cdf51 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegister.java @@ -0,0 +1,134 @@ +/* + * 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.PropertyKeyConst; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.config.listener.Listener; +import com.alibaba.nacos.api.exception.NacosException; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +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; + +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(PropertyKeyConst.SERVER_ADDR, serverAddr + ":" + port); + properties.put(PropertyKeyConst.NAMESPACE, settings.getNamespace()); + this.configService = NacosFactory.createConfigService(properties); + } + + @Override + public Optional 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 Optional.of(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 000000000..ce04db245 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationProvider.java @@ -0,0 +1,71 @@ +/* + * 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Get configuration from Nacos. + */ +public class NacosConfigurationProvider extends AbstractConfigurationProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(NacosConfigurationProvider.class); + + 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 { + LOGGER.info("settings: {}", settings); + 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 000000000..cbe4af121 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/main/java/org/apache/skywalking/oap/server/configuration/nacos/NacosServerSettings.java @@ -0,0 +1,36 @@ +/* + * 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 lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; + +@Getter +@Setter +@ToString +public class NacosServerSettings extends ModuleConfig { + private String clusterName = "default"; + private String namespace = ""; + private String serverAddr; + private int port = 8848; + private String group; + private int period = 60; +} 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 000000000..d3fbbfc8d --- /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 000000000..d71d0eeea --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/ITNacosConfigurationTest.java @@ -0,0 +1,116 @@ +/* + * 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 java.io.FileNotFoundException; +import java.io.Reader; +import java.util.Map; +import java.util.Properties; +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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class ITNacosConfigurationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ITNacosConfigurationTest.class); + + 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 = 20000) + public void shouldReadUpdated() throws NacosException { + assertNull(provider.watcher.value()); + + final Properties properties = new Properties(); + final String nacosHost = System.getProperty("nacos.host"); + final String nacosPort = System.getProperty("nacos.port"); + LOGGER.info("nacosHost: {}, nacosPort: {}", nacosHost, nacosPort); + properties.put("serverAddr", nacosHost + ":" + nacosPort); + + 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 000000000..671ae2a52 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigWatcherRegisterTest.java @@ -0,0 +1,65 @@ +/* + * 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 java.util.HashMap; +import java.util.Map; +import org.apache.skywalking.oap.server.configuration.api.ConfigTable; +import org.junit.Test; +import org.powermock.reflect.Whitebox; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +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); + when(mockSettings.getNamespace()).thenReturn(""); + + 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)).get(); + + 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 000000000..a638f96a8 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestModule.java @@ -0,0 +1,34 @@ +/* + * 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; + +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 000000000..ff2d097bf --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/java/org/apache/skywalking/oap/server/configuration/nacos/NacosConfigurationTestProvider.java @@ -0,0 +1,94 @@ +/* + * 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.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleDefine; +import org.apache.skywalking.oap.server.library.module.ModuleProvider; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NacosConfigurationTestProvider extends ModuleProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(NacosConfigurationTestProvider.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(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 000000000..9448151e6 --- /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 000000000..72ce82e5f --- /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 100755 index 000000000..f5bd261ac --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/resources/application.yml @@ -0,0 +1,35 @@ +# 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: ${nacos.host} + # Nacos Server Port + port: ${nacos.port} + # Nacos Configuration Group + group: 'skywalking' + # Nacos Configuration namespace + namespace: '' + # 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 000000000..c08daf9a2 --- /dev/null +++ b/oap-server/server-configuration/configuration-nacos/src/test/resources/docker/docker-entrypoint-initdb.d/nacos-mysql.sql @@ -0,0 +1,215 @@ +-- +-- 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'; + +USE test; + +/******************************************/ +/* 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 16bace438..5ab7b4ce3 100644 --- a/oap-server/server-configuration/pom.xml +++ b/oap-server/server-configuration/pom.xml @@ -36,6 +36,7 @@ configuration-etcd configuration-consul configuration-k8s-configmap + configuration-nacos diff --git a/tools/dependencies/known-oap-backend-dependencies-es7.txt b/tools/dependencies/known-oap-backend-dependencies-es7.txt index 8cf054b79..9d361b16e 100755 --- a/tools/dependencies/known-oap-backend-dependencies-es7.txt +++ b/tools/dependencies/known-oap-backend-dependencies-es7.txt @@ -122,6 +122,9 @@ lucene-suggest-8.0.0.jar minimal-json-0.9.5.jar moshi-1.5.0.jar msgpack-core-0.8.16.jar +nacos-api-1.3.1.jar +nacos-client-1.3.1.jar +nacos-common-1.3.1.jar netty-3.10.5.Final.jar netty-buffer-4.1.42.Final.jar netty-codec-4.1.42.Final.jar diff --git a/tools/dependencies/known-oap-backend-dependencies.txt b/tools/dependencies/known-oap-backend-dependencies.txt index 9ea4b732d..0805e18c9 100755 --- a/tools/dependencies/known-oap-backend-dependencies.txt +++ b/tools/dependencies/known-oap-backend-dependencies.txt @@ -120,6 +120,9 @@ lucene-suggest-7.3.1.jar minimal-json-0.9.5.jar moshi-1.5.0.jar msgpack-core-0.8.16.jar +nacos-api-1.3.1.jar +nacos-client-1.3.1.jar +nacos-common-1.3.1.jar netty-3.10.5.Final.jar netty-buffer-4.1.42.Final.jar netty-codec-4.1.42.Final.jar