Commit f4a69e43 by Ryan J Baxter Committed by Dave Syer

Sets the zone based on the hostname of the service if approximateZoneFromHostname is true.

The flag has always been there, it just isn't carried through to the ribbon client configuration without this change if I understand this change correctly. Fixes gh-315, fixes gh-423.
parent 3519ecf2
...@@ -22,8 +22,6 @@ import java.util.List; ...@@ -22,8 +22,6 @@ import java.util.List;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.util.StringUtils;
import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
...@@ -92,7 +90,7 @@ class DomainExtractingServer extends DiscoveryEnabledServer { ...@@ -92,7 +90,7 @@ class DomainExtractingServer extends DiscoveryEnabledServer {
setZone(server.getInstanceInfo().getMetadata().get("zone")); setZone(server.getInstanceInfo().getMetadata().get("zone"));
} }
else if (approximateZoneFromHostname) { else if (approximateZoneFromHostname) {
setZone(extractApproximateZone(server)); setZone(ZoneUtils.extractApproximateZone(server.getHost()));
} }
else { else {
setZone(server.getZone()); setZone(server.getZone());
...@@ -112,18 +110,4 @@ class DomainExtractingServer extends DiscoveryEnabledServer { ...@@ -112,18 +110,4 @@ class DomainExtractingServer extends DiscoveryEnabledServer {
} }
return super.getId(); return super.getId();
} }
private String extractApproximateZone(Server server) {
String host = server.getHost();
if (!host.contains(".")) {
return host;
}
String[] split = StringUtils.split(host, ".");
StringBuilder builder = new StringBuilder(split[1]);
for (int i = 2; i < split.length; i++) {
builder.append(".").append(split[i]);
}
return builder.toString();
}
} }
...@@ -21,11 +21,15 @@ import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity ...@@ -21,11 +21,15 @@ import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.config.ConfigurationManager; import com.netflix.config.ConfigurationManager;
...@@ -45,8 +49,10 @@ import com.netflix.niws.loadbalancer.NIWSDiscoveryPing; ...@@ -45,8 +49,10 @@ import com.netflix.niws.loadbalancer.NIWSDiscoveryPing;
* *
* @author Spencer Gibb * @author Spencer Gibb
* @author Dave Syer * @author Dave Syer
* @author Ryan Baxter
*/ */
@Configuration @Configuration
@CommonsLog
public class EurekaRibbonClientConfiguration { public class EurekaRibbonClientConfiguration {
@Value("${ribbon.eureka.approximateZoneFromHostname:false}") @Value("${ribbon.eureka.approximateZoneFromHostname:false}")
...@@ -62,13 +68,19 @@ public class EurekaRibbonClientConfiguration { ...@@ -62,13 +68,19 @@ public class EurekaRibbonClientConfiguration {
@Autowired(required = false) @Autowired(required = false)
private EurekaClientConfig clientConfig; private EurekaClientConfig clientConfig;
@Autowired
private EurekaInstanceConfigBean eurekaConfig;
public EurekaRibbonClientConfiguration() { public EurekaRibbonClientConfiguration() {
} }
public EurekaRibbonClientConfiguration(EurekaClientConfig clientConfig, public EurekaRibbonClientConfiguration(EurekaClientConfig clientConfig,
String serviceId) { String serviceId, EurekaInstanceConfigBean eurekaConfig,
boolean approximateZoneFromHostname) {
this.clientConfig = clientConfig; this.clientConfig = clientConfig;
this.serviceId = serviceId; this.serviceId = serviceId;
this.eurekaConfig = eurekaConfig;
this.approximateZoneFromHostname = approximateZoneFromHostname;
} }
@Bean @Bean
...@@ -82,23 +94,36 @@ public class EurekaRibbonClientConfiguration { ...@@ -82,23 +94,36 @@ public class EurekaRibbonClientConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config) { public ServerList<?> ribbonServerList(IClientConfig config) {
DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(config); DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(
DomainExtractingServerList serverList = new DomainExtractingServerList(discoveryServerList, config, this.approximateZoneFromHostname); config);
DomainExtractingServerList serverList = new DomainExtractingServerList(
discoveryServerList, config, this.approximateZoneFromHostname);
return serverList; return serverList;
} }
@PostConstruct @PostConstruct
public void preprocess() { public void preprocess() {
if (this.clientConfig != null String zone = ConfigurationManager.getDeploymentContext().getValue(
&& ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) { ContextKey.zone);
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig if (this.clientConfig != null && StringUtils.isEmpty(zone)) {
.getRegion()); if (approximateZoneFromHostname) {
String zone = zones != null && zones.length > 0 ? zones[0] : null; String approxZone = ZoneUtils.extractApproximateZone(eurekaConfig
if (zone != null) { .getHostname());
// You can set this with archaius.deployment.* (maybe requires log.debug("Setting Zone To " + approxZone);
// custom deployment context)?
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
zone); approxZone);
}
else {
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig
.getRegion());
String availabilityZone = zones != null && zones.length > 0 ? zones[0]
: null;
if (availabilityZone != null) {
// You can set this with archaius.deployment.* (maybe requires
// custom deployment context)?
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
availabilityZone);
}
} }
} }
setProp(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId); setProp(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId);
......
/* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import org.springframework.util.StringUtils;
/**
* Utility class for dealing with zones.
* @author Ryan Baxter
*
*/
public class ZoneUtils {
/**
* Approximates Eureka zones from a host name. This method approximates the zone to be
* everything after the first "." in the host name.
* @param host The host name to extract the host name from
* @return The approximate zone
*/
public static String extractApproximateZone(String host) {
if (!host.contains(".")) {
return host;
}
String[] split = StringUtils.split(host, ".");
StringBuilder builder = new StringBuilder(split[1]);
for (int i = 2; i < split.length; i++) {
builder.append(".").append(split[i]);
}
return builder.toString();
}
}
...@@ -16,10 +16,17 @@ ...@@ -16,10 +16,17 @@
package org.springframework.cloud.netflix.ribbon.eureka; package org.springframework.cloud.netflix.ribbon.eureka;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientConfiguration.VALUE_NOT_SET;
import org.junit.After; import org.junit.After;
import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import com.netflix.config.ConfigurationManager; import com.netflix.config.ConfigurationManager;
...@@ -29,15 +36,14 @@ import com.netflix.loadbalancer.ILoadBalancer; ...@@ -29,15 +36,14 @@ import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer; import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer; import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import static org.junit.Assert.*;
import static org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientConfiguration.VALUE_NOT_SET;
/** /**
* @author Dave Syer * @author Dave Syer
* @author Ryan Baxter
*/ */
public class EurekaRibbonClientConfigurationTests { public class EurekaRibbonClientConfigurationTests {
@After @After
@Before
public void close() { public void close() {
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, ""); ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, "");
} }
...@@ -46,10 +52,11 @@ public class EurekaRibbonClientConfigurationTests { ...@@ -46,10 +52,11 @@ public class EurekaRibbonClientConfigurationTests {
@Ignore @Ignore
public void basicConfigurationCreatedForLoadBalancer() { public void basicConfigurationCreatedForLoadBalancer() {
EurekaClientConfigBean client = new EurekaClientConfigBean(); EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean();
client.getAvailabilityZones().put(client.getRegion(), "foo"); client.getAvailabilityZones().put(client.getRegion(), "foo");
SpringClientFactory clientFactory = new SpringClientFactory(); SpringClientFactory clientFactory = new SpringClientFactory();
EurekaRibbonClientConfiguration clientPreprocessor = new EurekaRibbonClientConfiguration( EurekaRibbonClientConfiguration clientPreprocessor = new EurekaRibbonClientConfiguration(
client, "service"); client, "service", configBean, false);
clientPreprocessor.preprocess(); clientPreprocessor.preprocess();
ILoadBalancer balancer = clientFactory.getLoadBalancer("service"); ILoadBalancer balancer = clientFactory.getLoadBalancer("service");
assertNotNull(balancer); assertNotNull(balancer);
...@@ -63,8 +70,9 @@ public class EurekaRibbonClientConfigurationTests { ...@@ -63,8 +70,9 @@ public class EurekaRibbonClientConfigurationTests {
@Test @Test
public void testSetProp() { public void testSetProp() {
EurekaClientConfigBean client = new EurekaClientConfigBean(); EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean();
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration( EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService"); client, "myService", configBean, false);
String serviceId = "myService"; String serviceId = "myService";
String suffix = "mySuffix"; String suffix = "mySuffix";
String value = "myValue"; String value = "myValue";
...@@ -76,5 +84,26 @@ public class EurekaRibbonClientConfigurationTests { ...@@ -76,5 +84,26 @@ public class EurekaRibbonClientConfigurationTests {
preprocessor.setProp(serviceId, suffix, value); preprocessor.setProp(serviceId, suffix, value);
assertEquals("property has wrong value", value, property.get()); assertEquals("property has wrong value", value, property.get());
} }
@Test
public void testDefaultZone() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean();
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService", configBean, false);
preprocessor.preprocess();
assertEquals("defaultZone", ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
}
@Test
public void testApproximateZone() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean();
configBean.setHostname("this.is.a.test.com");
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService", configBean, true);
preprocessor.preprocess();
assertEquals("is.a.test.com", ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
}
} }
...@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration; import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
...@@ -98,6 +99,12 @@ public class RibbonClientPreprocessorIntegrationTests { ...@@ -98,6 +99,12 @@ public class RibbonClientPreprocessorIntegrationTests {
filter.setZone("myTestZone"); filter.setZone("myTestZone");
return filter; return filter;
} }
@Bean
public EurekaInstanceConfigBean getEurekaInstanceConfigBean() {
EurekaInstanceConfigBean bean = new EurekaInstanceConfigBean();
return bean;
}
} }
} }
/* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
*
* @author Ryan Baxter
*
*/
public class ZoneUtilsTest {
@Test
public void extractApproximateZoneTest() {
assertTrue("foo".equals(ZoneUtils.extractApproximateZone("foo")));
assertTrue("bar".equals(ZoneUtils.extractApproximateZone("foo.bar")));
assertTrue("world.foo.bar".equals(ZoneUtils
.extractApproximateZone("hello.world.foo.bar")));
}
}
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