From c8e839d10825859644ba6748364cc7de388f109e Mon Sep 17 00:00:00 2001 From: shawyeok Date: Wed, 7 Jul 2021 23:09:02 +0800 Subject: [PATCH] Reduce bootstrap time in the situation with large properties (#3800) --- CHANGES.md | 1 + .../ApolloApplicationContextInitializer.java | 15 ++- .../config/CachedCompositePropertySource.java | 66 ++++++++++ .../spring/config/ConfigPropertySource.java | 5 + .../config/PropertySourcesProcessor.java | 7 +- .../framework/apollo/util/ConfigUtil.java | 26 ++++ .../spring/JavaConfigAnnotationTest.java | 10 +- ...olloApplicationContextInitializerTest.java | 36 +++++- .../CachedCompositePropertySourceTest.java | 122 ++++++++++++++++++ .../framework/apollo/util/ConfigUtilTest.java | 11 ++ .../apollo/core/ApolloClientSystemConsts.java | 10 ++ docs/zh/usage/java-sdk-user-guide.md | 20 +++ 12 files changed, 323 insertions(+), 6 deletions(-) create mode 100644 apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySource.java create mode 100644 apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySourceTest.java diff --git a/CHANGES.md b/CHANGES.md index 390a37d6b4b..13b58679325 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -57,6 +57,7 @@ Apollo 1.9.0 * [speed up the stale issue mark and close phase](https://github.com/ctripcorp/apollo/pull/3808) * [feature: add the delegating password encoder for apollo-portal simple auth](https://github.com/ctripcorp/apollo/pull/3804) * [support release apollo-client-config-data](https://github.com/ctripcorp/apollo/pull/3822) +* [Reduce bootstrap time in the situation with large properties](https://github.com/ctripcorp/apollo/pull/3816) ------------------ All issues and pull requests are [here](https://github.com/ctripcorp/apollo/milestone/6?closed=1) diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java index 32ee605cadb..c53870164c5 100644 --- a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java @@ -18,12 +18,15 @@ import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigService; +import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.ApolloClientSystemConsts; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.utils.DeferredLogger; +import com.ctrip.framework.apollo.spring.config.CachedCompositePropertySource; import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory; import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants; import com.ctrip.framework.apollo.spring.util.SpringInjector; +import com.ctrip.framework.apollo.util.ConfigUtil; import com.google.common.base.Splitter; import com.google.common.base.Strings; import java.util.List; @@ -85,11 +88,14 @@ public class ApolloApplicationContextInitializer implements ApolloClientSystemConsts.APOLLO_ACCESS_KEY_SECRET, ApolloClientSystemConsts.APOLLO_META, ApolloClientSystemConsts.APOLLO_CONFIG_SERVICE, - ApolloClientSystemConsts.APOLLO_PROPERTY_ORDER_ENABLE}; + ApolloClientSystemConsts.APOLLO_PROPERTY_ORDER_ENABLE, + ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE}; private final ConfigPropertySourceFactory configPropertySourceFactory = SpringInjector .getInstance(ConfigPropertySourceFactory.class); + private final ConfigUtil configUtil = ApolloInjector.getInstance(ConfigUtil.class); + private int order = DEFAULT_ORDER; @Override @@ -123,7 +129,12 @@ protected void initialize(ConfigurableEnvironment environment) { logger.debug("Apollo bootstrap namespaces: {}", namespaces); List namespaceList = NAMESPACE_SPLITTER.splitToList(namespaces); - CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); + CompositePropertySource composite; + if (configUtil.isPropertyNamesCacheEnabled()) { + composite = new CachedCompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); + } else { + composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); + } for (String namespace : namespaceList) { Config config = ConfigService.getConfig(namespace); diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySource.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySource.java new file mode 100644 index 00000000000..022d94159f0 --- /dev/null +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySource.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 Apollo Authors + * + * Licensed 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 com.ctrip.framework.apollo.spring.config; + +import com.ctrip.framework.apollo.ConfigChangeListener; +import com.ctrip.framework.apollo.model.ConfigChangeEvent; +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.PropertySource; + +/** + * @author Shawyeok (shawyeok@outlook.com) + */ +public class CachedCompositePropertySource extends CompositePropertySource implements + ConfigChangeListener { + + private volatile String[] names; + + public CachedCompositePropertySource(String name) { + super(name); + } + + @Override + public String[] getPropertyNames() { + String[] propertyNames = this.names; + if (propertyNames == null) { + this.names = propertyNames = super.getPropertyNames(); + } + return propertyNames; + } + + @Override + public void addPropertySource(PropertySource propertySource) { + super.addPropertySource(propertySource); + if (propertySource instanceof ConfigPropertySource) { + ((ConfigPropertySource) propertySource).addChangeListener(this); + } + } + + @Override + public void addFirstPropertySource(PropertySource propertySource) { + super.addFirstPropertySource(propertySource); + if (propertySource instanceof ConfigPropertySource) { + ((ConfigPropertySource) propertySource).addChangeListener(this); + } + } + + @Override + public void onChange(ConfigChangeEvent changeEvent) { + // clear property names cache if any sources has changed + this.names = null; + } +} diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java index 298ce798d74..e740e86b3e7 100644 --- a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java @@ -35,6 +35,11 @@ public class ConfigPropertySource extends EnumerablePropertySource { super(name, source); } + @Override + public boolean containsProperty(String name) { + return this.source.getProperty(name, null) != null; + } + @Override public String[] getPropertyNames() { Set propertyNames = this.source.getPropertyNames(); diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java index 7649f69e693..8baa79a8724 100644 --- a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java @@ -80,7 +80,12 @@ private void initializePropertySources() { //already initialized return; } - CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME); + CompositePropertySource composite; + if (configUtil.isPropertyNamesCacheEnabled()) { + composite = new CachedCompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME); + } else { + composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME); + } //sort by order asc ImmutableSortedSet orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet()); diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java index 26474aec5a4..d55bf334867 100644 --- a/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java @@ -56,6 +56,7 @@ public class ConfigUtil { private boolean autoUpdateInjectedSpringProperties = true; private final RateLimiter warnLogRateLimiter; private boolean propertiesOrdered = false; + private boolean propertyNamesCacheEnabled = false; public ConfigUtil() { warnLogRateLimiter = RateLimiter.create(0.017); // 1 warning log output per minute @@ -68,6 +69,7 @@ public ConfigUtil() { initLongPollingInitialDelayInMills(); initAutoUpdateInjectedSpringProperties(); initPropertiesOrdered(); + initPropertyNamesCacheEnabled(); } /** @@ -394,4 +396,28 @@ private void initPropertiesOrdered() { public boolean isPropertiesOrderEnabled() { return propertiesOrdered; } + + public boolean isPropertyNamesCacheEnabled() { + return propertyNamesCacheEnabled; + } + + private void initPropertyNamesCacheEnabled() { + String propertyName = ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE; + String propertyEnvName = ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE_ENVIRONMENT_VARIABLES; + String enablePropertyNamesCache = System.getProperty(propertyName); + if (Strings.isNullOrEmpty(enablePropertyNamesCache)) { + enablePropertyNamesCache = System.getenv(propertyEnvName); + } + if (Strings.isNullOrEmpty(enablePropertyNamesCache)) { + enablePropertyNamesCache = Foundation.app().getProperty(propertyName, "false"); + } + if (!Strings.isNullOrEmpty(enablePropertyNamesCache)) { + try { + propertyNamesCacheEnabled = Boolean.parseBoolean(enablePropertyNamesCache); + } catch (Throwable ex) { + logger.warn("Config for {} is invalid: {}, set default value: false", + propertyName, enablePropertyNamesCache); + } + } + } } diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java index ba30015d8c1..fb0e34edc10 100644 --- a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java @@ -19,6 +19,7 @@ import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigChangeListener; import com.ctrip.framework.apollo.ConfigFileChangeListener; +import com.ctrip.framework.apollo.core.ApolloClientSystemConsts; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.internals.SimpleConfig; import com.ctrip.framework.apollo.internals.YamlConfigFile; @@ -93,6 +94,7 @@ public void tearDown() throws Exception { System.clearProperty(SystemPropertyKeyConstants.FROM_SYSTEM_YAML_NAMESPACE); System.clearProperty(SystemPropertyKeyConstants.FROM_NAMESPACE_APPLICATION_KEY); System.clearProperty(SystemPropertyKeyConstants.FROM_NAMESPACE_APPLICATION_KEY_YAML); + System.clearProperty(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE); super.tearDown(); } @@ -456,13 +458,17 @@ public void testApolloConfigChangeListenerResolveExpressionSimple() { Config applicationConfig = mock(Config.class); mockConfig(ConfigConsts.NAMESPACE_APPLICATION, applicationConfig); + System.setProperty(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE, "true"); + getSimpleBean(TestApolloConfigChangeListenerResolveExpressionSimpleConfiguration.class); // no using verify(ignoreConfig, never()).addChangeListener(any(ConfigChangeListener.class)); - // one invocation for spring value auto update and another for the @ApolloConfigChangeListener annotation - verify(applicationConfig, times(2)).addChangeListener(any(ConfigChangeListener.class)); + // one invocation for spring value auto update + // one invocation for the @ApolloConfigChangeListener annotation + // one invocation for CachedCompositePropertySource clear cache listener + verify(applicationConfig, times(3)).addChangeListener(any(ConfigChangeListener.class)); } /** diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializerTest.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializerTest.java index 316ad5476e4..57331c95aeb 100644 --- a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializerTest.java +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializerTest.java @@ -18,14 +18,20 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; -import com.ctrip.framework.apollo.core.ConfigConsts; +import com.ctrip.framework.apollo.build.MockInjector; import com.ctrip.framework.apollo.core.ApolloClientSystemConsts; +import com.ctrip.framework.apollo.core.ConfigConsts; +import com.ctrip.framework.apollo.spring.config.CachedCompositePropertySource; +import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants; +import com.ctrip.framework.apollo.util.ConfigUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MutablePropertySources; public class ApolloApplicationContextInitializerTest { @@ -42,6 +48,8 @@ public void tearDown() throws Exception { System.clearProperty(ConfigConsts.APOLLO_CLUSTER_KEY); System.clearProperty(ApolloClientSystemConsts.APOLLO_CACHE_DIR); System.clearProperty(ConfigConsts.APOLLO_META_KEY); + + MockInjector.reset(); } @Test @@ -109,4 +117,30 @@ public void testFillFromEnvironmentWithNoPropertyFromEnvironment() throws Except assertNull(System.getProperty(ApolloClientSystemConsts.APOLLO_CACHE_DIR)); assertNull(System.getProperty(ConfigConsts.APOLLO_META_KEY)); } + + @Test + public void testPropertyNamesCacheEnabled() { + ConfigurableEnvironment environment = mock(ConfigurableEnvironment.class); + MutablePropertySources propertySources = new MutablePropertySources(); + when(environment.getPropertySources()).thenReturn(propertySources); + when(environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES, + ConfigConsts.NAMESPACE_APPLICATION)).thenReturn(""); + + apolloApplicationContextInitializer.initialize(environment); + + assertTrue(propertySources.contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)); + assertFalse(propertySources.iterator().next() instanceof CachedCompositePropertySource); + + ConfigUtil configUtil = new ConfigUtil(); + configUtil = spy(configUtil); + when(configUtil.isPropertyNamesCacheEnabled()).thenReturn(true); + MockInjector.setInstance(ConfigUtil.class, configUtil); + apolloApplicationContextInitializer = new ApolloApplicationContextInitializer(); + propertySources.remove(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); + + apolloApplicationContextInitializer.initialize(environment); + + assertTrue(propertySources.contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)); + assertTrue(propertySources.iterator().next() instanceof CachedCompositePropertySource); + } } diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySourceTest.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySourceTest.java new file mode 100644 index 00000000000..b4e763045bd --- /dev/null +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/CachedCompositePropertySourceTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2021 Apollo Authors + * + * Licensed 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 com.ctrip.framework.apollo.spring.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.ctrip.framework.apollo.ConfigChangeListener; +import com.ctrip.framework.apollo.model.ConfigChangeEvent; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.assertj.core.util.Arrays; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; +import org.springframework.core.env.PropertySource; + +/** + * @author Shawyeok (shawyeok@outlook.com) + */ +@RunWith(MockitoJUnitRunner.class) +public class CachedCompositePropertySourceTest { + + private CachedCompositePropertySource compositeSource; + + @Mock + private ConfigPropertySource configPropertySource; + + private List listeners; + + @Before + public void setUp() throws Exception { + compositeSource = new CachedCompositePropertySource("testCompositeSource"); + listeners = new LinkedList<>(); + Mockito.doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ConfigChangeListener listener = invocation.getArgumentAt(0, ConfigChangeListener.class); + listeners.add(listener); + return Void.class; + } + }).when(configPropertySource).addChangeListener(any(ConfigChangeListener.class)); + compositeSource.addPropertySource(configPropertySource); + } + + @Test + public void testGetPropertyNames() { + String[] propertyNames = Arrays.array("propertyName"); + String[] anotherPropertyNames = Arrays.array("propertyName", "anotherPropertyName"); + + when(configPropertySource.getPropertyNames()).thenReturn(propertyNames, anotherPropertyNames); + + String[] returnedPropertyNames = compositeSource.getPropertyNames(); + assertArrayEquals(propertyNames, returnedPropertyNames); + assertSame(returnedPropertyNames, compositeSource.getPropertyNames()); + + listeners.get(0).onChange(new ConfigChangeEvent(null, null)); + + returnedPropertyNames = compositeSource.getPropertyNames(); + assertArrayEquals(anotherPropertyNames, returnedPropertyNames); + assertSame(returnedPropertyNames, compositeSource.getPropertyNames()); + } + + @Test + public void testAddPropertySource() { + verify(configPropertySource, times(1)) + .addChangeListener(any(CachedCompositePropertySource.class)); + assertEquals(1, listeners.size()); + assertTrue(compositeSource.getPropertySources().contains(configPropertySource)); + } + + @Test + public void testAddFirstPropertySource() { + ConfigPropertySource anotherSource = mock(ConfigPropertySource.class); + final List anotherListenerList = new LinkedList<>(); + Mockito.doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ConfigChangeListener listener = invocation.getArgumentAt(0, ConfigChangeListener.class); + anotherListenerList.add(listener); + return Void.class; + } + }).when(anotherSource).addChangeListener(any(ConfigChangeListener.class)); + compositeSource.addFirstPropertySource(anotherSource); + + Collection> propertySources = compositeSource.getPropertySources(); + Iterator> it = propertySources.iterator(); + + assertEquals(2, propertySources.size()); + assertEquals(1, anotherListenerList.size()); + assertSame(anotherSource, it.next()); + assertSame(configPropertySource, it.next()); + } +} \ No newline at end of file diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java index 7947e8c25ef..31e5e9dea6e 100644 --- a/apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java @@ -46,6 +46,7 @@ public void tearDown() throws Exception { System.clearProperty("apollo.autoUpdateInjectedSpringProperties"); System.clearProperty(ApolloClientSystemConsts.APOLLO_CACHE_DIR); System.clearProperty(PropertiesFactory.APOLLO_PROPERTY_ORDER_ENABLE); + System.clearProperty(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE); } @Test @@ -253,4 +254,14 @@ public void testCustomizePropertiesOrdered() { assertEquals(propertiesOrdered, configUtil.isPropertiesOrderEnabled()); } + + @Test + public void test() { + ConfigUtil configUtil = new ConfigUtil(); + assertFalse(configUtil.isPropertyNamesCacheEnabled()); + + System.setProperty(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE, "true"); + configUtil = new ConfigUtil(); + assertTrue(configUtil.isPropertyNamesCacheEnabled()); + } } diff --git a/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ApolloClientSystemConsts.java b/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ApolloClientSystemConsts.java index 7757a460476..75611eeb844 100644 --- a/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ApolloClientSystemConsts.java +++ b/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ApolloClientSystemConsts.java @@ -126,4 +126,14 @@ public class ApolloClientSystemConsts { * enable property order environment variables */ public static final String APOLLO_PROPERTY_ORDER_ENABLE_ENVIRONMENT_VARIABLES = "APOLLO_PROPERTY_ORDER_ENABLE"; + + /** + * enable property names cache + */ + public static final String APOLLO_PROPERTY_NAMES_CACHE_ENABLE = "apollo.property.names.cache.enable"; + + /** + * enable property names cache environment variables + */ + public static final String APOLLO_PROPERTY_NAMES_CACHE_ENABLE_ENVIRONMENT_VARIABLES = "APOLLO_PROPERTY_NAMES_CACHE_ENABLE"; } diff --git a/docs/zh/usage/java-sdk-user-guide.md b/docs/zh/usage/java-sdk-user-guide.md index bd53c8fe04d..ebaa9057270 100644 --- a/docs/zh/usage/java-sdk-user-guide.md +++ b/docs/zh/usage/java-sdk-user-guide.md @@ -317,6 +317,26 @@ Apollo从1.6.0版本开始增加访问密钥机制,从而只有经过身份验 * 可以通过操作系统的System Environment `APOLLO_PATH_SERVER_PROPERTIES`来指定 * 注意key为全大写,且中间是`_`分隔 +#### 1.2.4.6 开启`propertyNames`缓存,在大量配置场景下可以显著改善启动速度 + +> 适用于1.9.0及以上版本 + +在使用`@ConfigurationProperties`和存在大量配置项场景下,Spring容器的启动速度会变慢。通过开启该配置可以显著提升启动速度,当配置发生变化时缓存会自动清理,默认为`false`。详见:[issue 3800](https://github.com/ctripcorp/apollo/issues/3800) + +配置方式按照优先级从高到低依次为: +1. 通过Java System Property `apollo.property.names.cache.enable` + * 可以通过Java的System Property `apollo.property.names.cache.enable`来指定 + * 在Java程序启动脚本中,可以指定`-Dapollo.property.names.cache.enable=true` + * 如果是运行jar文件,需要注意格式是`java -Dapollo.property.names.cache.enable=true -jar xxx.jar` + * 也可以通过程序指定,如`System.setProperty("apollo.property.names.cache.enable", "true");` +2. 通过系统环境变量 + * 在启动程序前配置环境变量`APOLLO_PROPERTY_NAMES_CACHE_ENABLE=true`来指定 + * 注意key为全大写,且中间是`_`分隔 +3. 通过Spring Boot的配置文件 + * 可以在Spring Boot的`application.properties`或`bootstrap.properties`中指定`apollo.property.names.cache.enable=true` +4. 通过`app.properties`配置文件 + * 可以在`classpath:/META-INF/app.properties`指定`apollo.property.names.cache.enable=true` + # 二、Maven Dependency Apollo的客户端jar包已经上传到中央仓库,应用在实际使用时只需要按照如下方式引入即可。 ```xml