Skip to content

Commit 699009f

Browse files
committed
Config service cache and namespace name normalization
1. Enable config cache to improve config service performance, just set config-service.cache.enabled to true in ServerConfig 2. Normalize the namespace name in case the one provided has character case issue
1 parent f68cb45 commit 699009f

File tree

44 files changed

+2363
-500
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2363
-500
lines changed

apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceBranchController.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer;
1616

1717
import org.springframework.beans.factory.annotation.Autowired;
18+
import org.springframework.transaction.annotation.Transactional;
1819
import org.springframework.web.bind.annotation.PathVariable;
1920
import org.springframework.web.bind.annotation.RequestBody;
2021
import org.springframework.web.bind.annotation.RequestMapping;
@@ -70,6 +71,7 @@ public GrayReleaseRuleDTO findBranchGrayRules(@PathVariable String appId,
7071
return ruleDTO;
7172
}
7273

74+
@Transactional
7375
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.PUT)
7476
public void updateBranchGrayRules(@PathVariable String appId, @PathVariable String clusterName,
7577
@PathVariable String namespaceName, @PathVariable String branchName,
@@ -87,6 +89,7 @@ public void updateBranchGrayRules(@PathVariable String appId, @PathVariable Stri
8789
Topics.APOLLO_RELEASE_TOPIC);
8890
}
8991

