diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/API.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/API.java index 4e162e5928a6ae2f30c41136fcd9a31545c16d09..5ad95ddd11d84d3dbe79a9a43624ec86bf347373 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/API.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/API.java @@ -25,6 +25,6 @@ public class API { } public String getAdminServiceHost(Env env) { - return serviceLocator.getAdminService(env).getHomepageUrl(); + return serviceLocator.getServiceAddress(env).getHomepageUrl(); } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalConfigController.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalConfigController.java index 709dacb079ca6cf3a2d8eed835a3c29471422779..5c46bad7fd1690c60007a6d074d1fc97f9eb40b7 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalConfigController.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalConfigController.java @@ -30,7 +30,7 @@ public class PortalConfigController { @Autowired private PortalConfigService configService; - @RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = { + @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = { "application/json"}) public void modifyItems(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @@ -51,7 +51,7 @@ public class PortalConfigController { configService.updateConfigItemByText(model); } - @RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.POST) + @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.POST) public ItemDTO createItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody ItemDTO item){ @@ -64,7 +64,7 @@ public class PortalConfigController { return configService.createOrUpdateItem(appId, Env.valueOf(env), clusterName, namespaceName, item); } - @RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.PUT) + @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.PUT) public ItemDTO updateItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody ItemDTO item){ @@ -85,7 +85,7 @@ public class PortalConfigController { configService.deleteItem(Env.valueOf(env), itemId); } - @RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST, consumes = { + @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST, consumes = { "application/json"}) public ReleaseDTO createRelease(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @@ -106,7 +106,7 @@ public class PortalConfigController { } - @RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items") + @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items") public List findItems(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName){ diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalNamespaceController.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalNamespaceController.java index 26dd88d31a0d36c376312d0dab675a767ac67aa2..912fbab8ee1da382ce6fc6f7adfbb0dd74761928 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalNamespaceController.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PortalNamespaceController.java @@ -45,7 +45,7 @@ public class PortalNamespaceController { namespaceService.createAppNamespace(appNamespace); } - @RequestMapping("/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces") + @RequestMapping("/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces") public List findNamespaces(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName) { if (StringUtils.isContainEmpty(appId, env, clusterName)) { diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/form/NamespaceTextModel.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/form/NamespaceTextModel.java index fd2fc7938666b3d277b42f5624844f098baa695c..d6aaa0691eb6d2a6b0af0c6ef7b7d4ab02d41e11 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/form/NamespaceTextModel.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/form/NamespaceTextModel.java @@ -16,7 +16,7 @@ public class NamespaceTextModel implements Verifiable { @Override public boolean isInvalid(){ - return StringUtils.isContainEmpty(appId, env, clusterName, namespaceName, configText) || namespaceId <= 0; + return StringUtils.isContainEmpty(appId, env, clusterName, namespaceName) || namespaceId <= 0; } public String getAppId() { return appId; diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalNamespaceService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalNamespaceService.java index 59bca8592309a0c670f8f2213af60171acfe95aa..40a5185848527ff81d214e21fdfc207423e79b47 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalNamespaceService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalNamespaceService.java @@ -8,6 +8,7 @@ import com.ctrip.framework.apollo.core.dto.ItemDTO; import com.ctrip.framework.apollo.core.dto.NamespaceDTO; import com.ctrip.framework.apollo.core.dto.ReleaseDTO; import com.ctrip.framework.apollo.core.enums.Env; +import com.ctrip.framework.apollo.core.exception.NotFoundException; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.PortalSettings; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; @@ -47,11 +48,11 @@ public class PortalNamespaceService { private Gson gson = new Gson(); - public List findPublicAppNamespaces(){ + public List findPublicAppNamespaces() { return namespaceAPI.findPublicAppNamespaces(portalSettings.getFirstAliveEnv()); } - public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace){ + public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) { return namespaceAPI.createNamespace(env, namespace); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ServiceLocator.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ServiceLocator.java index bad8d8dd4b39facd9a98c3e509f0f8d5790dbbef..612507492d160ac650c16f428d36c518b6faa068 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ServiceLocator.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ServiceLocator.java @@ -1,8 +1,6 @@ package com.ctrip.framework.apollo.portal.service; import java.net.URI; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -33,57 +31,21 @@ public class ServiceLocator { private static final int DEFAULT_TIMEOUT_MS = 1000; + private static final int RETRY_TIMES = 3; + + private static final int CALL_META_SERVER_THRESHOLD = 10; + + private static final String ADMIN_SERVICE_URL_PATH = "/services/admin"; + private RestTemplate restTemplate; @Autowired private HttpMessageConverters httpMessageConverters; - private Map> serviceCaches = new ConcurrentHashMap>(); + private Map serviceAddressCache = new ConcurrentHashMap<>(); private final AtomicInteger adminCallCounts = new AtomicInteger(0); - private final AtomicInteger configCallCounts = new AtomicInteger(0); - - public ServiceDTO getAdminService(Env env) throws ServiceException { - List services = getServices(env, "admin"); - if (services == null || services.size() == 0) { - throw new ServiceException("No available admin service"); - } - return services.get(Math.abs(adminCallCounts.getAndIncrement()) % services.size()); - } - - public ServiceDTO getConfigService(Env env) throws ServiceException { - List services = getServices(env, "config"); - if (services == null || services.size() == 0) { - throw new ServiceException("No available config service"); - } - return services.get(Math.abs(configCallCounts.getAndIncrement()) % services.size()); - } - - private List getServices(Env env, String serviceUrl) { - String domainName = MetaDomainConsts.getDomain(env); - String url = domainName + "/services/" + serviceUrl; - List serviceDtos = null; - try { - ServiceDTO[] services = restTemplate.getForObject(new URI(url), ServiceDTO[].class); - if (services != null && services.length > 0) { - if (!serviceCaches.containsKey(env)) { - serviceDtos = new ArrayList(); - serviceCaches.put(env, serviceDtos); - } else { - serviceDtos = serviceCaches.get(env); - serviceDtos.clear(); - } - for (ServiceDTO service : services) { - serviceDtos.add(service); - } - } - } catch (Exception ex) { - logger.warn(ex.getMessage()); - } - return serviceDtos; - } - @PostConstruct private void postConstruct() { restTemplate = new RestTemplate(httpMessageConverters.getConverters()); @@ -99,4 +61,55 @@ public class ServiceLocator { rf.setConnectTimeout(DEFAULT_TIMEOUT_MS); } } + + + public ServiceDTO getServiceAddress(Env env) throws ServiceException { + + if (adminCallCounts.get() % CALL_META_SERVER_THRESHOLD == 0) { + return getServiceAddressFromMetaServer(env); + } else { + //if cached then return from cache + ServiceDTO[] serviceDTOs = serviceAddressCache.get(env); + if (serviceDTOs != null && serviceDTOs.length > 0){ + return randomServiceAddress(serviceDTOs); + }else {//return from meta server + return getServiceAddressFromMetaServer(env); + } + } + + + } + + public ServiceDTO getServiceAddressFromMetaServer(Env env) { + //retry + for (int i = 0; i < RETRY_TIMES; i++) { + ServiceDTO[] services = getServices(env); + if (services != null && services.length > 0) { + serviceAddressCache.put(env, services); + return randomServiceAddress(services); + } else { + logger.warn(String.format("can not get %s admin service address at %d time", env, i)); + } + } + logger.error(String.format("can not get %s admin service address", env)); + throw new ServiceException("No available admin service"); + } + + + private ServiceDTO[] getServices(Env env) { + String domainName = MetaDomainConsts.getDomain(env); + String url = domainName + ADMIN_SERVICE_URL_PATH; + + try { + return restTemplate.getForObject(new URI(url), ServiceDTO[].class); + } catch (Exception ex) { + logger.warn(ex.getMessage()); + return null; + } + } + + private ServiceDTO randomServiceAddress(ServiceDTO[] services){ + return services[Math.abs(adminCallCounts.getAndIncrement()) % services.length]; + } + } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/PropertyResolver.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/PropertyResolver.java index fb1f517584d2ca9706b767ee983307c15bd879da..f2ab1f6f38a8d489f5f5093f1737b9df54609f3c 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/PropertyResolver.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/PropertyResolver.java @@ -3,7 +3,6 @@ package com.ctrip.framework.apollo.portal.service.txtresolver; import com.ctrip.framework.apollo.core.dto.ItemChangeSets; import com.ctrip.framework.apollo.core.dto.ItemDTO; import com.ctrip.framework.apollo.core.exception.BadRequestException; -import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.stereotype.Component; diff --git a/apollo-portal/src/main/resources/static/config.html b/apollo-portal/src/main/resources/static/config.html index 1bebe99dc792c37a08cef45d3e9bb0a99d857659..7dcfb21a4552ed4be4e0c903f164ed225fc1a3a5 100644 --- a/apollo-portal/src/main/resources/static/config.html +++ b/apollo-portal/src/main/resources/static/config.html @@ -222,7 +222,8 @@
+ ng-show="namespace.viewType == 'table' && namespace.items.length > 0 + && !(namespace.items.length == 1 && !namespace.items[0].key)">
@@ -283,7 +284,7 @@ @@ -390,7 +391,7 @@