diff --git a/apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigServiceLocator.java b/apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigServiceLocator.java index f843f8d4eb350806959bcbb90df6ac7add63fe3a..3ee0103252214db702c843a67cbf4e0abc188f50 100644 --- a/apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigServiceLocator.java +++ b/apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigServiceLocator.java @@ -1,6 +1,10 @@ package com.ctrip.apollo.internals; +import com.google.common.base.Joiner; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.escape.Escaper; +import com.google.common.net.UrlEscapers; import com.google.gson.reflect.TypeToken; import com.ctrip.apollo.core.dto.ServiceDTO; @@ -19,9 +23,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.unidal.lookup.annotation.Inject; import org.unidal.lookup.annotation.Named; +import org.unidal.net.Networks; import java.lang.reflect.Type; import java.util.List; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -37,6 +43,7 @@ public class ConfigServiceLocator implements Initializable { private AtomicReference> m_configServices; private Type m_responseType; private ScheduledExecutorService m_executorService; + private static final Joiner.MapJoiner MAP_JOINER = Joiner.on("&").withKeyValueSeparator("="); /** * Create a config service locator. @@ -95,10 +102,8 @@ public class ConfigServiceLocator implements Initializable { m_configUtil.getRefreshTimeUnit()); } - //TODO periodically update config services private synchronized void updateConfigServices() { - String domainName = m_configUtil.getMetaServerDomainName(); - String url = domainName + "/services/config"; + String url = assembleMetaServiceUrl(); HttpRequest request = new HttpRequest(url); int maxRetries = 5; @@ -131,6 +136,19 @@ public class ConfigServiceLocator implements Initializable { throw new RuntimeException("Get config services failed", exception); } + private String assembleMetaServiceUrl() { + String domainName = m_configUtil.getMetaServerDomainName(); + String appId = m_configUtil.getAppId(); + String localIp = Networks.forIp().getLocalHostAddress(); + + Escaper escaper = UrlEscapers.urlPathSegmentEscaper(); + Map queryParams = Maps.newHashMap(); + queryParams.put("appId", escaper.escape(appId)); + queryParams.put("ip", escaper.escape(localIp)); + + return domainName + "/services/config?" + MAP_JOINER.join(queryParams); + } + private void logConfigServicesToCat(List serviceDtos) { for (ServiceDTO serviceDto : serviceDtos) { Cat.logEvent("Apollo.Config.Services", serviceDto.getHomepageUrl()); diff --git a/apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java b/apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java index 4f32e29342bf8c9277b4504b24c33945d124c955..24ae34f22094cda039d509bd8d6825ba9e77a0cc 100644 --- a/apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java +++ b/apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java @@ -57,6 +57,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository { private final ScheduledExecutorService m_executorService; private final AtomicBoolean m_longPollingStopped; private SchedulePolicy m_longPollSchedulePolicy; + private AtomicReference m_longPollServiceDto; /** * Constructor. @@ -79,6 +80,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository { m_longPollingStopped = new AtomicBoolean(false); m_executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("RemoteConfigRepository", true)); + m_longPollServiceDto = new AtomicReference<>(); this.trySync(); this.schedulePeriodicRefresh(); this.scheduleLongPollingRefresh(); @@ -148,8 +150,12 @@ public class RemoteConfigRepository extends AbstractConfigRepository { List configServices = getConfigServices(); for (int i = 0; i < maxRetries; i++) { - List randomConfigServices = Lists.newArrayList(configServices); + List randomConfigServices = Lists.newLinkedList(configServices); Collections.shuffle(randomConfigServices); + //Access the server which notifies the client first + if (m_longPollServiceDto.get() != null) { + randomConfigServices.add(0, m_longPollServiceDto.getAndSet(null)); + } for (ServiceDTO configService : randomConfigServices) { String url = @@ -272,6 +278,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository { logger.debug("Long polling response: {}, url: {}", response.getStatusCode(), url); if (response.getStatusCode() == 200) { + m_longPollServiceDto.set(lastServiceDto); longPollingService.submit(new Runnable() { @Override public void run() { diff --git a/apollo-configservice/src/main/java/com/ctrip/apollo/metaservice/controller/ServiceController.java b/apollo-configservice/src/main/java/com/ctrip/apollo/metaservice/controller/ServiceController.java index f8c56abfffe0bb8d1296c0ae0d824a916e003c47..d29f737643d811587a545ae221f3360de12c1038 100644 --- a/apollo-configservice/src/main/java/com/ctrip/apollo/metaservice/controller/ServiceController.java +++ b/apollo-configservice/src/main/java/com/ctrip/apollo/metaservice/controller/ServiceController.java @@ -6,6 +6,7 @@ import com.netflix.appinfo.InstanceInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -39,7 +40,9 @@ public class ServiceController { } @RequestMapping("/config") - public List getConfigService() { + public List getConfigService( + @RequestParam(value = "appId", defaultValue = "") String appId, + @RequestParam(value = "ip", defaultValue = "") String clientIp) { List instances = discoveryService.getConfigServiceInstances(); List result = instances.stream().map(new Function() {