You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2021/09/03 12:53:08 UTC
[skywalking] branch master updated: Support consul grouped dynamic
configurations (#7647)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new 0fae36e Support consul grouped dynamic configurations (#7647)
0fae36e is described below
commit 0fae36ed4c14264143aa0a4f3a04e67aa1bad23c
Author: wankai123 <wa...@foxmail.com>
AuthorDate: Fri Sep 3 20:52:22 2021 +0800
Support consul grouped dynamic configurations (#7647)
---
CHANGES.md | 1 +
docs/en/setup/backend/dynamic-config-consul.md | 52 +++++++++++++++++++++-
.../consul/ConsulConfigurationProvider.java | 8 ++--
.../consul/ConsulConfigurationWatcherRegister.java | 28 ++++++++----
.../consul/ConsulConfigurationTestProvider.java | 38 +++++++++++++---
.../consul/ITConsulConfigurationTest.java | 37 +++++++++++++++
.../nacos/ITNacosConfigurationTest.java | 2 +-
7 files changed, 146 insertions(+), 20 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 3871d9d..9838eb4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -53,6 +53,7 @@ Release Notes.
* Support for filter function filtering of int type values.
* Support mTLS for gRPC channel.
* Add yaml file suffix limit when reading ui templates.
+* Support consul grouped dynamic configurations.
#### UI
diff --git a/docs/en/setup/backend/dynamic-config-consul.md b/docs/en/setup/backend/dynamic-config-consul.md
index e5f8c3c..817fdc1 100755
--- a/docs/en/setup/backend/dynamic-config-consul.md
+++ b/docs/en/setup/backend/dynamic-config-consul.md
@@ -12,4 +12,54 @@ configuration:
period: ${SW_CONFIG_CONSUL_PERIOD:1}
# Consul aclToken
aclToken: ${SW_CONFIG_CONSUL_ACL_TOKEN:""}
-```
\ No newline at end of file
+```
+
+## Config Storage
+### Single Config
+Single configs in Consul are key/value pairs:
+
+| Key | Value |
+|-----|-----|
+| configKey | configVaule |
+
+e.g. The config is:
+```
+{agent-analyzer.default.slowDBAccessThreshold}:{default:200,mongodb:50}
+```
+The config in Consul is:
+
+| Key | Value |
+|-----|-----|
+| agent-analyzer.default.slowDBAccessThreshold | default:200,mongodb:50 |
+| ... | ... |
+
+
+### Group Config
+Group config in Consul are key/value pairs as well, but according to the level keys organized by `/`, see: https://www.consul.io/docs/dynamic-app-config/kv#using-consul-kv
+
+| Key | Value |
+|-----|-----|
+| configKey/subItemkey1 | subItemValue1 |
+| configKey/subItemkey2 | subItemValue2 |
+| ... | ... |
+
+If use Consul UI we can see keys organized like folder:
+```
+configKey
+ -- subItemkey1
+ -- subItemkey2
+...
+```
+e.g. The config is:
+```
+{core.default.endpoint-name-grouping-openapi}:|{customerAPI-v1}:{value of customerAPI-v1}
+ |{productAPI-v1}:{value of productAPI-v1}
+ |{productAPI-v2}:{value of productAPI-v2}
+```
+The config in Consul is:
+
+| Key | Value |
+|-----|-----|
+| core.default.endpoint-name-grouping-openapi/customerAPI-v1 | value of customerAPI-v1 |
+| core.default.endpoint-name-grouping-openapi/productAPI-v1 | value of productAPI-v1 |
+| core.default.endpoint-name-grouping-openapi/productAPI-v2 | value of productAPI-v2 |
diff --git a/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationProvider.java b/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationProvider.java
index e16aa5a..d75f6af 100644
--- a/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationProvider.java
+++ b/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationProvider.java
@@ -19,19 +19,17 @@
package org.apache.skywalking.oap.server.configuration.consul;
import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
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 Consul.
*/
+@Slf4j
public class ConsulConfigurationProvider extends AbstractConfigurationProvider {
- private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigurationProvider.class);
-
private final ConsulConfigurationCenterSettings settings;
public ConsulConfigurationProvider() {
@@ -50,7 +48,7 @@ public class ConsulConfigurationProvider extends AbstractConfigurationProvider {
@Override
protected ConfigWatcherRegister initConfigReader() throws ModuleStartException {
- LOGGER.info("consul settings: {}", settings);
+ log.info("consul settings: {}", settings);
if (Strings.isNullOrEmpty(settings.getHostAndPorts())) {
throw new ModuleStartException("Consul hostAndPorts cannot be null or empty");
diff --git a/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationWatcherRegister.java b/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationWatcherRegister.java
index a51aee1..0f53568 100644
--- a/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationWatcherRegister.java
+++ b/oap-server/server-configuration/configuration-consul/src/main/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationWatcherRegister.java
@@ -31,17 +31,15 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
import org.apache.skywalking.oap.server.configuration.api.ConfigWatcherRegister;
import org.apache.skywalking.oap.server.configuration.api.GroupConfigTable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
@SuppressWarnings("UnstableApiUsage")
+@Slf4j
public class ConsulConfigurationWatcherRegister extends ConfigWatcherRegister {
- private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigurationWatcherRegister.class);
-
private static final int DEFAULT_PORT = 8500;
private final KeyValueClient consul;
@@ -97,8 +95,22 @@ public class ConsulConfigurationWatcherRegister extends ConfigWatcherRegister {
@Override
public Optional<GroupConfigTable> readGroupConfig(final Set<String> keys) {
- // TODO: implement readGroupConfig
- return Optional.empty();
+ GroupConfigTable groupConfigTable = new GroupConfigTable();
+ keys.forEach(key -> {
+ GroupConfigTable.GroupConfigItems groupConfigItems = new GroupConfigTable.GroupConfigItems(key);
+ groupConfigTable.addGroupConfigItems(groupConfigItems);
+ String groupKey = key + "/";
+ List<String> groupItemKeys = this.consul.getKeys(groupKey);
+ if (groupItemKeys != null) {
+ groupItemKeys.stream().filter(it -> !groupKey.equals(it)).forEach(groupItemKey -> {
+ Optional<String> itemValue = this.consul.getValueAsString(groupItemKey);
+ String itemName = groupItemKey.substring(groupKey.length());
+ groupConfigItems.add(
+ new ConfigTable.ConfigItem(itemName, itemValue.orElse(null)));
+ });
+ }
+ });
+ return Optional.of(groupConfigTable);
}
private void registerKeyListeners(final Set<String> keys) {
@@ -133,8 +145,8 @@ public class ConsulConfigurationWatcherRegister extends ConfigWatcherRegister {
}
private void onKeyValueChanged(String key, String value) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info("Consul config changed: {}: {}", key, value);
+ if (log.isInfoEnabled()) {
+ log.info("Consul config changed: {}: {}", key, value);
}
configItemKeyedByName.put(key, Optional.ofNullable(value));
diff --git a/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationTestProvider.java b/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationTestProvider.java
index 23c548f..0516e51 100644
--- a/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationTestProvider.java
+++ b/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ConsulConfigurationTestProvider.java
@@ -18,21 +18,23 @@
package org.apache.skywalking.oap.server.configuration.consul;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import lombok.extern.slf4j.Slf4j;
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.configuration.api.GroupConfigChangeWatcher;
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;
+@Slf4j
public class ConsulConfigurationTestProvider extends ModuleProvider {
- private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigurationTestProvider.class);
-
ConfigChangeWatcher watcher;
+ GroupConfigChangeWatcher groupWatcher;
@Override
public String name() {
@@ -57,7 +59,7 @@ public class ConsulConfigurationTestProvider extends ModuleProvider {
@Override
public void notify(ConfigChangeWatcher.ConfigChangeEvent value) {
- LOGGER.info("ConfigChangeWatcher.ConfigChangeEvent: {}", value);
+ log.info("ConfigChangeWatcher.ConfigChangeEvent: {}", value);
if (EventType.DELETE.equals(value.getEventType())) {
testValue = null;
} else {
@@ -70,6 +72,27 @@ public class ConsulConfigurationTestProvider extends ModuleProvider {
return testValue;
}
};
+
+ groupWatcher = new GroupConfigChangeWatcher(ConsulConfigurationTestModule.NAME, this, "testKeyGroup") {
+ private Map<String, String> config = new ConcurrentHashMap<>();
+
+ @Override
+ public void notifyGroup(Map<String, ConfigChangeEvent> groupItems) {
+ log.info("GroupConfigChangeWatcher.ConfigChangeEvents: {}", groupItems);
+ groupItems.forEach((groupItemName, event) -> {
+ if (EventType.DELETE.equals(event.getEventType())) {
+ config.remove(groupItemName);
+ } else {
+ config.put(groupItemName, event.getNewValue());
+ }
+ });
+ }
+
+ @Override
+ public Map<String, String> groupItems() {
+ return config;
+ }
+ };
}
@Override
@@ -78,6 +101,11 @@ public class ConsulConfigurationTestProvider extends ModuleProvider {
.provider()
.getService(DynamicConfigurationService.class)
.registerConfigChangeWatcher(watcher);
+
+ getManager().find(ConfigurationModule.NAME)
+ .provider()
+ .getService(DynamicConfigurationService.class)
+ .registerConfigChangeWatcher(groupWatcher);
}
@Override
diff --git a/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ITConsulConfigurationTest.java b/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ITConsulConfigurationTest.java
index 425c4a1..335bc04 100644
--- a/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ITConsulConfigurationTest.java
+++ b/oap-server/server-configuration/configuration-consul/src/test/java/org/apache/skywalking/oap/server/configuration/consul/ITConsulConfigurationTest.java
@@ -83,6 +83,43 @@ public class ITConsulConfigurationTest {
assertNull(provider.watcher.value());
}
+ @Test(timeout = 30000)
+ public void shouldReadUpdated4Group() {
+ assertEquals("{}", provider.groupWatcher.groupItems().toString());
+
+ String hostAndPort = System.getProperty("consul.address", "127.0.0.1:8500");
+ Consul consul = Consul.builder()
+ .withHostAndPort(HostAndPort.fromString(hostAndPort))
+ .withConnectTimeoutMillis(5000)
+ .build();
+ KeyValueClient client = consul.keyValueClient();
+
+ assertTrue(client.putValue("test-module.default.testKeyGroup/item1", "100"));
+ assertTrue(client.putValue("test-module.default.testKeyGroup/item2", "200"));
+
+ for (String v = provider.groupWatcher.groupItems().get("item1"); v == null; v = provider.groupWatcher.groupItems().get("item1")) {
+ }
+ for (String v = provider.groupWatcher.groupItems().get("item2"); v == null; v = provider.groupWatcher.groupItems().get("item2")) {
+ }
+ assertEquals("100", provider.groupWatcher.groupItems().get("item1"));
+ assertEquals("200", provider.groupWatcher.groupItems().get("item2"));
+
+ //test remove item1
+ client.deleteKey("test-module.default.testKeyGroup/item1");
+ for (String v = provider.groupWatcher.groupItems().get("item1"); v != null; v = provider.groupWatcher.groupItems().get("item1")) {
+ }
+ assertNull(provider.groupWatcher.groupItems().get("item1"));
+
+ //test modify item2
+ client.putValue("test-module.default.testKeyGroup/item2", "300");
+ for (String v = provider.groupWatcher.groupItems().get("item2"); v.equals("200"); v = provider.groupWatcher.groupItems().get("item2")) {
+ }
+ assertEquals("300", provider.groupWatcher.groupItems().get("item2"));
+
+ //chean
+ client.deleteKey("test-module.default.testKeyGroup/item2");
+ }
+
@SuppressWarnings("unchecked")
private void loadConfig(ApplicationConfiguration configuration) throws FileNotFoundException {
Reader applicationReader = ResourceUtils.read("application.yml");
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
index 595cbe6..62f422b 100644
--- 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
@@ -88,7 +88,7 @@ public class ITNacosConfigurationTest {
@Test(timeout = 20000)
public void shouldReadUpdatedGroup() throws NacosException {
- assertNull(provider.watcher.value());
+ assertEquals("{}", provider.groupWatcher.groupItems().toString());
final Properties properties = new Properties();
final String nacosHost = System.getProperty("nacos.host");