Merge branch 'master' into 2.0.x
This commit is contained in:
@@ -121,8 +121,39 @@ spring:
|
||||
|
||||
With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the `vcap.application.instance_id` will be populated automatically in a Spring Boot application, so the random value will not be needed.
|
||||
|
||||
=== Using the DiscoveryClient
|
||||
Spring Cloud has support for https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign] (a REST client builder) and also https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon[Spring `RestTemplate`] using the logical service names instead of physical URLs.
|
||||
=== Looking up services
|
||||
|
||||
==== Using Ribbon
|
||||
|
||||
Spring Cloud has support for https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign] (a REST client builder) and also https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon[Spring `RestTemplate`]
|
||||
for looking up services using the logical service names/ids instead of physical URLs. Both Feign and the discovery-aware RestTemplate utilize http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#spring-cloud-ribbon[Ribbon] for client-side load balancing.
|
||||
|
||||
If you want to access service STORES using the RestTemplate simply declare:
|
||||
|
||||
----
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
public RestTemplate loadbalancedRestTemplate() {
|
||||
new RestTemplate();
|
||||
}
|
||||
----
|
||||
|
||||
and use it like this (notice how we use the STORES service name/id from Consul instead of a fully qualified domainname):
|
||||
|
||||
----
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
|
||||
public String getFirstProduct() {
|
||||
return this.restTemplate.getForObject("https://STORES/products/1", String.class);
|
||||
}
|
||||
----
|
||||
|
||||
If you have Consul clusters in multiple datacenters and you want to access a service in another datacenter a service name/id alone is not enough. In that case
|
||||
you use property `spring.cloud.consul.discovery.datacenters.STORES=dc-west` where `STORES` is the service name/id and `dc-west` is the datacenter
|
||||
where the STORES service lives.
|
||||
|
||||
==== Using the DiscoveryClient
|
||||
|
||||
You can also use the `org.springframework.cloud.client.discovery.DiscoveryClient` which provides a simple API for discovery clients that is not specific to Netflix, e.g.
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import lombok.Setter;
|
||||
* @author Spencer Gibb
|
||||
* @author Donnabell Dmello
|
||||
* @author Venil Noronha
|
||||
* @author Richard Kettelerij
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.consul.discovery")
|
||||
@Data
|
||||
@@ -132,6 +133,12 @@ public class ConsulDiscoveryProperties {
|
||||
*/
|
||||
private Map<String, String> serverListQueryTags = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map of serviceId's -> datacenter to query for in server list.
|
||||
* This allows looking up services in another datacenters.
|
||||
*/
|
||||
private Map<String, String> datacenters = new HashMap<>();
|
||||
|
||||
/** Tag to query for in service list if one is not listed in serverListQueryTags. */
|
||||
private String defaultQueryTag;
|
||||
|
||||
@@ -144,6 +151,9 @@ public class ConsulDiscoveryProperties {
|
||||
/** Register as a service in consul. */
|
||||
private boolean register = true;
|
||||
|
||||
/** Disable automatic de-registration of service in consul. */
|
||||
private boolean deregister = true;
|
||||
|
||||
/** Register health check in consul. Useful during development of a service. */
|
||||
private boolean registerHealthCheck = true;
|
||||
|
||||
@@ -169,7 +179,6 @@ public class ConsulDiscoveryProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param serviceId The service who's filtering tag is being looked up
|
||||
* @return The tag the given service id should be filtered by, or null.
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.netflix.loadbalancer.AbstractServerList;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Richard Kettelerij
|
||||
*/
|
||||
public class ConsulServerList extends AbstractServerList<ConsulServer> {
|
||||
|
||||
@@ -103,11 +104,16 @@ public class ConsulServerList extends AbstractServerList<ConsulServer> {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will create teh {@link QueryParams} to use when retrieving the
|
||||
* services from Consul. By default {@link QueryParams#DEFAULT} is used.
|
||||
* This method will create the {@link QueryParams} to use when retrieving the
|
||||
* services from Consul. By default {@link QueryParams#DEFAULT} is used. In case
|
||||
* a datacenter is specified for the current serviceId {@link QueryParams#datacenter} is set.
|
||||
* @return an instance of {@link QueryParams}
|
||||
*/
|
||||
protected QueryParams createQueryParamsForClientRequest() {
|
||||
String datacenter = getDatacenter();
|
||||
if (datacenter != null) {
|
||||
return new QueryParams(datacenter);
|
||||
}
|
||||
return QueryParams.DEFAULT;
|
||||
}
|
||||
|
||||
@@ -115,6 +121,10 @@ public class ConsulServerList extends AbstractServerList<ConsulServer> {
|
||||
return this.properties.getQueryTagForService(this.serviceId);
|
||||
}
|
||||
|
||||
protected String getDatacenter() {
|
||||
return this.properties.getDatacenters().get(this.serviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("ConsulServerList{");
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ConsulAutoServiceRegistration extends AbstractAutoServiceRegistrati
|
||||
|
||||
@Override
|
||||
protected void deregister() {
|
||||
if (!this.properties.isRegister()) {
|
||||
if (!this.properties.isRegister() || !this.properties.isDeregister()) {
|
||||
return;
|
||||
}
|
||||
super.deregister();
|
||||
@@ -101,7 +101,7 @@ public class ConsulAutoServiceRegistration extends AbstractAutoServiceRegistrati
|
||||
|
||||
@Override
|
||||
protected void deregisterManagement() {
|
||||
if (!this.properties.isRegister()) {
|
||||
if (!this.properties.isRegister() || !this.properties.isDeregister()) {
|
||||
return;
|
||||
}
|
||||
super.deregisterManagement();
|
||||
|
||||
@@ -15,16 +15,19 @@ public class ConsulDiscoveryPropertiesTests {
|
||||
|
||||
private static final String DEFAULT_TAG = "defaultTag";
|
||||
private static final String MAP_TAG = "mapTag";
|
||||
private static final String MAP_DC = "mapDc";
|
||||
private static final String SERVICE_NAME_IN_MAP = "serviceNameInMap";
|
||||
private static final String SERVICE_NAME_NOT_IN_MAP = "serviceNameNotInMap";
|
||||
private ConsulDiscoveryProperties properties;
|
||||
private Map<String, String> serverListQueryTags = Collections.singletonMap(SERVICE_NAME_IN_MAP, MAP_TAG);
|
||||
private Map<String, String> datacenters = Collections.singletonMap(SERVICE_NAME_IN_MAP, MAP_DC);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
properties = new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties()));
|
||||
properties.setDefaultQueryTag(DEFAULT_TAG);
|
||||
properties.setServerListQueryTags(serverListQueryTags);
|
||||
properties.setDatacenters(datacenters);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -43,4 +46,14 @@ public class ConsulDiscoveryPropertiesTests {
|
||||
public void testGetTagReturnsMapValueWhenInMap() throws Exception {
|
||||
assertEquals(MAP_TAG, properties.getQueryTagForService(SERVICE_NAME_IN_MAP));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDcReturnsNullWhenNotInMap() throws Exception {
|
||||
assertNull(properties.getDatacenters().get(SERVICE_NAME_NOT_IN_MAP));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDcReturnsMapValueWhenInMap() throws Exception {
|
||||
assertEquals(MAP_DC, properties.getDatacenters().get(SERVICE_NAME_IN_MAP));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2013-2017 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.serviceregistry;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.agent.model.Service;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
|
||||
import org.springframework.cloud.consul.ConsulAutoConfiguration;
|
||||
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
/**
|
||||
* @author Jon Freedman
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = ConsulAutoServiceRegistrationDisabledTests.TestConfig.class,
|
||||
properties = {"spring.application.name=myTestNotDeRegisteredService",
|
||||
"spring.cloud.consul.discovery.instanceId=myTestNotDeRegisteredService-D",
|
||||
"spring.cloud.consul.discovery.deregister=false"},
|
||||
webEnvironment = RANDOM_PORT)
|
||||
public class ConsulAutoServiceDeRegistrationDisabledTests {
|
||||
@Autowired
|
||||
private ConsulClient consul;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ConsulAutoServiceRegistration autoServiceRegistration;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ConsulDiscoveryProperties discoveryProperties;
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
assertNotNull("ConsulAutoServiceRegistration was not created", autoServiceRegistration);
|
||||
assertNotNull("ConsulDiscoveryProperties was not created", discoveryProperties);
|
||||
|
||||
checkService(true);
|
||||
autoServiceRegistration.deregister();
|
||||
checkService(true);
|
||||
discoveryProperties.setDeregister(true);
|
||||
autoServiceRegistration.deregister();
|
||||
checkService(false);
|
||||
}
|
||||
|
||||
private void checkService(final boolean expected) {
|
||||
final Response<Map<String, Service>> response = consul.getAgentServices();
|
||||
final Map<String, Service> services = response.getValue();
|
||||
final Service service = services.get("myTestNotDeRegisteredService-D");
|
||||
if (expected) {
|
||||
assertNotNull("service was not registered", service);
|
||||
} else {
|
||||
assertNull("service was registered", service);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ImportAutoConfiguration({AutoServiceRegistrationConfiguration.class, ConsulAutoConfiguration.class,
|
||||
ConsulAutoServiceRegistrationAutoConfiguration.class})
|
||||
public static class TestConfig {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user