92+
@Transactional
9093
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}", method = RequestMethod.DELETE)
9194
public void deleteBranch(@PathVariable String appId, @PathVariable String clusterName,
9295
@PathVariable String namespaceName, @PathVariable String branchName,

apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseController.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public ReleaseDTO getLatest(@PathVariable("appId") String appId,
9494
return BeanUtils.transfrom(ReleaseDTO.class, release);
9595
}
9696

97+
@Transactional
9798
@RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST)
9899
public ReleaseDTO publish(@PathVariable("appId") String appId,
99100
@PathVariable("clusterName") String clusterName,
@@ -160,6 +161,7 @@ public ReleaseDTO updateAndPublish(@PathVariable("appId") String appId,
160161

161162
}
162163

164+
@Transactional
163165
@RequestMapping(path = "/releases/{releaseId}/rollback", method = RequestMethod.PUT)
164166
public void rollback(@PathVariable("releaseId") long releaseId,
165167
@RequestParam("operator") String operator) {

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@
2121
@Component
2222
public class BizConfig extends RefreshableConfig {
2323

24+
private static final int DEFAULT_ITEM_KEY_LENGTH = 128;
25+
private static final int DEFAULT_ITEM_VALUE_LENGTH = 20000;
26+
private static final int DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL = 60; //60s
27+
private static final int DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL = 60; //60s
28+
private static final int DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL = 1; //1s
29+
private static final int DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL = 1; //1s
30+
private static final int DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS = 1000; //1000ms
31+
private static final int DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH = 100;
32+
private static final int DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI = 100;//100ms
33+
2434
private Gson gson = new Gson();
2535
private static final Type namespaceValueLengthOverrideTypeReference =
2636
new TypeToken<Map<Long, Integer>>() {
@@ -44,18 +54,18 @@ public List<String> eurekaServiceUrls() {
4454
}
4555

4656
public int grayReleaseRuleScanInterval() {
47-
int interval = getIntProperty("apollo.gray-release-rule-scan.interval", 60);
48-
return checkInt(interval, 1, Integer.MAX_VALUE, 60);
57+
int interval = getIntProperty("apollo.gray-release-rule-scan.interval", DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL);
58+
return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL);
4959
}
5060

5161
public int itemKeyLengthLimit() {
52-
int limit = getIntProperty("item.key.length.limit", 128);
53-
return checkInt(limit, 5, Integer.MAX_VALUE, 128);
62+
int limit = getIntProperty("item.key.length.limit", DEFAULT_ITEM_KEY_LENGTH);
63+
return checkInt(limit, 5, Integer.MAX_VALUE, DEFAULT_ITEM_KEY_LENGTH);
5464
}
5565

5666
public int itemValueLengthLimit() {
57-
int limit = getIntProperty("item.value.length.limit", 20000);
58-
return checkInt(limit, 5, Integer.MAX_VALUE, 20000);
67+
int limit = getIntProperty("item.value.length.limit", DEFAULT_ITEM_VALUE_LENGTH);
68+
return checkInt(limit, 5, Integer.MAX_VALUE, DEFAULT_ITEM_VALUE_LENGTH);
5969
}
6070

6171
public Map<Long, Integer> namespaceValueLengthLimitOverride() {
@@ -85,40 +95,49 @@ public String cloggingPort() {
8595
}
8696

8797
public int appNamespaceCacheScanInterval() {
88-
int interval = getIntProperty("apollo.app-namespace-cache-scan.interval", 1);
89-
return checkInt(interval, 1, Integer.MAX_VALUE, 1);
98+
int interval = getIntProperty("apollo.app-namespace-cache-scan.interval", DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL);
99+
return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL);
90100
}
91101

92102
public TimeUnit appNamespaceCacheScanIntervalTimeUnit() {
93103
return TimeUnit.SECONDS;
94104
}
95105

96106
public int appNamespaceCacheRebuildInterval() {
97-
int interval = getIntProperty("apollo.app-namespace-cache-rebuild.interval", 60);
98-
return checkInt(interval, 1, Integer.MAX_VALUE, 60);
107+
int interval = getIntProperty("apollo.app-namespace-cache-rebuild.interval", DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL);
108+
return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL);
99109
}
100110

101111
public TimeUnit appNamespaceCacheRebuildIntervalTimeUnit() {
102112
return TimeUnit.SECONDS;
103113
}
104114

105115
public int releaseMessageCacheScanInterval() {
106-
int interval = getIntProperty("apollo.release-message-cache-scan.interval", 1);
107-
return checkInt(interval, 1, Integer.MAX_VALUE, 1);
116+
int interval = getIntProperty("apollo.release-message-cache-scan.interval", DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL);
117+
return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL);
108118
}
109119

110120
public TimeUnit releaseMessageCacheScanIntervalTimeUnit() {
111121
return TimeUnit.SECONDS;
112122
}
113123

124+
public int releaseMessageScanIntervalInMilli() {
125+
int interval = getIntProperty("apollo.message-scan.interval", DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS);
126+
return checkInt(interval, 100, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS);
127+
}
128+
114129
public int releaseMessageNotificationBatch() {
115-
int batch = getIntProperty("apollo.release-message.notification.batch", 100);
116-
return checkInt(batch, 1, Integer.MAX_VALUE, 100);
130+
int batch = getIntProperty("apollo.release-message.notification.batch", DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH);
131+
return checkInt(batch, 1, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH);
117132
}
118133

119134
public int releaseMessageNotificationBatchIntervalInMilli() {
120-
int interval = getIntProperty("apollo.release-message.notification.batch.interval", 100);
121-
return checkInt(interval, 1, Integer.MAX_VALUE, 100);
135+
int interval = getIntProperty("apollo.release-message.notification.batch.interval", DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI);
136+
return checkInt(interval, 10, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI);
137+
}
138+
139+
public boolean isConfigServiceCacheEnabled() {
140+
return getBooleanProperty("config-service.cache.enabled", false);
122141
}
123142

124143
int checkInt(int value, int min, int max, int defaultValue) {

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/DatabaseMessageSender.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public void sendMessage(String message, String channel) {
6161
} catch (Throwable ex) {
6262
logger.error("Sending message to database failed", ex);
6363
transaction.setStatus(ex);
64+
throw ex;
6465
} finally {
6566
transaction.complete();
6667
}

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/ReleaseMessageScanner.java

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,31 @@
11
package com.ctrip.framework.apollo.biz.message;
22

3-
import com.google.common.collect.Lists;
4-
5-
import com.ctrip.framework.apollo.biz.entity.ReleaseMessage;
6-
import com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository;
7-
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
8-
import com.ctrip.framework.apollo.tracer.Tracer;
9-
import com.ctrip.framework.apollo.tracer.spi.Transaction;
3+
import java.util.List;
4+
import java.util.concurrent.Executors;
5+
import java.util.concurrent.ScheduledExecutorService;
6+
import java.util.concurrent.TimeUnit;
107

118
import org.slf4j.Logger;
129
import org.slf4j.LoggerFactory;
1310
import org.springframework.beans.factory.InitializingBean;
1411
import org.springframework.beans.factory.annotation.Autowired;
15-
import org.springframework.core.env.Environment;
1612
import org.springframework.util.CollectionUtils;
1713

18-
import java.util.List;
19-
import java.util.Objects;
20-
import java.util.concurrent.Executors;
21-
import java.util.concurrent.ScheduledExecutorService;
22-
import java.util.concurrent.TimeUnit;
14+
import com.ctrip.framework.apollo.biz.config.BizConfig;
15+
import com.ctrip.framework.apollo.biz.entity.ReleaseMessage;
16+
import com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository;
17+
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
18+
import com.ctrip.framework.apollo.tracer.Tracer;
19+
import com.ctrip.framework.apollo.tracer.spi.Transaction;
20+
import com.google.common.collect.Lists;
2321

2422
/**
2523
* @author Jason Song([email protected])
2624
*/
2725
public class ReleaseMessageScanner implements InitializingBean {
2826
private static final Logger logger = LoggerFactory.getLogger(ReleaseMessageScanner.class);
29-
private static final int DEFAULT_SCAN_INTERVAL_IN_MS = 1000;
3027
@Autowired
31-
private Environment env;
28+
private BizConfig bizConfig;
3229
@Autowired
3330
private ReleaseMessageRepository releaseMessageRepository;
3431
private int databaseScanInterval;
@@ -44,7 +41,7 @@ public ReleaseMessageScanner() {
4441

4542
@Override
4643
public void afterPropertiesSet() throws Exception {
47-
populateDataBaseInterval();
44+
databaseScanInterval = bizConfig.releaseMessageScanIntervalInMilli();
4845
maxIdScanned = loadLargestMessageId();
4946
executorService.scheduleWithFixedDelay((Runnable) () -> {
5047
Transaction transaction = Tracer.newTransaction("Apollo.ReleaseMessageScanner", "scanMessage");
@@ -57,7 +54,7 @@ public void afterPropertiesSet() throws Exception {
5754
} finally {
5855
transaction.complete();
5956
}
60-
}, getDatabaseScanIntervalMs(), getDatabaseScanIntervalMs(), TimeUnit.MILLISECONDS);
57+
}, databaseScanInterval, databaseScanInterval, TimeUnit.MILLISECONDS);
6158

6259
}
6360

@@ -124,21 +121,4 @@ private void fireMessageScanned(List<ReleaseMessage> messages) {
124121
}
125122
}
126123
}
127-
128-
private void populateDataBaseInterval() {
129-
databaseScanInterval = DEFAULT_SCAN_INTERVAL_IN_MS;
130-
try {
131-
String interval = env.getProperty("apollo.message-scan.interval");
132-
if (!Objects.isNull(interval)) {
133-
databaseScanInterval = Integer.parseInt(interval);
134-
}
135-
} catch (Throwable ex) {
136-
Tracer.logError(ex);
137-
logger.error("Load apollo message scan interval from system property failed", ex);
138-
}
139-
}
140-
141-
private int getDatabaseScanIntervalMs() {
142-
return databaseScanInterval;
143-
}
144124
}

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
import com.ctrip.framework.apollo.biz.entity.Item;
99
import com.ctrip.framework.apollo.biz.entity.Namespace;
1010
import com.ctrip.framework.apollo.biz.entity.Release;
11+
import com.ctrip.framework.apollo.biz.message.MessageSender;
12+
import com.ctrip.framework.apollo.biz.message.Topics;
1113
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
14+
import com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator;
1215
import com.ctrip.framework.apollo.common.constants.GsonType;
1316
import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;
1417
import com.ctrip.framework.apollo.common.entity.AppNamespace;
@@ -59,6 +62,8 @@ public class NamespaceService {
5962
private NamespaceLockService namespaceLockService;
6063
@Autowired
6164
private InstanceService instanceService;
65+
@Autowired
66+
private MessageSender messageSender;
6267

6368

6469
public Namespace findOne(Long namespaceId) {
@@ -282,7 +287,13 @@ public Namespace deleteNamespace(Namespace namespace, String operator) {
282287

283288
auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.DELETE, operator);
284289

285-
return namespaceRepository.save(namespace);
290+
Namespace deleted = namespaceRepository.save(namespace);
291+
292+
//Publish release message to do some clean up in config service, such as updating the cache
293+
messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),
294+
Topics.APOLLO_RELEASE_TOPIC);
295+
296+
return deleted;
286297
}
287298

