From 1d52d883446f5cdca87a71c395c2f372df736b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=8E=E6=9C=A8=E5=81=A5?= Date: Fri, 17 Feb 2023 23:00:54 +0800 Subject: [PATCH 1/2] feat: load config in parallel way --- .../cloud/zookeeper/config/ConfigWatcher.java | 4 +- .../config/ZookeeperConfigDataLoader.java | 7 +- .../ZookeeperConfigDataLocationResolver.java | 2 +- .../config/ZookeeperConfigProperties.java | 14 +++ .../config/ZookeeperPropertySource.java | 34 +++++-- .../ZookeeperPropertySourceLocator.java | 12 --- .../config/ZookeeperPropertySources.java | 2 +- .../config/ZookeeperPropertySourceTests.java | 96 +++++++++++++++++++ 8 files changed, 143 insertions(+), 28 deletions(-) create mode 100644 spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceTests.java diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ConfigWatcher.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ConfigWatcher.java index f9411ee6d..0e342668b 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ConfigWatcher.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ConfigWatcher.java @@ -17,7 +17,7 @@ package org.springframework.cloud.zookeeper.config; import java.io.Closeable; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -124,7 +124,7 @@ public String getEventDesc(TreeCacheEvent event) { out.append(", path=").append(event.getData().getPath()); byte[] data = event.getData().getData(); if (data != null && data.length > 0) { - out.append(", data=").append(new String(data, Charset.forName("UTF-8"))); + out.append(", data=").append(new String(data, StandardCharsets.UTF_8)); } return out.toString(); } diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java index 06501a809..02f047f51 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java @@ -42,12 +42,13 @@ public ZookeeperConfigDataLoader(DeferredLogFactory logFactory) { public ConfigData load(ConfigDataLoaderContext context, ZookeeperConfigDataResource resource) { try { CuratorFramework curator = context.getBootstrapContext().get(CuratorFramework.class); - if (curator == null) { + ZookeeperConfigProperties properties = context.getBootstrapContext().get(ZookeeperConfigProperties.class); + if (curator == null || properties == null) { // this can happen if certain conditions are met return null; } - ZookeeperPropertySource propertySource = new ZookeeperPropertySource(resource.getContext(), - curator); + ZookeeperPropertySource propertySource = new ZookeeperPropertySource(resource.getContext(), curator, + properties); List propertySources = Collections.singletonList(propertySource); return new ConfigData(propertySources, source -> { diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolver.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolver.java index 2c4a119ab..004dbebe5 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolver.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolver.java @@ -87,7 +87,7 @@ public List resolveProfileSpecific(ConfigDataLocati // create locations ZookeeperConfigProperties properties = loadConfigProperties(context); - context.getBootstrapContext().register(ZookeeperConfigProperties.class, InstanceSupplier.of(properties)); + context.getBootstrapContext().registerIfAbsent(ZookeeperConfigProperties.class, InstanceSupplier.of(properties)); ZookeeperPropertySources sources = new ZookeeperPropertySources(properties, log); diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigProperties.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigProperties.java index ae55f1c1e..2ce00f2a8 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigProperties.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigProperties.java @@ -62,6 +62,11 @@ public class ZookeeperConfigProperties { */ private boolean failFast = true; + /** + * get config in parallel way. + */ + private boolean parallel = false; + public boolean isEnabled() { return this.enabled; } @@ -112,6 +117,14 @@ public void setFailFast(boolean failFast) { this.failFast = failFast; } + public boolean isParallel() { + return parallel; + } + + public void setParallel(boolean parallel) { + this.parallel = parallel; + } + @Override public String toString() { return new ToStringCreator(this) @@ -121,6 +134,7 @@ public String toString() { .append("defaultContext", defaultContext) .append("profileSeparator", profileSeparator) .append("failFast", failFast) + .append("parallel", parallel) .toString(); } diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java index 4cd6c03a7..d28aa7e35 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java @@ -16,11 +16,12 @@ package org.springframework.cloud.zookeeper.config; -import java.nio.charset.Charset; -import java.util.LinkedHashMap; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Stream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -40,10 +41,14 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource { private static final Log log = LogFactory.getLog(ZookeeperPropertySource.class); - private Map properties = new LinkedHashMap<>(); + private final ZookeeperConfigProperties zookeeperConfigProperties; - public ZookeeperPropertySource(String context, CuratorFramework source) { + private Map properties = new ConcurrentHashMap<>(256); + + public ZookeeperPropertySource(String context, CuratorFramework source, + ZookeeperConfigProperties zookeeperConfigProperties) { super(context, source); + this.zookeeperConfigProperties = zookeeperConfigProperties; findProperties(this.getContext(), null); } @@ -86,9 +91,20 @@ private void findProperties(String path, List children) { if (children == null || children.isEmpty()) { return; } - for (String child : children) { + + Stream childrenStream = children.stream(); + if (zookeeperConfigProperties.isParallel() && this.getContext().equals(path)) { + childrenStream = children.parallelStream(); + } + childrenStream.forEach(child -> { String childPath = path + "/" + child; - List childPathChildren = getChildren(childPath); + List childPathChildren = null; + try { + childPathChildren = getChildren(childPath); + } + catch (Exception e) { + ReflectionUtils.rethrowRuntimeException(e); + } byte[] bytes = getPropertyBytes(childPath); if (bytes == null || bytes.length == 0) { @@ -97,13 +113,13 @@ private void findProperties(String path, List children) { } } else { - registerKeyValue(childPath, - new String(bytes, Charset.forName("UTF-8"))); + registerKeyValue(childPath, new String(bytes, StandardCharsets.UTF_8)); } // Check children even if we have found a value for the current znode findProperties(childPath, childPathChildren); - } + }); + log.trace("leaving findProperties for path: " + path); } catch (Exception exception) { diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java index 8c184acd8..e019fcd99 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java @@ -107,16 +107,4 @@ public PropertySource locate(Environment environment) { @PreDestroy public void destroy() { } - - private PropertySource create(String context) { - return new ZookeeperPropertySource(context, this.curator); - } - - private void addProfiles(List contexts, String baseContext, - List profiles) { - for (String profile : profiles) { - contexts.add(baseContext + this.properties.getProfileSeparator() + profile); - } - } - } diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java index 0730ff1b5..06b11b67e 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java @@ -75,7 +75,7 @@ private void addProfiles(List contexts, String baseContext, List 1) { + assertThat(parallelElapsedTime).as("parallelElapsedTime").isLessThan(serialElapsedTime); + } + + Field propertiesField = ZookeeperPropertySource.class.getDeclaredField("properties"); + propertiesField.setAccessible(true); + Map serialPropertyMap = (Map) ReflectionUtils.getField(propertiesField, + serialPropertySource); + Map parallelPropertyMap = (Map) ReflectionUtils.getField(propertiesField, + parallelPropertySource); + assertThat(parallelPropertyMap).as("parallelPropertyMap").containsAllEntriesOf(serialPropertyMap); + } +} From 5d87d34c046765e9e5b77a161a45c8fb88188e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=8E=E6=9C=A8=E5=81=A5?= Date: Sat, 18 Feb 2023 13:23:56 +0800 Subject: [PATCH 2/2] test: remove time compare --- .../zookeeper/config/ZookeeperPropertySourceTests.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceTests.java b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceTests.java index 1f956b3a4..dd0ffca9f 100644 --- a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceTests.java +++ b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceTests.java @@ -69,21 +69,13 @@ public void loadConfigInParallel() throws Exception { this.curator.create().creatingParentsIfNeeded().forPath(path); this.curator.setData().forPath(path, "testPropValUpdate".getBytes()); } - long startTime = System.currentTimeMillis(); + ZookeeperConfigProperties properties = new ZookeeperConfigProperties(); properties.setParallel(true); ZookeeperPropertySource parallelPropertySource = new ZookeeperPropertySource(ROOT, curator, properties); - long parallelElapsedTime = System.currentTimeMillis() - startTime; - startTime = System.currentTimeMillis(); properties.setParallel(false); ZookeeperPropertySource serialPropertySource = new ZookeeperPropertySource(ROOT, curator, properties); - long serialElapsedTime = System.currentTimeMillis() - startTime; - - int processors = Runtime.getRuntime().availableProcessors(); - if (processors > 1) { - assertThat(parallelElapsedTime).as("parallelElapsedTime").isLessThan(serialElapsedTime); - } Field propertiesField = ZookeeperPropertySource.class.getDeclaredField("properties"); propertiesField.setAccessible(true);