Skip to content

Commit

Permalink
Optimize performance of '/apps/{appId}/envs/{env}/clusters/{clusterNa…
Browse files Browse the repository at this point in the history
…me}/namespaces' interface queries (#4473)

* add tech-support-qq-4.png

* Update README.md

* Enhance the user experience in the scenario of submitting duplicate keys

* Modify the key-value conflict exception prompt, adjust the code style

* pref(apollo-portal): Optimize performance of '/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces' interface queries

* doc(CHANGES.md): update CHANGES.md

* fix(apollo-portal/NamespaceService): Fix Expected exceptions not thrown outward problem, add test cases

* refactor(apollo-portal/NamespaceService): Enhanced exception log information

* fix(apollo-portal/NamespaceService): Repair test cases

* Update apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java

Co-authored-by: Jason Song <[email protected]>

* refactor(apollo-portal/NamespaceService): Replace CopyOnWriteArrayList with Collections.synchronizedList

Co-authored-by: Jason Song <[email protected]>
  • Loading branch information
klboke and nobodyiam authored Jul 26, 2022
1 parent aaa3561 commit 0f7dc80
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ Apollo 2.1.0
* [Allow users to associate multiple public namespaces at a time](https://github.com/apolloconfig/apollo/pull/4437)
* [Move apollo-demo, scripts/docker-quick-start and scripts/apollo-on-kubernetes out of main repository](https://github.com/apolloconfig/apollo/pull/4440)
* [Add search key when comparing Configuration items](https://github.com/apolloconfig/apollo/pull/4459)
* [Optimize performance of '/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces' interface queries](https://github.com/apolloconfig/apollo/pull/4473)
* [Add a new API to load items with pagination](https://github.com/apolloconfig/apollo/pull/4468)
* [fix(#4474):'openjdk:8-jre-alpine' potentially causing wrong number of cpu cores](https://github.com/apolloconfig/apollo/pull/4475)

------------------
All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/11?closed=1)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.component.PortalSettings;
Expand All @@ -41,11 +42,15 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
Expand All @@ -58,6 +63,9 @@ public class NamespaceService {

private static final Logger LOGGER = LoggerFactory.getLogger(NamespaceService.class);
private static final Gson GSON = new Gson();
private static final ExecutorService executorService = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors() * 2
, ApolloThreadFactory.create("NamespaceService", true));

private final PortalConfig portalConfig;
private final PortalSettings portalSettings;
Expand Down Expand Up @@ -165,20 +173,35 @@ public List<NamespaceBO> findNamespaceBOs(String appId, Env env, String clusterN
throw new BadRequestException("namespaces not exist");
}

List<NamespaceBO> namespaceBOs = new LinkedList<>();
List<NamespaceBO> namespaceBOs = Collections.synchronizedList(new LinkedList<>());
List<String> exceptionNamespaces = Collections.synchronizedList(new LinkedList<>());
CountDownLatch latch = new CountDownLatch(namespaces.size());
for (NamespaceDTO namespace : namespaces) {
executorService.submit(() -> {
NamespaceBO namespaceBO;
try {
namespaceBO = transformNamespace2BO(env, namespace);
namespaceBOs.add(namespaceBO);
} catch (Exception e) {
LOGGER.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
appId, env, clusterName, namespace.getNamespaceName(), e);
exceptionNamespaces.add(namespace.getNamespaceName());
} finally {
latch.countDown();
}
});

NamespaceBO namespaceBO;
try {
namespaceBO = transformNamespace2BO(env, namespace);
namespaceBOs.add(namespaceBO);
} catch (Exception e) {
LOGGER.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
appId, env, clusterName, namespace.getNamespaceName(), e);
throw e;
}
}
try {
latch.await();
} catch (InterruptedException e) {
//ignore
}

if(namespaceBOs.size() != namespaces.size()){
throw new RuntimeException(String
.format("Parse namespaces error, expected: %s, but actual: %s, cannot get those namespaces: %s", namespaces.size(), namespaceBOs.size(), exceptionNamespaces));
}
return namespaceBOs;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
Expand Down Expand Up @@ -127,6 +128,14 @@ public void testFindNamespace() {
assertEquals(testClusterName, namespaceVO.getBaseInfo().getClusterName());
assertEquals(testNamespaceName, namespaceVO.getBaseInfo().getNamespaceName());

ReleaseDTO errorRelease = new ReleaseDTO();
someRelease.setConfigurations("\"a\":\"123\",\"b\":\"123\"");
when(releaseService.loadLatestRelease(testAppId, Env.DEV, testClusterName, "hermes")).thenReturn(errorRelease);
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(()-> namespaceService.findNamespaceBOs(testAppId, Env.DEV, testClusterName))
.withMessageContaining("hermes", testNamespaceName)
.withMessageStartingWith("Parse namespaces error, expected: 2, but actual: 0, cannot get those namespaces: ");

}

@Test
Expand Down

0 comments on commit 0f7dc80

Please sign in to comment.