diff --git a/CHANGES.md b/CHANGES.md index 4d97eead265..d6f1df67765 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ Apollo 2.2.0 * [Fix the issue of the system permission management page retrieving non-existent users](https://github.com/apolloconfig/apollo/pull/4802) * [Add release history cleaning function](https://github.com/apolloconfig/apollo/pull/4813) * [[Multi-Database Support][pg] Make JdbcUserDetailsManager compat with postgre](https://github.com/apolloconfig/apollo/pull/4790) +* [Add a configuration config-service.cache.key.ignore-case to control whether the cache key is case-sensitive](https://github.com/apolloconfig/apollo/pull/4820) ------------------ All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/13?closed=1) \ No newline at end of file diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java index 1d87cd07e07..a43218870eb 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java @@ -205,6 +205,10 @@ public boolean isConfigServiceCacheEnabled() { return getBooleanProperty("config-service.cache.enabled", false); } + public boolean isConfigServiceCacheKeyIgnoreCase() { + return getBooleanProperty("config-service.cache.key.ignore-case", false); + } + int checkInt(int value, int min, int max, int defaultValue) { if (value >= min && value <= max) { return value; diff --git a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java index 53bb003f077..4e722725692 100644 --- a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java +++ b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java @@ -27,6 +27,8 @@ import org.springframework.test.util.ReflectionTestUtils; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; /** @@ -124,4 +126,11 @@ public void testCheckInt() throws Exception { assertEquals(someValidValue, bizConfig.checkInt(someValidValue, Integer.MIN_VALUE, Integer.MAX_VALUE, someDefaultValue)); } + + @Test + public void testIsConfigServiceCacheKeyIgnoreCase() { + assertFalse(bizConfig.isConfigServiceCacheKeyIgnoreCase()); + when(environment.getProperty("config-service.cache.key.ignore-case")).thenReturn("true"); + assertTrue(bizConfig.isConfigServiceCacheKeyIgnoreCase()); + } } diff --git a/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java b/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java index ba6a31877ac..db472518c44 100644 --- a/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java +++ b/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java @@ -67,7 +67,7 @@ public GrayReleaseRulesHolder grayReleaseRulesHolder() { public ConfigService configService() { if (bizConfig.isConfigServiceCacheEnabled()) { return new ConfigServiceWithCache(releaseService, releaseMessageService, - grayReleaseRulesHolder()); + grayReleaseRulesHolder(), bizConfig); } return new DefaultConfigService(releaseService, grayReleaseRulesHolder()); } diff --git a/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCache.java b/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCache.java index db4c0111506..8fe981fe0be 100644 --- a/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCache.java +++ b/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCache.java @@ -17,6 +17,7 @@ package com.ctrip.framework.apollo.configservice.service.config; import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; +import com.ctrip.framework.apollo.biz.config.BizConfig; import com.google.common.base.Strings; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -61,6 +62,7 @@ public class ConfigServiceWithCache extends AbstractConfigService { private final ReleaseService releaseService; private final ReleaseMessageService releaseMessageService; + private final BizConfig bizConfig; private LoadingCache configCache; @@ -70,10 +72,12 @@ public class ConfigServiceWithCache extends AbstractConfigService { public ConfigServiceWithCache(final ReleaseService releaseService, final ReleaseMessageService releaseMessageService, - final GrayReleaseRulesHolder grayReleaseRulesHolder) { + final GrayReleaseRulesHolder grayReleaseRulesHolder, + final BizConfig bizConfig) { super(grayReleaseRulesHolder); this.releaseService = releaseService; this.releaseMessageService = releaseMessageService; + this.bizConfig = bizConfig; nullConfigCacheEntry = new ConfigCacheEntry(ConfigConsts.NOTIFICATION_ID_PLACEHOLDER, null); } @@ -147,18 +151,23 @@ protected Release findActiveOne(long id, ApolloNotificationMessages clientMessag @Override protected Release findLatestActiveRelease(String appId, String clusterName, String namespaceName, ApolloNotificationMessages clientMessages) { - String key = ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName); + String messageKey = ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName); + String cacheKey = messageKey; - Tracer.logEvent(TRACER_EVENT_CACHE_GET, key); + if (bizConfig.isConfigServiceCacheKeyIgnoreCase()) { + cacheKey = cacheKey.toLowerCase(); + } + + Tracer.logEvent(TRACER_EVENT_CACHE_GET, cacheKey); - ConfigCacheEntry cacheEntry = configCache.getUnchecked(key); + ConfigCacheEntry cacheEntry = configCache.getUnchecked(cacheKey); //cache is out-dated - if (clientMessages != null && clientMessages.has(key) && - clientMessages.get(key) > cacheEntry.getNotificationId()) { + if (clientMessages != null && clientMessages.has(messageKey) && + clientMessages.get(messageKey) > cacheEntry.getNotificationId()) { //invalidate the cache and try to load from db again - invalidate(key); - cacheEntry = configCache.getUnchecked(key); + invalidate(cacheKey); + cacheEntry = configCache.getUnchecked(cacheKey); } return cacheEntry.getRelease(); @@ -177,10 +186,14 @@ public void handleMessage(ReleaseMessage message, String channel) { } try { - invalidate(message.getMessage()); + String messageKey = message.getMessage(); + if (bizConfig.isConfigServiceCacheKeyIgnoreCase()) { + messageKey = messageKey.toLowerCase(); + } + invalidate(messageKey); //warm up the cache - configCache.getUnchecked(message.getMessage()); + configCache.getUnchecked(messageKey); } catch (Throwable ex) { //ignore } diff --git a/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheAndCacheKeyIgnoreCaseTest.java b/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheAndCacheKeyIgnoreCaseTest.java new file mode 100644 index 00000000000..d9d30b69408 --- /dev/null +++ b/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheAndCacheKeyIgnoreCaseTest.java @@ -0,0 +1,382 @@ +/* + * Copyright 2023 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.configservice.service.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.matches; +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.biz.config.BizConfig; +import com.ctrip.framework.apollo.biz.entity.Release; +import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; +import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; +import com.ctrip.framework.apollo.biz.message.Topics; +import com.ctrip.framework.apollo.biz.service.ReleaseMessageService; +import com.ctrip.framework.apollo.biz.service.ReleaseService; +import com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator; +import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; +import com.google.common.collect.Lists; +import java.util.regex.Pattern; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * @author kl (http://kailing.pub) + * @since 2023/3/28 + */ +@RunWith(MockitoJUnitRunner.class) +public class ConfigServiceWithCacheAndCacheKeyIgnoreCaseTest { + + private ConfigServiceWithCache configServiceWithCache; + + @Mock + private ReleaseService releaseService; + @Mock + private ReleaseMessageService releaseMessageService; + @Mock + private Release someRelease; + @Mock + private ReleaseMessage someReleaseMessage; + @Mock + private BizConfig bizConfig; + @Mock + private GrayReleaseRulesHolder grayReleaseRulesHolder; + + private String someAppId; + private String someClusterName; + private String someNamespaceName; + private String lowerCaseSomeKey; + private String normalSomeKey; + private long someNotificationId; + private ApolloNotificationMessages someNotificationMessages; + + @Before + public void setUp() throws Exception { + configServiceWithCache = new ConfigServiceWithCache(releaseService, releaseMessageService, + grayReleaseRulesHolder, bizConfig); + + when(bizConfig.isConfigServiceCacheKeyIgnoreCase()).thenReturn(true); + + configServiceWithCache.initialize(); + + someAppId = "someAppId"; + someClusterName = "someClusterName"; + someNamespaceName = "someNamespaceName"; + someNotificationId = 1; + + normalSomeKey = ReleaseMessageKeyGenerator.generate(someAppId, someClusterName, someNamespaceName); + lowerCaseSomeKey = normalSomeKey.toLowerCase(); + someNotificationMessages = new ApolloNotificationMessages(); + } + + @Test + public void testFindActiveOne() { + long someId = 1; + + when(releaseService.findActiveOne(someId)).thenReturn(someRelease); + + assertEquals(someRelease, + configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + verify(releaseService, times(1)).findActiveOne(someId); + } + + @Test + public void testFindActiveOneWithSameIdMultipleTimes() { + long someId = 1; + + when(releaseService.findActiveOne(someId)).thenReturn(someRelease); + + assertEquals(someRelease, + configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + assertEquals(someRelease, + configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + assertEquals(someRelease, + configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + + verify(releaseService, times(1)).findActiveOne(someId); + } + + @Test + public void testFindActiveOneWithMultipleIdMultipleTimes() { + long someId = 1; + long anotherId = 2; + Release anotherRelease = mock(Release.class); + + when(releaseService.findActiveOne(someId)).thenReturn(someRelease); + when(releaseService.findActiveOne(anotherId)).thenReturn(anotherRelease); + + assertEquals(someRelease, + configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + assertEquals(someRelease, + configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + + assertEquals(anotherRelease, + configServiceWithCache.findActiveOne(anotherId, someNotificationMessages)); + assertEquals(anotherRelease, + configServiceWithCache.findActiveOne(anotherId, someNotificationMessages)); + + verify(releaseService, times(1)).findActiveOne(someId); + verify(releaseService, times(1)).findActiveOne(anotherId); + } + + @Test + public void testFindActiveOneWithReleaseNotFoundMultipleTimes() { + long someId = 1; + + when(releaseService.findActiveOne(someId)).thenReturn(null); + + assertNull(configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + assertNull(configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + assertNull(configServiceWithCache.findActiveOne(someId, someNotificationMessages)); + + verify(releaseService, times(1)).findActiveOne(someId); + } + + @Test + public void testFindLatestActiveRelease() { + when(releaseMessageService.findLatestReleaseMessageForMessages(Lists.newArrayList(lowerCaseSomeKey))) + .thenReturn(someReleaseMessage); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(someRelease); + when(someReleaseMessage.getId()).thenReturn(someNotificationId); + + Release release = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, someNotificationMessages); + Release anotherRelease = configServiceWithCache.findLatestActiveRelease(someAppId, + someClusterName, someNamespaceName, someNotificationMessages); + + int retryTimes = 100; + + for (int i = 0; i < retryTimes; i++) { + configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, someNotificationMessages); + } + + assertEquals(someRelease, release); + assertEquals(someRelease, anotherRelease); + + verify(releaseMessageService, times(1)).findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey)); + verify(releaseService, times(1)).findLatestActiveRelease( + someAppId.toLowerCase(), + someClusterName.toLowerCase(), + someNamespaceName.toLowerCase()); + } + + @Test + public void testFindLatestActiveReleaseWithReleaseNotFound() { + when(releaseMessageService.findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey))).thenReturn(null); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(null); + + Release release = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, + someNotificationMessages); + Release anotherRelease = configServiceWithCache.findLatestActiveRelease(someAppId, + someClusterName, + someNamespaceName, someNotificationMessages); + + int retryTimes = 100; + + for (int i = 0; i < retryTimes; i++) { + configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, someNotificationMessages); + } + + assertNull(release); + assertNull(anotherRelease); + + verify(releaseMessageService, times(1)).findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey)); + verify(releaseService, times(1)).findLatestActiveRelease( + someAppId.toLowerCase(), + someClusterName.toLowerCase(), + someNamespaceName.toLowerCase()); + } + + @Test + public void testFindLatestActiveReleaseWithDirtyRelease() { + long someNewNotificationId = someNotificationId + 1; + ReleaseMessage anotherReleaseMessage = mock(ReleaseMessage.class); + Release anotherRelease = mock(Release.class); + + when(releaseMessageService.findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey))).thenReturn + (someReleaseMessage); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(someRelease); + when(someReleaseMessage.getId()).thenReturn(someNotificationId); + + Release release = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, + someNotificationMessages); + + when(releaseMessageService.findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey))).thenReturn(anotherReleaseMessage); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(anotherRelease); + when(anotherReleaseMessage.getId()).thenReturn(someNewNotificationId); + + Release stillOldRelease = configServiceWithCache.findLatestActiveRelease(someAppId, + someClusterName, + someNamespaceName, someNotificationMessages); + + someNotificationMessages.put( + ReleaseMessageKeyGenerator.generate(someAppId, someClusterName, someNamespaceName), + someNewNotificationId); + + Release shouldBeNewRelease = configServiceWithCache.findLatestActiveRelease(someAppId, + someClusterName, + someNamespaceName, someNotificationMessages); + + assertEquals(someRelease, release); + assertEquals(someRelease, stillOldRelease); + assertEquals(anotherRelease, shouldBeNewRelease); + + verify(releaseMessageService, times(2)).findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey)); + verify(releaseService, times(2)).findLatestActiveRelease( + someAppId.toLowerCase(), + someClusterName.toLowerCase(), + someNamespaceName.toLowerCase()); + } + + @Test + public void testFindLatestActiveReleaseWithReleaseMessageNotification() { + long someNewNotificationId = someNotificationId + 1; + ReleaseMessage anotherReleaseMessage = mock(ReleaseMessage.class); + Release anotherRelease = mock(Release.class); + + when(releaseMessageService.findLatestReleaseMessageForMessages(Lists.newArrayList(lowerCaseSomeKey))) + .thenReturn(someReleaseMessage); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(someRelease); + when(someReleaseMessage.getId()).thenReturn(someNotificationId); + + Release release = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, + someNotificationMessages); + + when(releaseMessageService.findLatestReleaseMessageForMessages(Lists.newArrayList(lowerCaseSomeKey))) + .thenReturn(anotherReleaseMessage); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(anotherRelease); + + when(anotherReleaseMessage.getMessage()).thenReturn(lowerCaseSomeKey); + when(anotherReleaseMessage.getId()).thenReturn(someNewNotificationId); + + Release stillOldRelease = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, someNotificationMessages); + + configServiceWithCache.handleMessage(anotherReleaseMessage, Topics.APOLLO_RELEASE_TOPIC); + + Release shouldBeNewRelease = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, someNotificationMessages); + + assertEquals(someRelease, release); + assertEquals(someRelease, stillOldRelease); + assertEquals(anotherRelease, shouldBeNewRelease); + + verify(releaseMessageService, times(2)).findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey)); + verify(releaseService, times(2)).findLatestActiveRelease( + someAppId.toLowerCase(), + someClusterName.toLowerCase(), + someNamespaceName.toLowerCase()); + + when(anotherReleaseMessage.getMessage()).thenReturn(normalSomeKey); + when(anotherReleaseMessage.getId()).thenReturn(someNewNotificationId); + + configServiceWithCache.handleMessage(anotherReleaseMessage, Topics.APOLLO_RELEASE_TOPIC); + + shouldBeNewRelease = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, someNotificationMessages); + assertEquals(anotherRelease, shouldBeNewRelease); + } + + @Test + public void testFindLatestActiveReleaseWithIrrelevantMessages() { + long someNewNotificationId = someNotificationId + 1; + String someIrrelevantKey = "someIrrelevantKey"; + + when(releaseMessageService.findLatestReleaseMessageForMessages(Lists.newArrayList(lowerCaseSomeKey))) + .thenReturn(someReleaseMessage); + when(releaseService.findLatestActiveRelease( + matchesCaseInsensitive(someAppId), + matchesCaseInsensitive(someClusterName), + matchesCaseInsensitive(someNamespaceName) + )).thenReturn(someRelease); + when(someReleaseMessage.getId()).thenReturn(someNotificationId); + + Release release = configServiceWithCache.findLatestActiveRelease(someAppId, someClusterName, + someNamespaceName, + someNotificationMessages); + + Release stillOldRelease = configServiceWithCache.findLatestActiveRelease(someAppId, + someClusterName, + someNamespaceName, someNotificationMessages); + + someNotificationMessages.put(someIrrelevantKey, someNewNotificationId); + + Release shouldStillBeOldRelease = configServiceWithCache.findLatestActiveRelease(someAppId, + someClusterName, + someNamespaceName, someNotificationMessages); + + assertEquals(someRelease, release); + assertEquals(someRelease, stillOldRelease); + assertEquals(someRelease, shouldStillBeOldRelease); + + verify(releaseMessageService, times(1)).findLatestReleaseMessageForMessages( + Lists.newArrayList(lowerCaseSomeKey)); + verify(releaseService, times(1)).findLatestActiveRelease( + someAppId.toLowerCase(), + someClusterName.toLowerCase(), + someNamespaceName.toLowerCase()); + } + + private String matchesCaseInsensitive(final String regex) { + return matches(Pattern.compile(regex, Pattern.CASE_INSENSITIVE)); + } + +} diff --git a/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheTest.java b/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheTest.java index 179c808b6b8..266ca174cc4 100644 --- a/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheTest.java +++ b/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCacheTest.java @@ -17,6 +17,7 @@ package com.ctrip.framework.apollo.configservice.service.config; import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; +import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import com.google.common.collect.Lists; @@ -56,6 +57,8 @@ public class ConfigServiceWithCacheTest { @Mock private ReleaseMessage someReleaseMessage; @Mock + private BizConfig bizConfig; + @Mock private GrayReleaseRulesHolder grayReleaseRulesHolder; private String someAppId; @@ -68,7 +71,8 @@ public class ConfigServiceWithCacheTest { @Before public void setUp() throws Exception { configServiceWithCache = new ConfigServiceWithCache(releaseService, releaseMessageService, - grayReleaseRulesHolder); + grayReleaseRulesHolder, bizConfig); + configServiceWithCache.initialize(); someAppId = "someAppId"; diff --git a/docs/en/deployment/distributed-deployment-guide.md b/docs/en/deployment/distributed-deployment-guide.md index 59d011490c6..87592367e94 100644 --- a/docs/en/deployment/distributed-deployment-guide.md +++ b/docs/en/deployment/distributed-deployment-guide.md @@ -1500,10 +1500,17 @@ This is a function switch, if configured to true, config service will cache the The default is false. Please evaluate the total configuration size and adjust the config service memory configuration before turning it on. -> Ensure that the `app.id`、`apollo.cluster` of the configuration in the application is in the correct case when caching is enabled, otherwise it will not fetch the correct configuration +> Ensure that the `app.id`、`apollo.cluster` of the configuration in the application is in the correct case when caching is enabled, otherwise it will not fetch the correct configuration, You can also refer to the `config-service.cache.key.ignore-case` configuration for compatibility processing. > `config-service.cache.enabled` configuration adjustment requires a restart of the config service to take effect +#### 3.2.3.1 config-service.cache.key.ignore-case - whether to ignore the case of the configuration cache key +> For versions 2.2.0 and above + +This configuration takes effect when config-service.cache.enabled is set to true, and controls whether the configuration cache key ignores case. The default value is false, which means that cache keys are strictly case-sensitive. In this case, it is necessary to ensure that the capitalization of app.id and apollo.cluster configured in the application is correct, otherwise the correct configuration cannot be obtained. It can be configured as true to ignore case sensitivity. + +> This configuration is used to be compatible with the configuration acquisition logic when the cache is not enabled, because MySQL database queries are case-insensitive by default. If the cache is enabled and MySQL is used, it is recommended to configure it as true. If the database used by your Apollo is case-sensitive, you must keep the default configuration as false, otherwise the configuration cannot be obtained. + ### 3.2.4 `item.key.length.limit`- Maximum length limit for configuration item key The default configuration is 128. diff --git a/docs/zh/deployment/distributed-deployment-guide.md b/docs/zh/deployment/distributed-deployment-guide.md index 5da79cd3272..f26ffed58d0 100644 --- a/docs/zh/deployment/distributed-deployment-guide.md +++ b/docs/zh/deployment/distributed-deployment-guide.md @@ -1442,10 +1442,18 @@ http://5.5.5.5:8080/eureka/,http://6.6.6.6:8080/eureka/ 默认为false,开启前请先评估总配置大小并调整config service内存配置。 -> 开启缓存后必须确保应用中配置的`app.id`、`apollo.cluster`大小写正确,否则将获取不到正确的配置 +> 开启缓存后必须确保应用中配置的`app.id`、`apollo.cluster`大小写正确,否则将获取不到正确的配置,另可参考`config-service.cache.key.ignore-case`配置做兼容处理。 > `config-service.cache.enabled` 配置调整必须重启 config service 才能生效 +#### 3.2.3.1 config-service.cache.key.ignore-case - 是否忽略配置缓存key的大小写 +> 适用于2.2.0及以上版本 + +该配置作用于`config-service.cache.enabled`为 true 时,用于控制配置缓存key是否忽略大小写。 +默认为 false,即缓存键大小写严格匹配。此时需要确保应用中配置的`app.id`、`apollo.cluster`大小写正确,否则将获取不到正确的配置。可配置为 true, 则忽略大小写。 + +> 这个配置用于兼容未开启缓存时的配置获取逻辑,因为 MySQL 数据库查询默认字符串匹配大小写不敏感。如果开启了缓存,且用了 MySQL,建议配置 true。如果你 Apollo 使用的数据库字符串匹配大小写敏感,那么必须保持默认配置 false,否则将获取不到配置。 + ### 3.2.4 item.key.length.limit - 配置项 key 最大长度限制 默认配置是128。