Use eureka.instance zone data consistently determining client zone

The zone for a remote server comes from its
eureka.instance.metadataMap.zone, but we didn't (until this change)
apply the same logic to the client. If the client is registering
itslef with eureka then it will have a metadataMap itself and
we should be able to just reverse the logic.

Fixes gh-991
This commit is contained in:
Dave Syer
2016-04-27 09:06:57 +01:00
parent 8952cff24d
commit 6087bc755a
3 changed files with 62 additions and 26 deletions

View File

@@ -36,12 +36,12 @@ import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
import com.netflix.niws.loadbalancer.NIWSDiscoveryPing;
import lombok.extern.apachecommons.CommonsLog;
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
import static org.springframework.cloud.netflix.ribbon.RibbonProperyUtils.setRibbonProperty;
import lombok.extern.apachecommons.CommonsLog;
/**
* Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as:
* <code>@zone</code>, NIWSServerListClassName, DeploymentContextBasedVipAddresses,
@@ -104,21 +104,26 @@ public class EurekaRibbonClientConfiguration {
@PostConstruct
public void preprocess() {
String zone = ConfigurationManager.getDeploymentContext().getValue(
ContextKey.zone);
String zone = ConfigurationManager.getDeploymentContext()
.getValue(ContextKey.zone);
if (this.clientConfig != null && StringUtils.isEmpty(zone)) {
if (approximateZoneFromHostname && eurekaConfig != null) {
String approxZone = ZoneUtils.extractApproximateZone(eurekaConfig
.getHostName(false));
if (this.approximateZoneFromHostname && this.eurekaConfig != null) {
String approxZone = ZoneUtils
.extractApproximateZone(this.eurekaConfig.getHostName(false));
log.debug("Setting Zone To " + approxZone);
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
approxZone);
}
else {
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig
.getRegion());
String availabilityZone = zones != null && zones.length > 0 ? zones[0]
: null;
String availabilityZone = this.eurekaConfig == null ? null
: this.eurekaConfig.getMetadataMap().get("zone");
if (availabilityZone == null) {
String[] zones = this.clientConfig
.getAvailabilityZones(this.clientConfig.getRegion());
// Pick the first one from the regions we want to connect to
availabilityZone = zones != null && zones.length > 0 ? zones[0]
: null;
}
if (availabilityZone != null) {
// You can set this with archaius.deployment.* (maybe requires
// custom deployment context)?
@@ -127,7 +132,8 @@ public class EurekaRibbonClientConfiguration {
}
}
}
setRibbonProperty(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId);
setRibbonProperty(this.serviceId, DeploymentContextBasedVipAddresses.key(),
this.serviceId);
setRibbonProperty(this.serviceId, EnableZoneAffinity.key(), "true");
}

View File

@@ -36,8 +36,10 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
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.RibbonProperyUtils.*;
import static org.springframework.cloud.netflix.ribbon.RibbonProperyUtils.VALUE_NOT_SET;
import static org.springframework.cloud.netflix.ribbon.RibbonProperyUtils.getProperty;
import static org.springframework.cloud.netflix.ribbon.RibbonProperyUtils.getRibbonKey;
import static org.springframework.cloud.netflix.ribbon.RibbonProperyUtils.setRibbonProperty;
/**
* @author Dave Syer
@@ -83,15 +85,27 @@ public class EurekaRibbonClientConfigurationTests {
String serviceId = "myService";
String suffix = "mySuffix";
String value = "myValue";
DynamicStringProperty property = getProperty(getRibbonKey(
serviceId, suffix));
assertEquals("property doesn't have default value", VALUE_NOT_SET, property.get());
DynamicStringProperty property = getProperty(getRibbonKey(serviceId, suffix));
assertEquals("property doesn't have default value", VALUE_NOT_SET,
property.get());
setRibbonProperty(serviceId, suffix, value);
assertEquals("property has wrong value", value, property.get());
setRibbonProperty(serviceId, suffix, value);
assertEquals("property has wrong value", value, property.get());
}
@Test
public void testExplicitZone() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
EurekaInstanceConfigBean configBean = getEurekaInstanceConfigBean();
configBean.getMetadataMap().put("zone", "myZone");
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService", configBean, false);
preprocessor.preprocess();
assertEquals("myZone",
ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
}
@Test
public void testDefaultZone() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
@@ -99,9 +113,10 @@ public class EurekaRibbonClientConfigurationTests {
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService", configBean, false);
preprocessor.preprocess();
assertEquals("defaultZone", ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
assertEquals("defaultZone",
ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
}
@Test
public void testApproximateZone() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
@@ -110,7 +125,8 @@ public class EurekaRibbonClientConfigurationTests {
EurekaRibbonClientConfiguration preprocessor = new EurekaRibbonClientConfiguration(
client, "myService", configBean, true);
preprocessor.preprocess();
assertEquals("is.a.test.com", ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
assertEquals("is.a.test.com",
ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone));
}
}