288299
@Transactional

apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/message/DatabaseMessageSenderTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
import static org.junit.Assert.assertEquals;
1414
import static org.mockito.Mockito.any;
15+
import static org.mockito.Mockito.mock;
1516
import static org.mockito.Mockito.never;
1617
import static org.mockito.Mockito.times;
1718
import static org.mockito.Mockito.verify;
19+
import static org.mockito.Mockito.when;
1820

1921
/**
2022
* @author Jason Song([email protected])
@@ -33,6 +35,11 @@ public void setUp() throws Exception {
3335
@Test
3436
public void testSendMessage() throws Exception {
3537
String someMessage = "some-message";
38+
long someId = 1;
39+
ReleaseMessage someReleaseMessage = mock(ReleaseMessage.class);
40+
when(someReleaseMessage.getId()).thenReturn(someId);
41+
when(releaseMessageRepository.save(any(ReleaseMessage.class))).thenReturn(someReleaseMessage);
42+
3643
ArgumentCaptor<ReleaseMessage> captor = ArgumentCaptor.forClass(ReleaseMessage.class);
3744

3845
messageSender.sendMessage(someMessage, Topics.APOLLO_RELEASE_TOPIC);
@@ -50,4 +57,12 @@ public void testSendUnsupportedMessage() throws Exception {
5057

5158
verify(releaseMessageRepository, never()).save(any(ReleaseMessage.class));
5259
}
60+
61+
@Test(expected = RuntimeException.class)
62+
public void testSendMessageFailed() throws Exception {
63+
String someMessage = "some-message";
64+
when(releaseMessageRepository.save(any(ReleaseMessage.class))).thenThrow(new RuntimeException());
65+
66+
messageSender.sendMessage(someMessage, Topics.APOLLO_RELEASE_TOPIC);
67+
}
5368
}

apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/message/ReleaseMessageScannerTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ctrip.framework.apollo.biz.message;
22

3+
import com.ctrip.framework.apollo.biz.config.BizConfig;
34
import com.google.common.collect.Lists;
45
import com.google.common.util.concurrent.SettableFuture;
56

@@ -26,17 +27,17 @@ public class ReleaseMessageScannerTest extends AbstractUnitTest {
2627
@Mock
2728
private ReleaseMessageRepository releaseMessageRepository;
2829
@Mock
29-
private Environment env;
30+
private BizConfig bizConfig;
3031
private int databaseScanInterval;
3132

3233
@Before
3334
public void setUp() throws Exception {
3435
releaseMessageScanner = new ReleaseMessageScanner();
3536
ReflectionTestUtils
3637
.setField(releaseMessageScanner, "releaseMessageRepository", releaseMessageRepository);
37-
ReflectionTestUtils.setField(releaseMessageScanner, "env", env);
38+
ReflectionTestUtils.setField(releaseMessageScanner, "bizConfig", bizConfig);
3839
databaseScanInterval = 100; //100 ms
39-
when(env.getProperty("apollo.message-scan.interval")).thenReturn(String.valueOf(databaseScanInterval));
40+
when(bizConfig.releaseMessageScanIntervalInMilli()).thenReturn(databaseScanInterval);
4041
releaseMessageScanner.afterPropertiesSet();
4142
}
4243

0 commit comments

Comments
 (0)