From 03f6d12e5087ad93c0e35864255e8c7475723f7a Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 22 Dec 2015 15:04:57 -0700 Subject: [PATCH] Implement ServiceInstance.getMetadata. Introduce ServerIntrospector.getMetadata(Server). fixes gh-419 --- .../netflix/eureka/EurekaDiscoveryClient.java | 11 ++++ .../ribbon/DefaultServerIntrospector.java | 8 +++ .../ribbon/RibbonLoadBalancerClient.java | 58 +++++++++++-------- .../netflix/ribbon/ServerIntrospector.java | 4 ++ .../eureka/EurekaServerIntrospector.java | 18 +++++- .../ribbon/RibbonLoadBalancerClientTests.java | 43 +++++++++----- 6 files changed, 101 insertions(+), 41 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java index da380116..9a4768f6 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java @@ -22,6 +22,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; @@ -79,6 +80,11 @@ public class EurekaDiscoveryClient implements DiscoveryClient { public URI getUri() { return DefaultServiceInstance.getUri(this); } + + @Override + public Map getMetadata() { + return EurekaDiscoveryClient.this.config.getMetadataMap(); + } }; } @@ -132,6 +138,11 @@ public class EurekaDiscoveryClient implements DiscoveryClient { public URI getUri() { return DefaultServiceInstance.getUri(this); } + + @Override + public Map getMetadata() { + return this.instance.getMetadata(); + } } @Override diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/DefaultServerIntrospector.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/DefaultServerIntrospector.java index 1356ea57..a228544f 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/DefaultServerIntrospector.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/DefaultServerIntrospector.java @@ -16,6 +16,9 @@ package org.springframework.cloud.netflix.ribbon; +import java.util.Collections; +import java.util.Map; + import com.netflix.loadbalancer.Server; /** @@ -27,4 +30,9 @@ public class DefaultServerIntrospector implements ServerIntrospector { // Can we do better? return (""+server.getPort()).endsWith("443"); } + + @Override + public Map getMetadata(Server server) { + return Collections.emptyMap(); + } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java index 244512d6..ff13f0ce 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java @@ -17,6 +17,8 @@ package org.springframework.cloud.netflix.ribbon; import java.net.URI; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.TimeUnit; import org.springframework.cloud.client.DefaultServiceInstance; @@ -24,17 +26,14 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.web.util.UriComponentsBuilder; -import com.netflix.appinfo.InstanceInfo.PortType; import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerStats; -import com.netflix.niws.loadbalancer.DiscoveryEnabledServer; import com.netflix.servo.monitor.Stopwatch; /** @@ -56,7 +55,7 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { RibbonLoadBalancerContext context = this.clientFactory .getLoadBalancerContext(serviceId); Server server = new Server(instance.getHost(), instance.getPort()); - boolean secure = isSecure(this.clientFactory, server, serviceId); + boolean secure = isSecure(server, serviceId); URI uri = original; if (secure) { uri = UriComponentsBuilder.fromUri(uri).scheme("https").build().toUri(); @@ -70,8 +69,8 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { if (server == null) { return null; } - return new RibbonServer(serviceId, server, - isSecure(this.clientFactory, server, serviceId)); + return new RibbonServer(serviceId, server, isSecure(server, serviceId), + serverIntrospector(serviceId).getMetadata(server)); } @Override @@ -80,8 +79,8 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { RibbonLoadBalancerContext context = this.clientFactory .getLoadBalancerContext(serviceId); Server server = getServer(loadBalancer); - RibbonServer ribbonServer = new RibbonServer(serviceId, server, - isSecure(this.clientFactory, server, serviceId)); + RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server, + serviceId), serverIntrospector(serviceId).getMetadata(server)); ServerStats serverStats = context.getServerStats(server); context.noteOpenConnection(serverStats); @@ -99,25 +98,29 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { return null; } - private boolean isSecure(SpringClientFactory clientFactory, Server server, - String serviceId) { - IClientConfig config = clientFactory.getClientConfig(serviceId); - if (config != null) { - return config.get(CommonClientConfigKey.IsSecure, false); - } - ServerIntrospector serverIntrospector = clientFactory.getInstance(serviceId, ServerIntrospector.class); + private ServerIntrospector serverIntrospector(String serviceId) { + ServerIntrospector serverIntrospector = this.clientFactory.getInstance(serviceId, + ServerIntrospector.class); if (serverIntrospector == null) { serverIntrospector = new DefaultServerIntrospector(); } - return serverIntrospector.isSecure(server); + return serverIntrospector; + } + + private boolean isSecure(Server server, String serviceId) { + IClientConfig config = this.clientFactory.getClientConfig(serviceId); + if (config != null) { + return config.get(CommonClientConfigKey.IsSecure, false); + } + + return serverIntrospector(serviceId).isSecure(server); } private void recordStats(RibbonLoadBalancerContext context, Stopwatch tracer, ServerStats serverStats, Object entity, Throwable exception) { tracer.stop(); long duration = tracer.getDuration(TimeUnit.MILLISECONDS); - context.noteRequestCompletion(serverStats, entity, exception, duration, - null/* errorHandler */); + context.noteRequestCompletion(serverStats, entity, exception, duration, null/* errorHandler */); } protected Server getServer(String serviceId) { @@ -136,17 +139,21 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { } protected static class RibbonServer implements ServiceInstance { - private String serviceId; - private Server server; - private boolean secure; + private final String serviceId; + private final Server server; + private final boolean secure; + private Map metadata; protected RibbonServer(String serviceId, Server server) { - this(serviceId, server, false); + this(serviceId, server, false, Collections. emptyMap()); } - protected RibbonServer(String serviceId, Server server, boolean secure) { + protected RibbonServer(String serviceId, Server server, boolean secure, + Map metadata) { this.serviceId = serviceId; this.server = server; + this.secure = secure; + this.metadata = metadata; } @Override @@ -174,6 +181,11 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { return DefaultServiceInstance.getUri(this); } + @Override + public Map getMetadata() { + return this.metadata; + } + public Server getServer() { return this.server; } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/ServerIntrospector.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/ServerIntrospector.java index 8842c595..0e62b8f3 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/ServerIntrospector.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/ServerIntrospector.java @@ -16,6 +16,8 @@ package org.springframework.cloud.netflix.ribbon; +import java.util.Map; + import com.netflix.loadbalancer.Server; /** @@ -24,4 +26,6 @@ import com.netflix.loadbalancer.Server; public interface ServerIntrospector { boolean isSecure(Server server); + + Map getMetadata(Server server); } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaServerIntrospector.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaServerIntrospector.java index 904bcf96..4bf4f74a 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaServerIntrospector.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaServerIntrospector.java @@ -16,10 +16,13 @@ package org.springframework.cloud.netflix.ribbon.eureka; +import java.util.Map; + +import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; + import com.netflix.appinfo.InstanceInfo; import com.netflix.loadbalancer.Server; import com.netflix.niws.loadbalancer.DiscoveryEnabledServer; -import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; /** * @author Spencer Gibb @@ -29,9 +32,18 @@ public class EurekaServerIntrospector extends DefaultServerIntrospector { @Override public boolean isSecure(Server server) { if (server instanceof DiscoveryEnabledServer) { - DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server; - return enabled.getInstanceInfo().isPortEnabled(InstanceInfo.PortType.SECURE); + DiscoveryEnabledServer discoveryServer = (DiscoveryEnabledServer) server; + return discoveryServer.getInstanceInfo().isPortEnabled(InstanceInfo.PortType.SECURE); } return super.isSecure(server); } + + @Override + public Map getMetadata(Server server) { + if (server instanceof DiscoveryEnabledServer) { + DiscoveryEnabledServer discoveryServer = (DiscoveryEnabledServer) server; + return discoveryServer.getInstanceInfo().getMetadata(); + } + return super.getMetadata(server); + } } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java index 5c4c9eae..22d22835 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java @@ -16,22 +16,10 @@ package org.springframework.cloud.netflix.ribbon; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; -import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.anyDouble; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import java.net.URI; import java.net.URL; - -import lombok.SneakyThrows; +import java.util.Collections; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -48,6 +36,21 @@ import com.netflix.loadbalancer.LoadBalancerStats; import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerStats; +import lombok.SneakyThrows; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + /** * @author Spencer Gibb */ @@ -70,6 +73,13 @@ public class RibbonLoadBalancerClientTests { MockitoAnnotations.initMocks(this); given(this.clientFactory.getLoadBalancerContext(anyString())).willReturn( new RibbonLoadBalancerContext(this.loadBalancer)); + given(this.clientFactory.getInstance(anyString(), eq(ServerIntrospector.class))) + .willReturn(new DefaultServerIntrospector() { + @Override + public Map getMetadata(Server server) { + return Collections.singletonMap("mykey", "myvalue"); + } + }); } @Test @@ -167,7 +177,8 @@ public class RibbonLoadBalancerClientTests { } protected RibbonServer getRibbonServer() { - return new RibbonServer("testService", new Server("myhost", 9080)); + return new RibbonServer("testService", new Server("myhost", 9080), false, + Collections.singletonMap("mykey", "myvalue")); } protected void verifyServerStats() { @@ -184,6 +195,8 @@ public class RibbonLoadBalancerClientTests { instance.getServiceId()); assertEquals("host was wrong", ribbonServer.getHost(), instance.getHost()); assertEquals("port was wrong", ribbonServer.getPort(), instance.getPort()); + assertEquals("missing metadata", ribbonServer.getMetadata().get("mykey"), + instance.getMetadata().get("mykey")); } protected RibbonLoadBalancerClient getRibbonLoadBalancerClient(