Switch to using EurekaClientConfig to determine client zone

This makes perfect sense since there is already support in the API.
Unfortunately Eureka also uses that information to set the Server
zones by default (duh?!) - see DiscoveryClient.getZone(InstanceInfo),
so unless you aggressively update them, the zones will all be the same
in all servers.

I fixed that problem by unconditionally applying the "domain as zone"
guess algorithm, which is fine unless you actually want to use
the Amazon metadata. So that's an outstanding problem

See gh-30
This commit is contained in:
Dave Syer
2014-10-17 09:54:18 +01:00
parent 997f531094
commit 859c96d31b
9 changed files with 43 additions and 57 deletions

View File

@@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
/**
* @author Spencer Gibb
*/
public class DiscoveryManagerIntitializer {
public class DiscoveryManagerInitializer {
@Autowired
private EurekaClientConfigBean clientConfig;

View File

@@ -83,6 +83,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
{
serviceUrl.put(DEFAULT_ZONE, "http://localhost:8761/v2/");
serviceUrl.put("default", "http://localhost:8761/v2/");
}
private boolean gZipContent = true;

View File

@@ -126,9 +126,9 @@ public class EurekaClientConfiguration implements SmartLifecycle, Ordered {
}
@Bean
@ConditionalOnMissingBean(DiscoveryManagerIntitializer.class)
public DiscoveryManagerIntitializer discoveryManagerIntitializer() {
return new DiscoveryManagerIntitializer();
@ConditionalOnMissingBean(DiscoveryManagerInitializer.class)
public DiscoveryManagerInitializer discoveryManagerIntitializer() {
return new DiscoveryManagerInitializer();
}
@Bean

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.springframework.util.StringUtils;
@@ -50,32 +48,23 @@ public class DomainExtractingServerList implements ServerList<Server> {
private List<Server> setZones(List<Server> servers) {
for (Server server : servers) {
if (!server.getZone().equals("default")) {
String zone = extractApproximateZone(server.getId());
server.setZone(zone);
}
String zone = extractApproximateZone(server);
server.setZone(zone);
}
return servers;
}
private String extractApproximateZone(String id) {
try {
URL url = new URL("http://" + id);
String host = url.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();
private String extractApproximateZone(Server server) {
String host = server.getHost();
if (!host.contains(".")) {
return host;
}
catch (MalformedURLException e) {
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 "defaultZone";
return builder.toString();
}
}

View File

@@ -8,11 +8,10 @@ import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilt
import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
import com.netflix.appinfo.AmazonInfo;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.client.ClientFactory;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext.ContextKey;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
@@ -29,24 +28,21 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
*/
public class EurekaRibbonInitializer implements ServerListInitializer {
private EurekaInstanceConfig instance;
private EurekaClientConfig client;
public EurekaRibbonInitializer(EurekaInstanceConfig instance) {
this.instance = instance;
public EurekaRibbonInitializer(EurekaClientConfig client) {
this.client = client;
}
@Override
public void initialize(String serviceId) {
if (instance != null
if (client != null
&& ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) {
// You can set this with archaius.deployment.* (maybe requires
// custom deployment context)?
String zone = instance.getMetadataMap().get("zone");
if (zone == null && instance.getDataCenterInfo() instanceof AmazonInfo) {
AmazonInfo info = (AmazonInfo) instance.getDataCenterInfo();
zone = info.getMetadata().get(AmazonInfo.MetaDataKey.availabilityZone);
}
String[] zones = client.getAvailabilityZones(client.getRegion());
String zone = zones != null && zones.length > 0 ? zones[0] : null;
if (zone != null) {
// You can set this with archaius.deployment.* (maybe requires
// custom deployment context)?
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
zone);
}
@@ -71,10 +67,10 @@ public class EurekaRibbonInitializer implements ServerListInitializer {
@SuppressWarnings("unchecked")
DynamicServerListLoadBalancer<Server> dynamic = (DynamicServerListLoadBalancer<Server>) balancer;
ServerList<Server> list = dynamic.getServerListImpl();
if (!(list instanceof DomainExtractingServerList)
&& !(instance.getDataCenterInfo() instanceof AmazonInfo)) {
// This is optional: you can use the native Eureka AWS features by making
// the EurekaInstanceConfig.dataCenterInfo an AmazonInfo
if (!(list instanceof DomainExtractingServerList)) {
// This is optional: you can use the native Eureka AWS features as long as
// the server zone is populated. TODO: find a way to back off if AWS
// metadata *is* available.
dynamic.setServerListImpl(new DomainExtractingServerList(list));
}
}

View File

@@ -15,9 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -28,6 +25,9 @@ import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
/**
* @author Dave Syer
*
@@ -40,10 +40,10 @@ import org.springframework.context.annotation.Configuration;
public class RibbonEurekaAutoConfiguration {
@Autowired(required=false)
private EurekaInstanceConfig instance;
private EurekaClientConfig client;
@Bean
public ServerListInitializer serverListInitializer() {
return new EurekaRibbonInitializer(instance);
return new EurekaRibbonInitializer(client);
}
}

View File

@@ -21,7 +21,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Test;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
import com.netflix.client.ClientFactory;
import com.netflix.config.ConfigurationManager;
@@ -43,10 +43,10 @@ public class EurekaRibbonInitializerTests {
@Test
public void basicConfigurationCreatedForLoadBalancer() {
EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean();
instance.getMetadataMap().put("zone", "foo");
EurekaClientConfigBean client = new EurekaClientConfigBean();
client.getAvailabilityZones().put(client.getRegion(), "foo");
EurekaRibbonInitializer initializer = new EurekaRibbonInitializer(
instance);
client);
initializer.initialize("service");
ILoadBalancer balancer = ClientFactory.getNamedLoadBalancer("service");
assertNotNull(balancer);

View File

@@ -36,7 +36,7 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
bean.setOrder(Ordered.LOWEST_PRECEDENCE);
bean.addInitParameter("com.sun.jersey.config.property.packages",
"com.netflix.discovery;com.netflix.eureka");
bean.addInitParameter(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, "true");
// bean.addInitParameter(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, "true");
bean.setUrlPatterns(Lists.newArrayList("/v2/*"));
return bean;
}

View File

@@ -30,7 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.eureka.DiscoveryManagerIntitializer;
import org.springframework.cloud.netflix.eureka.DiscoveryManagerInitializer;
import org.springframework.cloud.netflix.eureka.EurekaServerConfigBean;
import org.springframework.cloud.netflix.eureka.server.advice.LeaseManagerLite;
import org.springframework.cloud.netflix.eureka.server.advice.PiggybackMethodInterceptor;
@@ -82,9 +82,9 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
}
@Bean
@ConditionalOnMissingBean(DiscoveryManagerIntitializer.class)
public DiscoveryManagerIntitializer discoveryManagerIntitializer() {
return new DiscoveryManagerIntitializer();
@ConditionalOnMissingBean(DiscoveryManagerInitializer.class)
public DiscoveryManagerInitializer discoveryManagerIntitializer() {
return new DiscoveryManagerInitializer();
}
@Override