Commit 6860f0a2 authored by Jason Song's avatar Jason Song Committed by GitHub

Merge pull request #1275 from nobodyiam/configurable-apollo-meta-config-service

support passing apollo.meta and apollo.configService via system property, etc
parents 612f1967 87b8de4b
package com.ctrip.framework.apollo.internals; package com.ctrip.framework.apollo.internals;
import com.ctrip.framework.apollo.core.ServiceNameConsts;
import com.ctrip.framework.foundation.Foundation;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -51,10 +53,57 @@ public class ConfigServiceLocator { ...@@ -51,10 +53,57 @@ public class ConfigServiceLocator {
m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);
this.m_executorService = Executors.newScheduledThreadPool(1, this.m_executorService = Executors.newScheduledThreadPool(1,
ApolloThreadFactory.create("ConfigServiceLocator", true)); ApolloThreadFactory.create("ConfigServiceLocator", true));
initConfigServices();
}
private void initConfigServices() {
// get from run time configurations
List<ServiceDTO> customizedConfigServices = getCustomizedConfigService();
if (customizedConfigServices != null) {
setConfigServices(customizedConfigServices);
return;
}
// update from meta service
this.tryUpdateConfigServices(); this.tryUpdateConfigServices();
this.schedulePeriodicRefresh(); this.schedulePeriodicRefresh();
} }
private List<ServiceDTO> getCustomizedConfigService() {
// 1. Get from System Property
String configServices = System.getProperty("apollo.configService");
if (Strings.isNullOrEmpty(configServices)) {
// 2. Get from OS environment variable
configServices = System.getenv("APOLLO.CONFIGSERVICE");
}
if (Strings.isNullOrEmpty(configServices)) {
// 3. Get from server.properties
configServices = Foundation.server().getProperty("apollo.configService", null);
}
if (Strings.isNullOrEmpty(configServices)) {
return null;
}
logger.warn("Located config services from apollo.configService configuration: {}, will not refresh config services from remote meta service!", configServices);
// mock service dto list
String[] configServiceUrls = configServices.split(",");
List<ServiceDTO> serviceDTOS = Lists.newArrayList();
for (String configServiceUrl : configServiceUrls) {
configServiceUrl = configServiceUrl.trim();
ServiceDTO serviceDTO = new ServiceDTO();
serviceDTO.setHomepageUrl(configServiceUrl);
serviceDTO.setAppName(ServiceNameConsts.APOLLO_CONFIGSERVICE);
serviceDTO.setInstanceId(configServiceUrl);
serviceDTOS.add(serviceDTO);
}
return serviceDTOS;
}
/** /**
* Get the config service info from remote meta server. * Get the config service info from remote meta server.
* *
...@@ -109,8 +158,7 @@ public class ConfigServiceLocator { ...@@ -109,8 +158,7 @@ public class ConfigServiceLocator {
logConfigService("Empty response!"); logConfigService("Empty response!");
continue; continue;
} }
m_configServices.set(services); setConfigServices(services);
logConfigServices(services);
return; return;
} catch (Throwable ex) { } catch (Throwable ex) {
Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex)); Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex));
...@@ -131,6 +179,11 @@ public class ConfigServiceLocator { ...@@ -131,6 +179,11 @@ public class ConfigServiceLocator {
String.format("Get config services failed from %s", url), exception); String.format("Get config services failed from %s", url), exception);
} }
private void setConfigServices(List<ServiceDTO> services) {
m_configServices.set(services);
logConfigServices(services);
}
private String assembleMetaServiceUrl() { private String assembleMetaServiceUrl() {
String domainName = m_configUtil.getMetaServerDomainName(); String domainName = m_configUtil.getMetaServerDomainName();
String appId = m_configUtil.getAppId(); String appId = m_configUtil.getAppId();
......
...@@ -221,7 +221,11 @@ public class ConfigUtil { ...@@ -221,7 +221,11 @@ public class ConfigUtil {
// 1. Get from System Property // 1. Get from System Property
String cacheRoot = System.getProperty("apollo.cacheDir"); String cacheRoot = System.getProperty("apollo.cacheDir");
if (Strings.isNullOrEmpty(cacheRoot)) { if (Strings.isNullOrEmpty(cacheRoot)) {
// 2. Get from server.properties // 2. Get from OS environment variable
cacheRoot = System.getenv("APOLLO.CACHEDIR");
}
if (Strings.isNullOrEmpty(cacheRoot)) {
// 3. Get from server.properties
cacheRoot = Foundation.server().getProperty("apollo.cacheDir", null); cacheRoot = Foundation.server().getProperty("apollo.cacheDir", null);
} }
......
package com.ctrip.framework.apollo.internals;
import static org.junit.Assert.assertEquals;
import com.ctrip.framework.apollo.core.dto.ServiceDTO;
import java.util.List;
import org.junit.After;
import org.junit.Test;
public class ConfigServiceLocatorTest {
@After
public void tearDown() throws Exception {
System.clearProperty("apollo.configService");
}
@Test
public void testGetConfigServicesWithSystemProperty() throws Exception {
String someConfigServiceUrl = " someConfigServiceUrl ";
String anotherConfigServiceUrl = " anotherConfigServiceUrl ";
System.setProperty("apollo.configService", someConfigServiceUrl + "," + anotherConfigServiceUrl);
ConfigServiceLocator configServiceLocator = new ConfigServiceLocator();
List<ServiceDTO> result = configServiceLocator.getConfigServices();
assertEquals(2, result.size());
assertEquals(someConfigServiceUrl.trim(), result.get(0).getHomepageUrl());
assertEquals(anotherConfigServiceUrl.trim(), result.get(1).getHomepageUrl());
}
}
...@@ -6,6 +6,8 @@ import com.ctrip.framework.apollo.core.utils.NetUtil; ...@@ -6,6 +6,8 @@ import com.ctrip.framework.apollo.core.utils.NetUtil;
import com.ctrip.framework.apollo.core.utils.ResourceUtils; import com.ctrip.framework.apollo.core.utils.ResourceUtils;
import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.Tracer;
import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.tracer.spi.Transaction;
import com.ctrip.framework.foundation.Foundation;
import com.google.common.base.Strings;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import java.util.Collections; import java.util.Collections;
...@@ -33,9 +35,10 @@ public class MetaDomainConsts { ...@@ -33,9 +35,10 @@ public class MetaDomainConsts {
private static final long REFRESH_INTERVAL_IN_SECOND = 60;//1 min private static final long REFRESH_INTERVAL_IN_SECOND = 60;//1 min
private static final Logger logger = LoggerFactory.getLogger(MetaDomainConsts.class); private static final Logger logger = LoggerFactory.getLogger(MetaDomainConsts.class);
private static Map<Env, String> domains = new HashMap<>(); private static final Map<Env, String> domains = new HashMap<>();
private static Map<String, String> metaServerAddressCache = Maps.newConcurrentMap(); private static final Map<String, String> metaServerAddressCache = Maps.newConcurrentMap();
private static AtomicBoolean periodicRefreshStarted = new AtomicBoolean(false); private static final AtomicBoolean periodicRefreshStarted = new AtomicBoolean(false);
private static final AtomicBoolean customizedMetaServiceLogged = new AtomicBoolean(false);
static { static {
initialize(); initialize();
...@@ -60,11 +63,38 @@ public class MetaDomainConsts { ...@@ -60,11 +63,38 @@ public class MetaDomainConsts {
} }
public static String getDomain(Env env) { public static String getDomain(Env env) {
String metaAddress = domains.get(env); // 1. Get meta server address from run time configurations
//if there is more than one address, need to select one String metaAddress = getCustomizedMetaServerAddress();
if (Strings.isNullOrEmpty(metaAddress)) {
// 2. Get meta server address from environment
metaAddress = domains.get(env);
}
// 3. if there is more than one address, need to select one
if (metaAddress != null && metaAddress.contains(",")) { if (metaAddress != null && metaAddress.contains(",")) {
return selectMetaServerAddress(metaAddress); return selectMetaServerAddress(metaAddress);
} }
// 4. trim if necessary
if (metaAddress != null) {
metaAddress = metaAddress.trim();
}
return metaAddress;
}
private static String getCustomizedMetaServerAddress() {
// 1. Get from System Property
String metaAddress = System.getProperty("apollo.meta");
if (Strings.isNullOrEmpty(metaAddress)) {
// 2. Get from OS environment variable
metaAddress = System.getenv("APOLLO.META");
}
if (Strings.isNullOrEmpty(metaAddress)) {
metaAddress = Foundation.server().getProperty("apollo.meta", null);
}
if (!Strings.isNullOrEmpty(metaAddress) && customizedMetaServiceLogged.compareAndSet(false, true)) {
logger.warn("Located meta services from apollo.meta configuration: {}, will not use meta services defined in apollo-env.properties!", metaAddress);
}
return metaAddress; return metaAddress;
} }
...@@ -105,6 +135,7 @@ public class MetaDomainConsts { ...@@ -105,6 +135,7 @@ public class MetaDomainConsts {
boolean serverAvailable = false; boolean serverAvailable = false;
for (String address : metaServers) { for (String address : metaServers) {
address = address.trim();
if (NetUtil.pingUrl(address)) { if (NetUtil.pingUrl(address)) {
//select the first available meta server //select the first available meta server
metaServerAddressCache.put(metaServerAddresses, address); metaServerAddressCache.put(metaServerAddresses, address);
...@@ -116,7 +147,7 @@ public class MetaDomainConsts { ...@@ -116,7 +147,7 @@ public class MetaDomainConsts {
//we need to make sure the map is not empty, e.g. the first update might be failed //we need to make sure the map is not empty, e.g. the first update might be failed
if (!metaServerAddressCache.containsKey(metaServerAddresses)) { if (!metaServerAddressCache.containsKey(metaServerAddresses)) {
metaServerAddressCache.put(metaServerAddresses, metaServers.get(0)); metaServerAddressCache.put(metaServerAddresses, metaServers.get(0).trim());
} }
if (!serverAvailable) { if (!serverAvailable) {
......
...@@ -18,6 +18,7 @@ public class MetaDomainTest extends BaseIntegrationTest { ...@@ -18,6 +18,7 @@ public class MetaDomainTest extends BaseIntegrationTest {
System.clearProperty("fat_meta"); System.clearProperty("fat_meta");
System.clearProperty("uat_meta"); System.clearProperty("uat_meta");
System.clearProperty("lpt_meta"); System.clearProperty("lpt_meta");
System.clearProperty("apollo.meta");
} }
@Test @Test
...@@ -27,12 +28,22 @@ public class MetaDomainTest extends BaseIntegrationTest { ...@@ -27,12 +28,22 @@ public class MetaDomainTest extends BaseIntegrationTest {
assertEquals(MetaDomainConsts.DEFAULT_META_URL, MetaDomainConsts.getDomain(Env.PRO)); assertEquals(MetaDomainConsts.DEFAULT_META_URL, MetaDomainConsts.getDomain(Env.PRO));
} }
@Test
public void testGetMetaDomainWithSystemProperty() throws Exception {
String someMeta = "some-meta";
Env someEnv = Env.DEV;
System.setProperty("apollo.meta", someMeta);
assertEquals(someMeta, MetaDomainConsts.getDomain(someEnv));
}
@Test @Test
public void testGetValidAddress() throws Exception { public void testGetValidAddress() throws Exception {
String someResponse = "some response"; String someResponse = "some response";
startServerWithHandlers(mockServerHandler(HttpServletResponse.SC_OK, someResponse)); startServerWithHandlers(mockServerHandler(HttpServletResponse.SC_OK, someResponse));
String validServer = "http://localhost:" + PORT; String validServer = " http://localhost:" + PORT + " ";
String invalidServer = "http://localhost:" + findFreePort(); String invalidServer = "http://localhost:" + findFreePort();
System.setProperty("fat_meta", validServer + "," + invalidServer); System.setProperty("fat_meta", validServer + "," + invalidServer);
...@@ -40,14 +51,14 @@ public class MetaDomainTest extends BaseIntegrationTest { ...@@ -40,14 +51,14 @@ public class MetaDomainTest extends BaseIntegrationTest {
MetaDomainConsts.initialize(); MetaDomainConsts.initialize();
assertEquals(validServer, MetaDomainConsts.getDomain(Env.FAT)); assertEquals(validServer.trim(), MetaDomainConsts.getDomain(Env.FAT));
assertEquals(validServer, MetaDomainConsts.getDomain(Env.UAT)); assertEquals(validServer.trim(), MetaDomainConsts.getDomain(Env.UAT));
} }
@Test @Test
public void testInvalidAddress() throws Exception { public void testInvalidAddress() throws Exception {
String invalidServer = "http://localhost:" + findFreePort(); String invalidServer = "http://localhost:" + findFreePort() + " ";
String anotherInvalidServer = "http://localhost:" + findFreePort(); String anotherInvalidServer = "http://localhost:" + findFreePort() + " ";
System.setProperty("lpt_meta", invalidServer + "," + anotherInvalidServer); System.setProperty("lpt_meta", invalidServer + "," + anotherInvalidServer);
...@@ -55,6 +66,6 @@ public class MetaDomainTest extends BaseIntegrationTest { ...@@ -55,6 +66,6 @@ public class MetaDomainTest extends BaseIntegrationTest {
String metaServer = MetaDomainConsts.getDomain(Env.LPT); String metaServer = MetaDomainConsts.getDomain(Env.LPT);
assertTrue(metaServer.equals(invalidServer) || metaServer.equals(anotherInvalidServer)); assertTrue(metaServer.equals(invalidServer.trim()) || metaServer.equals(anotherInvalidServer.trim()));
} }
} }
package com.ctrip.framework.apollo.foundation; package com.ctrip.framework.foundation;
import org.junit.AfterClass; import static org.junit.Assert.assertTrue;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.ctrip.framework.foundation.Foundation; import com.ctrip.framework.foundation.Foundation;
import com.ctrip.framework.foundation.internals.provider.DefaultApplicationProvider;
import com.ctrip.framework.foundation.internals.provider.DefaultServerProvider;
import org.junit.Assert;
import org.junit.Test;
public class FoundationTest { public class FoundationTest {
private static final String someEnv = "pro";
@BeforeClass
public static void before() {
System.setProperty("env", someEnv);
}
@AfterClass
public static void afterClass() {
System.clearProperty("env");
}
@Test @Test
public void testApp() { public void testApp() {
// 获取AppId assertTrue(Foundation.app() instanceof DefaultApplicationProvider);
String appId = Foundation.app().getAppId();
Assert.assertEquals("110402", appId);
} }
@Test @Test
public void testServer() { public void testServer() {
// 获取当前环境 assertTrue(Foundation.server() instanceof DefaultServerProvider);
String envType = Foundation.server().getEnvType();
Assert.assertEquals(someEnv, envType);
} }
@Test @Test
......
package com.ctrip.framework.apollo.foundation.internals; package com.ctrip.framework.foundation.internals;
import com.ctrip.framework.foundation.internals.ServiceBootstrap; import com.ctrip.framework.foundation.internals.ServiceBootstrap;
import org.junit.Test; import org.junit.Test;
...@@ -54,4 +54,4 @@ public class ServiceBootstrapTest { ...@@ -54,4 +54,4 @@ public class ServiceBootstrapTest {
private interface Interface5 { private interface Interface5 {
} }
} }
\ No newline at end of file
package com.ctrip.framework.apollo.foundation.internals.provider; package com.ctrip.framework.foundation.internals.provider;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
......
package com.ctrip.framework.apollo.foundation.internals.provider; package com.ctrip.framework.foundation.internals.provider;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
......
com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1Impl
\ No newline at end of file
com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1Impl
\ No newline at end of file
com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$SomeImplNotExists
\ No newline at end of file
local.meta=http://localhost:8080 local.meta=http://localhost:8080
dev.meta=http://dev:8080 dev.meta=http://dev:8080
\ No newline at end of file
...@@ -27,9 +27,6 @@ public class SimpleApolloConfigDemo { ...@@ -27,9 +27,6 @@ public class SimpleApolloConfigDemo {
ConfigChangeListener changeListener = new ConfigChangeListener() { ConfigChangeListener changeListener = new ConfigChangeListener() {
@Override @Override
public void onChange(ConfigChangeEvent changeEvent) { public void onChange(ConfigChangeEvent changeEvent) {
if (!changeEvent.isChanged("someKey")) {
return;
}
logger.info("Changes for namespace {}", changeEvent.getNamespace()); logger.info("Changes for namespace {}", changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) { for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key); ConfigChange change = changeEvent.getChange(key);
......
...@@ -29,7 +29,6 @@ public class SpringBootApolloRefreshConfig { ...@@ -29,7 +29,6 @@ public class SpringBootApolloRefreshConfig {
public void onChange(ConfigChangeEvent changeEvent) { public void onChange(ConfigChangeEvent changeEvent) {
boolean redisCacheKeysChanged = false; boolean redisCacheKeysChanged = false;
for (String changedKey : changeEvent.changedKeys()) { for (String changedKey : changeEvent.changedKeys()) {
if (changeEvent.isChanged("someKey"))
if (changedKey.startsWith("redis.cache")) { if (changedKey.startsWith("redis.cache")) {
redisCacheKeysChanged = true; redisCacheKeysChanged = true;
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment