From c259293933b08c0de9a63b2ce73588c1b217c7e4 Mon Sep 17 00:00:00 2001 From: Max Liu Date: Thu, 17 Nov 2016 00:48:42 +0800 Subject: [PATCH] Add service instance zone support. (#251) fixes gh-249 --- .../discovery/ConsulDiscoveryProperties.java | 9 +++ .../consul/discovery/ConsulLifecycle.java | 3 + .../consul/discovery/ConsulServerList.java | 6 +- ...lLifecycleCustomizedInstanceZoneTests.java | 67 +++++++++++++++++++ .../discovery/ConsulServerListTests.java | 23 ++++++- 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulLifecycleCustomizedInstanceZoneTests.java diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java index 15152b34..99b93f1d 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java @@ -106,6 +106,15 @@ public class ConsulDiscoveryProperties { /** Unique service instance id */ private String instanceId; + /** Service instance zone */ + private String instanceZone; + + /** + * Service instance zone comes from metadata. + * This allows changing the metadata tag name. + */ + private String defaultZoneMetadataName = "zone"; + /** Whether to register an http or https service */ private String scheme = "http"; diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulLifecycle.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulLifecycle.java index 4d7a1693..0320bdce 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulLifecycle.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulLifecycle.java @@ -210,6 +210,9 @@ public class ConsulLifecycle extends AbstractDiscoveryLifecycle { && StringUtils.hasText(servletContext.getContextPath().replaceAll("/", ""))) { tags.add("contextPath=" + servletContext.getContextPath()); } + if (!StringUtils.isEmpty(properties.getInstanceZone())) { + tags.add(properties.getDefaultZoneMetadataName() + "=" + properties.getInstanceZone()); + } return tags; } diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulServerList.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulServerList.java index de18cb5b..f4dd6631 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulServerList.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulServerList.java @@ -70,7 +70,11 @@ public class ConsulServerList extends AbstractServerList { } List servers = new ArrayList<>(); for (HealthService service : response.getValue()) { - servers.add(new ConsulServer(service)); + ConsulServer server = new ConsulServer(service); + if (server.getMetadata().containsKey(this.properties.getDefaultZoneMetadataName())) { + server.setZone(server.getMetadata().get(this.properties.getDefaultZoneMetadataName())); + } + servers.add(server); } return servers; } diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulLifecycleCustomizedInstanceZoneTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulLifecycleCustomizedInstanceZoneTests.java new file mode 100644 index 00000000..c361c725 --- /dev/null +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulLifecycleCustomizedInstanceZoneTests.java @@ -0,0 +1,67 @@ +/* + * 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.consul.discovery; + +import com.ecwid.consul.v1.ConsulClient; +import com.ecwid.consul.v1.Response; +import com.ecwid.consul.v1.agent.model.Service; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * @author Sixian Liu + */ +@RunWith(SpringJUnit4ClassRunner.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@SpringApplicationConfiguration(classes = TestPropsConfig.class) +@WebIntegrationTest(value = { "spring.application.name=myTestService-WithZone", + "spring.cloud.consul.discovery.instanceId=myTestService1-WithZone", + "spring.cloud.consul.discovery.instanceZone=zone1", + "spring.cloud.consul.discovery.defaultZoneMetadataName=myZone"}, randomPort = true) +public class ConsulLifecycleCustomizedInstanceZoneTests { + + @Autowired + ConsulLifecycle lifecycle; + + @Autowired + ConsulClient consul; + + @Autowired + ApplicationContext context; + + @Test + public void contextLoads() { + Response> response = consul.getAgentServices(); + Map services = response.getValue(); + Service service = services.get("myTestService1-WithZone"); + assertNotNull("service was null", service); + assertNotEquals("service port is 0", 0, service.getPort().intValue()); + assertEquals("service id was wrong", "myTestService1-WithZone", service.getId()); + assertTrue("service zone was wrong", service.getTags().contains("myZone=zone1")); + } +} diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulServerListTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulServerListTests.java index 8014689d..d5452c30 100644 --- a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulServerListTests.java +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulServerListTests.java @@ -55,9 +55,18 @@ public class ConsulServerListTests { String tag = "mytag"; tagged.setTags(Arrays.asList(tag)); + NewService withZone = new NewService(); + withZone.setAddress("localhost"); + withZone.setId(name+"WithZone"); + withZone.setName(name); + withZone.setPort(10080); + String zone = "myzone"; + withZone.setTags(Arrays.asList("zone=" + zone)); + try { consul.agentServiceRegister(nonTagged); consul.agentServiceRegister(tagged); + consul.agentServiceRegister(withZone); InetUtils inetUtils = new InetUtils(new InetUtilsProperties()); DefaultClientConfigImpl config = new DefaultClientConfigImpl(); @@ -67,7 +76,18 @@ public class ConsulServerListTests { serverList.initWithNiwsConfig(config); List servers = serverList.getInitialListOfServers(); - assertThat("servers was wrong size", servers, hasSize(2)); + assertThat("servers was wrong size", servers, hasSize(3)); + + int serverWithZoneCount = 0; + for (ConsulServer server : servers) { + if (server.getMetadata().containsKey("zone")) { + serverWithZoneCount++; + assertThat("server was wrong zone", server.getZone(), is(zone)); + } else { + assertThat("server was wrong zone", server.getZone(), is(ConsulServer.UNKNOWN_ZONE)); + } + } + assertThat("server was wrong zone", serverWithZoneCount, is(1)); serverList = new ConsulServerList(consul, getProperties(name, tag, inetUtils)); serverList.initWithNiwsConfig(config); @@ -79,6 +99,7 @@ public class ConsulServerListTests { } finally { consul.agentServiceDeregister(nonTagged.getId()); consul.agentServiceDeregister(tagged.getId()); + consul.agentServiceDeregister(withZone.getId()); } }