Add metadataMap option for Server.zone

Adds a metadataMap for the Server.zone so that user can
provide the data through external configuration if needed.
This commit is contained in:
Dave Syer
2015-02-03 12:13:21 +01:00
parent 4afc44acaf
commit 4c5179130e
3 changed files with 49 additions and 12 deletions

View File

@@ -235,6 +235,9 @@ By default every Eureka server is also a Eureka client and requires
the service will run and work, but it will shower your logs with a lot
of noise about not being able to register with the peer.
See also <<spring-cloud-ribbon,below for details of Ribbon
support>> on the client side for Zones and Regions.
=== Standalone Mode
The combination of the two caches (client and server) and the
@@ -495,11 +498,22 @@ This replaces the `NoOpPing` with `PingUrl`.
=== Using the Ribbon with Eureka
When Eureka is used in conjunction with Ribbon the `ribbonServerList` is
overridden with an extension of `DiscoveryEnabledNIWSServerList` which
populates the list of servers from Eureka. It also replaces the `IPing`
interface with `NIWSDiscoveryPing` which delegates to Eureka to determine if
a server is up.
When Eureka is used in conjunction with Ribbon the `ribbonServerList`
is overridden with an extension of `DiscoveryEnabledNIWSServerList`
which populates the list of servers from Eureka. It also replaces the
`IPing` interface with `NIWSDiscoveryPing` which delegates to Eureka
to determine if a server is up. The `ServerList` that is installed by
default is a `DomainExtractingServerList` and the purpose of this is
to make physical metadata available to the load balancer without using
AWS AMI metadata (which is what Netflix relies on). By default the
server list will be constructed with "zone" information as provided in
the instance metadata (so on the client set
`eureka.instance.metadataMap.zone`), and if that is missing it can use
the domain name from the server hostname as a proxy for zone (if the
flag `approximateZoneFromDomain` is set). Once the zone information is
available it can be used in a `ServerListFilter` (by default it will
be used to locate a server in the same zone as the client because the
default is a `ZonePreferenceServerListFilter`).
[[spring-cloud-ribbon-without-eureka]]
=== Example: How to Use Ribbon Without Eureka

View File

@@ -51,13 +51,15 @@ public class DomainExtractingServerList implements ServerList<DiscoveryEnabledSe
@Override
public List<DiscoveryEnabledServer> getInitialListOfServers() {
List<DiscoveryEnabledServer> servers = setZones(this.list.getInitialListOfServers());
List<DiscoveryEnabledServer> servers = setZones(this.list
.getInitialListOfServers());
return servers;
}
@Override
public List<DiscoveryEnabledServer> getUpdatedListOfServers() {
List<DiscoveryEnabledServer> servers = setZones(this.list.getUpdatedListOfServers());
List<DiscoveryEnabledServer> servers = setZones(this.list
.getUpdatedListOfServers());
return servers;
}
@@ -68,8 +70,8 @@ public class DomainExtractingServerList implements ServerList<DiscoveryEnabledSe
boolean shouldUseIpAddr = this.clientConfig.getPropertyAsBoolean(
CommonClientConfigKey.UseIPAddrForServer, Boolean.FALSE);
for (DiscoveryEnabledServer server : servers) {
result.add(new DomainExtractingServer(server,
isSecure, shouldUseIpAddr, this.approximateZoneFromHostname));
result.add(new DomainExtractingServer(server, isSecure, shouldUseIpAddr,
this.approximateZoneFromHostname));
}
return result;
}
@@ -86,7 +88,10 @@ class DomainExtractingServer extends DiscoveryEnabledServer {
boolean useIpAddr, boolean approximateZoneFromHostname) {
// host and port are set in super()
super(server.getInstanceInfo(), useSecurePort, useIpAddr);
if (approximateZoneFromHostname) {
if (server.getInstanceInfo().getMetadata().containsKey("zone")) {
setZone(server.getInstanceInfo().getMetadata().get("zone"));
}
else if (approximateZoneFromHostname) {
setZone(extractApproximateZone(server));
}
else {

View File

@@ -18,7 +18,9 @@ package org.springframework.cloud.netflix.ribbon.eureka;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
@@ -50,6 +52,9 @@ public class DomainExtractingServerListTests {
static final String INSTANCE_ID = "myInstanceId";
private Map<String, String> metadata = Collections.<String, String> singletonMap(
"instanceId", INSTANCE_ID);
@Test
public void testDomainExtractingServer() {
DomainExtractingServerList serverList = getDomainExtractingServerList(
@@ -61,6 +66,20 @@ public class DomainExtractingServerListTests {
assertEquals("hostPort was wrong", HOST_NAME + ":" + PORT, des.getHostPort());
}
@Test
public void testZoneInMetaData() {
this.metadata = new HashMap<String, String>();
this.metadata.put("zone", "us-west-1");
this.metadata.put("instanceId", INSTANCE_ID);
DomainExtractingServerList serverList = getDomainExtractingServerList(
new DefaultClientConfigImpl(), false);
List<DiscoveryEnabledServer> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
DomainExtractingServer des = assertDomainExtractingServer(servers, "us-west-1");
assertEquals("Zone was wrong", "us-west-1", des.getZone());
}
@Test
public void testDomainExtractingServerDontApproximateZone() {
DomainExtractingServerList serverList = getDomainExtractingServerList(
@@ -104,8 +123,7 @@ public class DomainExtractingServerListTests {
InstanceInfo instanceInfo = mock(InstanceInfo.class);
given(server.getInstanceInfo()).willReturn(instanceInfo);
given(server.getHost()).willReturn(HOST_NAME);
given(instanceInfo.getMetadata()).willReturn(
Collections.<String, String> singletonMap("instanceId", INSTANCE_ID));
given(instanceInfo.getMetadata()).willReturn(this.metadata);
given(instanceInfo.getHostName()).willReturn(HOST_NAME);
given(instanceInfo.getIPAddr()).willReturn(IP_ADDR);
given(instanceInfo.getPort()).willReturn(PORT);