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;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
......@@ -92,7 +90,7 @@ class DomainExtractingServer extends DiscoveryEnabledServer {
setZone(server.getInstanceInfo().getMetadata().get("zone"));
}
else if (approximateZoneFromHostname) {
setZone(extractApproximateZone(server));
setZone(ZoneUtils.extractApproximateZone(server.getHost()));
}
else {
setZone(server.getZone());
......@@ -112,18 +110,4 @@ class DomainExtractingServer extends DiscoveryEnabledServer {
}
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
import javax.annotation.PostConstruct;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.Configuration;
import org.springframework.util.StringUtils;
import com.netflix.client.config.IClientConfig;
import com.netflix.config.ConfigurationManager;
......@@ -45,8 +49,10 @@ import com.netflix.niws.loadbalancer.NIWSDiscoveryPing;
*
* @author Spencer Gibb
* @author Dave Syer
* @author Ryan Baxter
*/
@Configuration
@CommonsLog
public class EurekaRibbonClientConfiguration {
@Value("${ribbon.eureka.approximateZoneFromHostname:false}")
......@@ -62,13 +68,19 @@ public class EurekaRibbonClientConfiguration {
@Autowired(required = false)
private EurekaClientConfig clientConfig;
@Autowired
private EurekaInstanceConfigBean eurekaConfig;
public EurekaRibbonClientConfiguration() {
}
public EurekaRibbonClientConfiguration(EurekaClientConfig clientConfig,
String serviceId) {
String serviceId, EurekaInstanceConfigBean eurekaConfig,
boolean approximateZoneFromHostname) {
this.clientConfig = clientConfig;
this.serviceId = serviceId;
this.eurekaConfig = eurekaConfig;
this.approximateZoneFromHostname = approximateZoneFromHostname;
}
@Bean
......@@ -82,23 +94,36 @@ public class EurekaRibbonClientConfiguration {
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config) {
DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(config);
DomainExtractingServerList serverList = new DomainExtractingServerList(discoveryServerList, config, this.approximateZoneFromHostname);
DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(
config);
DomainExtractingServerList serverList = new DomainExtractingServerList(
discoveryServerList, config, this.approximateZoneFromHostname);
return serverList;
}
@PostConstruct
public void preprocess() {
if (this.clientConfig != null
&& ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) {
String zone = ConfigurationManager.getDeploymentContext().getValue(
ContextKey.zone);
if (this.clientConfig != null && StringUtils.isEmpty(zone)) {
if (approximateZoneFromHostname) {
String approxZone = ZoneUtils.extractApproximateZone(eurekaConfig
.getHostname());
log.debug("Setting Zone To " + approxZone);
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
approxZone);
}
else {
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig
.getRegion());
String zone = zones != null && zones.length > 0 ? zones[0] : null;
if (zone != null) {
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,
zone);
availabilityZone);
}
}
}
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 @@
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.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import com.netflix.config.ConfigurationManager;
......@@ -29,15 +36,14 @@ import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
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 Ryan Baxter
*/
public class EurekaRibbonClientConfigurationTests {
@After
@Before
public void close() {
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, "");
}
......@@ -46,10 +52,11 @@ public class EurekaRibbonClientConfigurationTests {
@Ignore
public void basicConfigurationCreatedForLoadBalancer() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean();
client.getAvailabilityZones().put(client.getRegion(), "foo");
SpringClientFactory clientFactory = new SpringClientFactory();
EurekaRibbonClientConfiguration clientPreprocessor = new EurekaRibbonClientConfiguration(
client, "service");
client, "service", configBean, false);
clientPreprocessor.preprocess();
ILoadBalancer balancer = clientFactory.getLoadBalancer("service");
assertNotNull(balancer);
......@@ -63,8 +70,9 @@ public class EurekaRibbonClientConfigurationTests {
@Test
public void testSetProp() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean();
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService");
client, "myService", configBean, false);
String serviceId = "myService";
String suffix = "mySuffix";
String value = "myValue";
......@@ -77,4 +85,25 @@ public class EurekaRibbonClientConfigurationTests {
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;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
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.RibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
......@@ -98,6 +99,12 @@ public class RibbonClientPreprocessorIntegrationTests {
filter.setZone("myTestZone");
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