Initial Service Registry impl

ZookeeperServiceDiscovery and ZookeeperLifecycle are deprecated. They
are still supported if user creates a @Bean for each.

Adds a ZookeeperServiceRegistry implementation and support for auto
registration.
This commit is contained in:
Spencer Gibb
2016-12-15 12:16:53 -07:00
parent 465f416121
commit 42f643bcaa
31 changed files with 1278 additions and 186 deletions

26
circle.yml Normal file
View File

@@ -0,0 +1,26 @@
general:
branches:
ignore:
- gh-pages # list of branches to ignore
machine:
java:
version: oraclejdk8
environment:
_JAVA_OPTIONS: "-Xms1024m -Xmx2048m"
dependencies:
override:
- ./mvnw -s .settings.xml -U --fail-never dependency:go-offline || true
test:
override:
- ./mvnw -s .settings.xml clean install org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
post:
- find . -type f -regex ".*/spring-cloud-*.*/target/*.*" | cpio -pdm $CIRCLE_ARTIFACTS
- mkdir -p $CIRCLE_TEST_REPORTS/junit/
- find . -type f -regex ".*/target/.*-reports/.*" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
- bash <(curl -s https://codecov.io/bash)
notify:
webhooks:
# A list of hook hashes, containing the url field
# gitter hook
- url: https://webhooks.gitter.im/e/22e6bb4eb945dd61ba54

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2013-2016 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.zookeeper.compat;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import java.util.concurrent.atomic.AtomicReference;
/**
* @deprecated for backwards compatibility. Will be removed in Edgware.
* @author Spencer Gibb
*/
@Deprecated
public interface ServiceDiscoveryHolder {
AtomicReference<ServiceDiscovery<ZookeeperInstance>> getServiceDiscoveryRef();
CuratorFramework getCurator();
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2013-2016 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.zookeeper.compat;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import java.util.concurrent.atomic.AtomicReference;
/**
* @deprecated for backwards compatibility. Will be removed in Edgware.
* @author Spencer Gibb
*/
@Deprecated
public interface ServiceInstanceHolder {
AtomicReference<ServiceInstance<ZookeeperInstance>> getServiceInstanceRef();
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2013-2016 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.zookeeper.discovery;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Spencer Gibb
* @since 1.1.0
*/
@Configuration
@ConditionalOnBean(ZookeeperDiscoveryClientConfiguration.Marker.class)
@ConditionalOnProperty(value = "spring.cloud.zookeeper.discovery.enabled", matchIfMissing = true)
@AutoConfigureBefore({CommonsClientAutoConfiguration.class, NoopDiscoveryClientAutoConfiguration.class})
public class ZookeeperDiscoveryAutoConfiguration {
@Autowired(required = false)
private ZookeeperDependencies zookeeperDependencies;
@Autowired
private CuratorFramework curator;
@Bean
@ConditionalOnMissingBean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(InetUtils inetUtils) {
return new ZookeeperDiscoveryProperties(inetUtils);
}
@Bean
@ConditionalOnBean(ZookeeperServiceDiscovery.class)
public ZookeeperDiscoveryClient zookeeperDiscoveryClientDeprecated(ZookeeperServiceDiscovery zookeeperServiceDiscovery) {
return new ZookeeperDiscoveryClient(zookeeperServiceDiscovery, this.zookeeperDependencies);
}
@Bean
@ConditionalOnMissingBean(ZookeeperServiceDiscovery.class)
// currently means auto-registration is false. That will change when ZookeeperServiceDiscovery is gone
public ZookeeperDiscoveryClient zookeeperDiscoveryClient(ZookeeperServiceRegistry registry) {
return new ZookeeperDiscoveryClient(registry, null, this.zookeeperDependencies);
}
@Bean
@ConditionalOnMissingBean
public InstanceSerializer<ZookeeperInstance> instanceSerializer() {
return new JsonInstanceSerializer<>(ZookeeperInstance.class);
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class ZookeeperDiscoveryHealthConfig {
@Autowired(required = false)
private ZookeeperDependencies zookeeperDependencies;
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(ZookeeperServiceDiscovery.class)
public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicatorDeprecated(ZookeeperServiceDiscovery serviceDiscovery,
ZookeeperDiscoveryProperties properties) {
return new ZookeeperDiscoveryHealthIndicator(serviceDiscovery,
this.zookeeperDependencies, properties);
}
@Bean
@ConditionalOnMissingBean({ZookeeperDiscoveryHealthIndicator.class, ZookeeperServiceDiscovery.class})
public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicator(ZookeeperServiceRegistry registry,
ZookeeperDiscoveryProperties properties) {
return new ZookeeperDiscoveryHealthIndicator(registry,
this.zookeeperDependencies, properties);
}
}
@Bean
public ZookeeperServiceWatch zookeeperServiceWatch(ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
return new ZookeeperServiceWatch(this.curator, zookeeperDiscoveryProperties);
}
}

View File

@@ -28,7 +28,11 @@ import org.apache.commons.logging.LogFactory;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.zookeeper.compat.ServiceDiscoveryHolder;
import org.springframework.cloud.zookeeper.compat.ServiceInstanceHolder;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import org.springframework.util.ReflectionUtils;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
@@ -45,12 +49,21 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
private static final Log log = LogFactory.getLog(ZookeeperDiscoveryClient.class);
private ZookeeperServiceDiscovery serviceDiscovery;
private ServiceDiscoveryHolder serviceDiscovery;
private ServiceInstanceHolder serviceInstanceHolder;
private ZookeeperDependencies zookeeperDependencies;
@Deprecated
public ZookeeperDiscoveryClient(ZookeeperServiceDiscovery serviceDiscovery, ZookeeperDependencies zookeeperDependencies) {
this.serviceDiscovery = serviceDiscovery;
this.serviceInstanceHolder = serviceDiscovery;
this.zookeeperDependencies = zookeeperDependencies;
}
public ZookeeperDiscoveryClient(ZookeeperServiceRegistry registry, ZookeeperRegistration registration, ZookeeperDependencies zookeeperDependencies) {
this.serviceDiscovery = registry;
this.serviceInstanceHolder = null;
this.zookeeperDependencies = zookeeperDependencies;
}
@@ -61,7 +74,10 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
@Override
public org.springframework.cloud.client.ServiceInstance getLocalServiceInstance() {
ServiceInstance<ZookeeperInstance> serviceInstance = this.serviceDiscovery.getServiceInstance();
if (this.serviceInstanceHolder == null) {
return null;
}
ServiceInstance<ZookeeperInstance> serviceInstance = this.serviceInstanceHolder.getServiceInstanceRef().get();
return serviceInstance == null ? null : createServiceInstance(serviceInstance.getName(), serviceInstance);
}
@@ -84,12 +100,12 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
public List<org.springframework.cloud.client.ServiceInstance> getInstances(
final String serviceId) {
try {
if (this.serviceDiscovery.getServiceDiscovery() == null) {
if (this.serviceDiscovery.getServiceDiscoveryRef().get() == null) {
return Collections.EMPTY_LIST;
}
String serviceIdToQuery = getServiceIdToQuery(serviceId);
Collection<ServiceInstance<ZookeeperInstance>> zkInstances = this.serviceDiscovery
.getServiceDiscovery().queryForInstances(serviceIdToQuery);
.getServiceDiscoveryRef().get().queryForInstances(serviceIdToQuery);
List<org.springframework.cloud.client.ServiceInstance> instances = new ArrayList<>();
for (ServiceInstance<ZookeeperInstance> instance : zkInstances) {
instances.add(createServiceInstance(serviceIdToQuery, instance));
@@ -112,12 +128,12 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
@Override
public List<String> getServices() {
List<String> services = null;
if (this.serviceDiscovery.getServiceDiscovery() == null) {
if (this.serviceDiscovery.getServiceDiscoveryRef() == null) {
log.warn("Service Discovery is not yet ready - returning empty list of services");
return Collections.emptyList();
}
try {
services = new ArrayList<>(this.serviceDiscovery.getServiceDiscovery().queryForNames());
services = new ArrayList<>(this.serviceDiscovery.getServiceDiscoveryRef().get().queryForNames());
}
catch (Exception e) {
rethrowRuntimeException(e);

View File

@@ -16,16 +16,7 @@
package org.springframework.cloud.zookeeper.discovery;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -40,60 +31,11 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnProperty(value = "spring.cloud.zookeeper.discovery.enabled", matchIfMissing = true)
public class ZookeeperDiscoveryClientConfiguration {
@Autowired(required = false)
private ZookeeperDependencies zookeeperDependencies;
@Autowired
private CuratorFramework curator;
class Marker {}
@Bean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(InetUtils inetUtils) {
return new ZookeeperDiscoveryProperties(inetUtils);
}
@Bean
@ConditionalOnMissingBean
public ZookeeperServiceDiscovery zookeeperServiceDiscovery(ZookeeperDiscoveryProperties zookeeperDiscoveryProperties, InstanceSerializer<ZookeeperInstance> instanceSerializer) {
return new ZookeeperServiceDiscovery(this.curator, zookeeperDiscoveryProperties,
instanceSerializer);
}
@Bean
public ZookeeperLifecycle zookeeperLifecycle(ZookeeperServiceDiscovery zookeeperServiceDiscovery, ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
return new ZookeeperLifecycle(zookeeperDiscoveryProperties, zookeeperServiceDiscovery);
}
@Bean
public ZookeeperDiscoveryClient zookeeperDiscoveryClient(ZookeeperServiceDiscovery zookeeperServiceDiscovery) {
return new ZookeeperDiscoveryClient(zookeeperServiceDiscovery, this.zookeeperDependencies);
}
@Bean
public InstanceSerializer<ZookeeperInstance> instanceSerializer() {
return new JsonInstanceSerializer<>(ZookeeperInstance.class);
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class ZookeeperDiscoveryHealthConfig {
@Autowired
private ZookeeperServiceDiscovery serviceDiscovery;
@Autowired
private ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;
@Autowired(required = false)
private ZookeeperDependencies zookeeperDependencies;
@Bean
@ConditionalOnMissingBean
public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicator() {
return new ZookeeperDiscoveryHealthIndicator(this.serviceDiscovery,
this.zookeeperDependencies, this.zookeeperDiscoveryProperties);
}
}
@Bean
public ZookeeperServiceWatch zookeeperServiceWatch(ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
return new ZookeeperServiceWatch(this.curator, zookeeperDiscoveryProperties);
public Marker zookeeperDiscoveryClientMarker() {
return new Marker();
}
}

View File

@@ -22,22 +22,26 @@ import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.boot.actuate.health.Health;
import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
/**
* {@link org.springframework.boot.actuate.health.HealthIndicator} that presents
* the status of all instances registered in Zookeeper.
* {@link org.springframework.boot.actuate.health.HealthIndicator} that presents the
* status of all instances registered in Zookeeper.
*
* @author Spencer Gibb
* @since 1.0.0
*/
public class ZookeeperDiscoveryHealthIndicator implements DiscoveryHealthIndicator {
private static final Log log = LogFactory .getLog(ZookeeperDiscoveryHealthIndicator.class);
private static final Log log = LogFactory
.getLog(ZookeeperDiscoveryHealthIndicator.class);
private ZookeeperServiceDiscovery serviceDiscovery;
private ZookeeperServiceRegistry serviceRegistry;
private ZookeeperDependencies zookeeperDependencies;
private ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;
@Deprecated
public ZookeeperDiscoveryHealthIndicator(ZookeeperServiceDiscovery serviceDiscovery,
ZookeeperDependencies zookeeperDependencies,
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
@@ -46,6 +50,14 @@ public class ZookeeperDiscoveryHealthIndicator implements DiscoveryHealthIndicat
this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties;
}
public ZookeeperDiscoveryHealthIndicator(ZookeeperServiceRegistry serviceRegistry,
ZookeeperDependencies zookeeperDependencies,
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
this.serviceRegistry = serviceRegistry;
this.zookeeperDependencies = zookeeperDependencies;
this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties;
}
@Override
public String getName() {
return "zookeeper";
@@ -55,9 +67,16 @@ public class ZookeeperDiscoveryHealthIndicator implements DiscoveryHealthIndicat
public Health health() {
Health.Builder builder = Health.unknown();
try {
Iterable<ServiceInstance<ZookeeperInstance>> allInstances = new ZookeeperServiceInstances(
this.serviceDiscovery, this.zookeeperDependencies,
this.zookeeperDiscoveryProperties);
Iterable<ServiceInstance<ZookeeperInstance>> allInstances;
if (this.serviceDiscovery != null) {
allInstances = new ZookeeperServiceInstances(
this.serviceDiscovery, this.zookeeperDependencies,
this.zookeeperDiscoveryProperties);
} else {
allInstances = new ZookeeperServiceInstances(
this.serviceRegistry, this.zookeeperDependencies,
this.zookeeperDiscoveryProperties);
}
builder.up().withDetail("services", allInstances);
}
catch (Exception e) {

View File

@@ -27,7 +27,9 @@ import org.springframework.util.ReflectionUtils;
*
* @author Spencer Gibb
* @since 1.0.0
* @deprecated replaced by {@link org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistration} . Remove in Edgware
*/
@Deprecated
public class ZookeeperLifecycle extends AbstractDiscoveryLifecycle {
private static final Log log = LogFactory.getLog(ZookeeperLifecycle.class);
@@ -53,7 +55,8 @@ public class ZookeeperLifecycle extends AbstractDiscoveryLifecycle {
return;
}
try {
this.serviceDiscovery.getServiceDiscovery().start();
this.serviceDiscovery.getServiceDiscoveryRef().get().start();
this.serviceDiscovery.getServiceDiscoveryRef().get().registerService(this.serviceDiscovery.getServiceInstanceRef().get());
}
catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e);
@@ -68,8 +71,8 @@ public class ZookeeperLifecycle extends AbstractDiscoveryLifecycle {
return;
}
try {
this.serviceDiscovery.getServiceDiscovery().unregisterService(
this.serviceDiscovery.getServiceInstance());
this.serviceDiscovery.getServiceDiscoveryRef().get().unregisterService(
this.serviceDiscovery.getServiceInstanceRef().get());
}
catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e);

View File

@@ -37,6 +37,7 @@ import org.springframework.cloud.zookeeper.discovery.dependency.ConditionalOnDep
import org.springframework.cloud.zookeeper.discovery.dependency.ConditionalOnDependenciesPassed;
import org.springframework.cloud.zookeeper.discovery.dependency.DependenciesBasedLoadBalancer;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -61,7 +62,7 @@ public class ZookeeperRibbonClientConfiguration {
protected static final String DEFAULT_NAMESPACE = "ribbon";
@Autowired
private ZookeeperServiceDiscovery serviceDiscovery;
private ZookeeperServiceRegistry registry;
@Value("${ribbon.client.name}")
private String serviceId = "client";
@@ -73,7 +74,7 @@ public class ZookeeperRibbonClientConfiguration {
@ConditionalOnMissingBean
@ConditionalOnDependenciesPassed
public ServerList<?> ribbonServerListFromDependencies(IClientConfig config, ZookeeperDependencies zookeeperDependencies) {
ZookeeperServerList serverList = new ZookeeperServerList(this.serviceDiscovery.getServiceDiscovery());
ZookeeperServerList serverList = new ZookeeperServerList(this.registry.getServiceDiscoveryRef().get());
serverList.initFromDependencies(config, zookeeperDependencies);
log.debug(String.format("Server list for Ribbon's dependencies based load balancing is [%s]", serverList));
return serverList;
@@ -99,7 +100,7 @@ public class ZookeeperRibbonClientConfiguration {
@ConditionalOnMissingBean
@ConditionalOnDependenciesNotPassed
public ServerList<?> ribbonServerList(IClientConfig config) {
ZookeeperServerList serverList = new ZookeeperServerList(this.serviceDiscovery.getServiceDiscovery());
ZookeeperServerList serverList = new ZookeeperServerList(this.registry.getServiceDiscoveryRef().get());
serverList.initWithNiwsConfig(config);
log.debug(String.format("Server list for Ribbon's non-dependency based load balancing is [%s]", serverList));
return serverList;

View File

@@ -30,7 +30,10 @@ import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.UriSpec;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.cloud.zookeeper.compat.ServiceDiscoveryHolder;
import org.springframework.cloud.zookeeper.compat.ServiceInstanceHolder;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ReflectionUtils;
@@ -42,19 +45,19 @@ import org.springframework.util.StringUtils;
*
* @author Spencer Gibb
* @since 1.0.0
* @deprecated replaced by {@link org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry}
* and {@link org.springframework.cloud.zookeeper.serviceregistry.ZookeeperBuilderRegistration}. Remove in Edgware
*/
public class ZookeeperServiceDiscovery implements ApplicationContextAware {
@Deprecated
public class ZookeeperServiceDiscovery implements ZookeeperRegistration, ApplicationContextAware, ServiceDiscoveryHolder, ServiceInstanceHolder {
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
private CuratorFramework curator;
private ZookeeperDiscoveryProperties properties;
private InstanceSerializer<ZookeeperInstance> instanceSerializer;
private ApplicationContext context;
private AtomicBoolean built = new AtomicBoolean(false);
private AtomicInteger port = new AtomicInteger();
@@ -63,8 +66,10 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
private AtomicReference<ServiceDiscovery<ZookeeperInstance>> serviceDiscovery = new AtomicReference<>();
@Value("${spring.application.name:application}")
private String appName;
private ApplicationContext context;
private boolean register;
public ZookeeperServiceDiscovery(CuratorFramework curator,
ZookeeperDiscoveryProperties properties,
@@ -72,6 +77,8 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
this.curator = curator;
this.properties = properties;
this.instanceSerializer = instanceSerializer;
this.register = this.properties.isRegister();
}
public int getPort() {
@@ -82,17 +89,19 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
this.port.set(port);
}
public ServiceInstance<ZookeeperInstance> getServiceInstance() {
return this.serviceInstance.get();
}
public ServiceDiscovery<ZookeeperInstance> getServiceDiscovery() {
return this.serviceDiscovery.get();
/**
* Override the register property, useful when auto-register == false
* @param register
*/
public void setRegister(boolean register) {
this.register = register;
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(this.context.getEnvironment());
this.appName = resolver.getProperty("spring.application.name", "application");
}
/**
@@ -101,7 +110,7 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
*/
public void build() {
if (this.built.compareAndSet(false, true)) {
if (this.port.get() <= 0 && this.properties.isRegister()) {
if (this.port.get() <= 0 && this.register) {
throw new IllegalStateException("Cannot create instance whose port is not greater than 0");
}
String host = this.properties.getInstanceHost();
@@ -109,10 +118,14 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
throw new IllegalStateException("instanceHost must not be empty");
}
UriSpec uriSpec = new UriSpec(this.properties.getUriSpec());
if (this.properties.isRegister()) {
if (this.register) {
configureServiceInstance(this.serviceInstance, this.appName,
this.context, this.port, host, uriSpec);
}
if (this.serviceDiscovery.get() != null) {
configureServiceDiscovery(this.serviceDiscovery, this.curator, this.properties,
this.instanceSerializer, this.serviceInstance);
}
}
}
@@ -132,7 +145,7 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
* One can override this method to provide custom way of registering a service
* instance (e.g. when no payload is required).
*/
protected void configureServiceInstance(AtomicReference<ServiceInstance<ZookeeperInstance>> serviceInstance,
public void configureServiceInstance(AtomicReference<ServiceInstance<ZookeeperInstance>> serviceInstance,
String appName,
ApplicationContext context,
AtomicInteger port,
@@ -155,25 +168,35 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
/**
* One can override this method to provide custom way of registering {@link ServiceDiscovery}
*/
protected void configureServiceDiscovery(AtomicReference<ServiceDiscovery<ZookeeperInstance>> serviceDiscovery,
public void configureServiceDiscovery(AtomicReference<ServiceDiscovery<ZookeeperInstance>> serviceDiscovery,
CuratorFramework curator, ZookeeperDiscoveryProperties properties,
InstanceSerializer<ZookeeperInstance> instanceSerializer,
AtomicReference<ServiceInstance<ZookeeperInstance>> serviceInstance) {
// @formatter:off
serviceDiscovery.set(ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)
ServiceDiscoveryBuilder<ZookeeperInstance> builder = ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)
.client(curator)
.basePath(properties.getRoot())
.serializer(instanceSerializer)
.thisInstance(serviceInstance.get())
.build());
.serializer(instanceSerializer);
if (serviceInstance != null) {
builder.thisInstance(serviceInstance.get());
}
serviceDiscovery.set(builder.build());
// @formatter:on
}
protected AtomicReference<ServiceDiscovery<ZookeeperInstance>> getServiceDiscoveryRef() {
@Override
public ServiceInstance<ZookeeperInstance> getServiceInstance() {
build();
return this.serviceInstance.get();
}
public AtomicReference<ServiceDiscovery<ZookeeperInstance>> getServiceDiscoveryRef() {
return this.serviceDiscovery;
}
protected AtomicReference<ServiceInstance<ZookeeperInstance>> getServiceInstanceRef() {
public AtomicReference<ServiceInstance<ZookeeperInstance>> getServiceInstanceRef() {
return this.serviceInstance;
}
@@ -181,7 +204,7 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
return this.built;
}
protected CuratorFramework getCurator() {
public CuratorFramework getCurator() {
return this.curator;
}
}

View File

@@ -8,7 +8,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.zookeeper.compat.ServiceDiscoveryHolder;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.sanitize;
@@ -19,16 +21,19 @@ import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.
*
* @since 1.0.0
*/
public class ZookeeperServiceInstances implements Iterable<ServiceInstance<ZookeeperInstance>> {
public class ZookeeperServiceInstances
implements Iterable<ServiceInstance<ZookeeperInstance>> {
private static final Log log = LogFactory.getLog(ZookeeperServiceInstances.class);
private final ZookeeperServiceDiscovery serviceDiscovery;
private final ServiceDiscoveryHolder serviceDiscovery;
private final ZookeeperDependencies zookeeperDependencies;
private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;
private final List<ServiceInstance<ZookeeperInstance>> allInstances;
public ZookeeperServiceInstances(ZookeeperServiceDiscovery serviceDiscovery, ZookeeperDependencies zookeeperDependencies,
@Deprecated
public ZookeeperServiceInstances(ZookeeperServiceDiscovery serviceDiscovery,
ZookeeperDependencies zookeeperDependencies,
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
this.serviceDiscovery = serviceDiscovery;
this.zookeeperDependencies = zookeeperDependencies;
@@ -36,6 +41,15 @@ public class ZookeeperServiceInstances implements Iterable<ServiceInstance<Zooke
this.allInstances = getZookeeperInstances();
}
public ZookeeperServiceInstances(ZookeeperServiceRegistry serviceRegistry,
ZookeeperDependencies zookeeperDependencies,
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
this.serviceDiscovery = serviceRegistry;
this.zookeeperDependencies = zookeeperDependencies;
this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties;
this.allInstances = getZookeeperInstances();
}
private List<ServiceInstance<ZookeeperInstance>> getZookeeperInstances() {
ArrayList<ServiceInstance<ZookeeperInstance>> allInstances = new ArrayList<>();
try {
@@ -49,20 +63,24 @@ public class ZookeeperServiceInstances implements Iterable<ServiceInstance<Zooke
return allInstances;
}
catch (Exception e) {
log.debug("Exception occurred while trying to build the list of instances", e);
log.debug("Exception occurred while trying to build the list of instances",
e);
return allInstances;
}
}
private List<ServiceInstance<ZookeeperInstance>> nestedInstances(
List<ServiceInstance<ZookeeperInstance>> accumulator, String name) throws Exception {
List<ServiceInstance<ZookeeperInstance>> accumulator, String name)
throws Exception {
String parentPath = prepareQueryName(name);
Collection<ServiceInstance<ZookeeperInstance>> childrenInstances = tryToGetInstances(parentPath);
Collection<ServiceInstance<ZookeeperInstance>> childrenInstances = tryToGetInstances(
parentPath);
if (childrenInstances != null) {
return convertCollectionToList(childrenInstances);
}
try {
List<String> children = this.serviceDiscovery.getCurator().getChildren().forPath(parentPath);
List<String> children = this.serviceDiscovery.getCurator().getChildren()
.forPath(parentPath);
return iterateOverChildren(accumulator, parentPath, children);
} catch (Exception e) {
if (log.isTraceEnabled()) {
@@ -77,11 +95,15 @@ public class ZookeeperServiceInstances implements Iterable<ServiceInstance<Zooke
return name.startsWith(root) ? name : root + name;
}
private Collection<ServiceInstance<ZookeeperInstance>> tryToGetInstances(String path) {
private Collection<ServiceInstance<ZookeeperInstance>> tryToGetInstances(
String path) {
try {
return this.serviceDiscovery.getServiceDiscovery().queryForInstances(getPathWithoutRoot(path));
} catch (Exception e) {
log.trace("Exception occurred while trying to retrieve instances of [" + path + "]", e);
return this.serviceDiscovery.getServiceDiscoveryRef().get()
.queryForInstances(getPathWithoutRoot(path));
}
catch (Exception e) {
log.trace("Exception occurred while trying to retrieve instances of [" + path
+ "]", e);
return null;
}
}
@@ -91,9 +113,10 @@ public class ZookeeperServiceInstances implements Iterable<ServiceInstance<Zooke
}
private List<ServiceInstance<ZookeeperInstance>> injectZookeeperServiceInstances(
List<ServiceInstance<ZookeeperInstance>> accumulator, String name) throws Exception {
List<ServiceInstance<ZookeeperInstance>> accumulator, String name)
throws Exception {
Collection<ServiceInstance<ZookeeperInstance>> instances = this.serviceDiscovery
.getServiceDiscovery().queryForInstances(name);
.getServiceDiscoveryRef().get().queryForInstances(name);
accumulator.addAll(convertCollectionToList(instances));
return accumulator;
}
@@ -108,8 +131,8 @@ public class ZookeeperServiceInstances implements Iterable<ServiceInstance<Zooke
}
private List<ServiceInstance<ZookeeperInstance>> iterateOverChildren(
List<ServiceInstance<ZookeeperInstance>> accumulator,
String parentPath, List<String> children) throws Exception {
List<ServiceInstance<ZookeeperInstance>> accumulator, String parentPath,
List<String> children) throws Exception {
List<ServiceInstance<ZookeeperInstance>> lists = new ArrayList<>();
for (String child : children) {
lists.addAll(nestedInstances(accumulator, parentPath + "/" + child));
@@ -123,7 +146,8 @@ public class ZookeeperServiceInstances implements Iterable<ServiceInstance<Zooke
log.debug("Using direct name resolution instead of dependency based one");
}
List<String> names = new ArrayList<>();
for (String name : this.serviceDiscovery.getServiceDiscovery().queryForNames()) {
for (String name : this.serviceDiscovery.getServiceDiscoveryRef().get()
.queryForNames()) {
names.add(sanitize(name));
}
return names;

View File

@@ -22,10 +22,12 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.curator.x.discovery.ServiceCache;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.cloud.zookeeper.compat.ServiceDiscoveryHolder;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependency;
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import org.springframework.context.ApplicationListener;
import org.springframework.util.ReflectionUtils;
@@ -42,12 +44,13 @@ import org.springframework.util.ReflectionUtils;
*/
public class DefaultDependencyWatcher implements DependencyRegistrationHookProvider, ApplicationListener<InstanceRegisteredEvent<?>> {
private final ZookeeperServiceDiscovery serviceDiscovery;
private final ServiceDiscoveryHolder serviceDiscovery;
private final Map<String, ServiceCache<?>> dependencyRegistry = new ConcurrentHashMap<>();
private final List<DependencyWatcherListener> listeners;
private final DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier;
private final ZookeeperDependencies zookeeperDependencies;
@Deprecated
public DefaultDependencyWatcher(ZookeeperServiceDiscovery serviceDiscovery,
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
List<DependencyWatcherListener> dependencyWatcherListeners,
@@ -58,6 +61,16 @@ public class DefaultDependencyWatcher implements DependencyRegistrationHookProvi
this.zookeeperDependencies = zookeeperDependencies;
}
public DefaultDependencyWatcher(ZookeeperServiceRegistry registry,
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
List<DependencyWatcherListener> dependencyWatcherListeners,
ZookeeperDependencies zookeeperDependencies) {
this.serviceDiscovery = registry;
this.dependencyPresenceOnStartupVerifier = dependencyPresenceOnStartupVerifier;
this.listeners = dependencyWatcherListeners;
this.zookeeperDependencies = zookeeperDependencies;
}
@Override
public void onApplicationEvent(InstanceRegisteredEvent<?> event) {
registerDependencyRegistrationHooks();
@@ -67,7 +80,7 @@ public class DefaultDependencyWatcher implements DependencyRegistrationHookProvi
public void registerDependencyRegistrationHooks() {
for (ZookeeperDependency zookeeperDependency : this.zookeeperDependencies.getDependencyConfigurations()) {
String dependencyPath = zookeeperDependency.getPath();
ServiceCache<?> serviceCache = this.serviceDiscovery.getServiceDiscovery()
ServiceCache<?> serviceCache = this.serviceDiscovery.getServiceDiscoveryRef().get()
.serviceCacheBuilder().name(dependencyPath).build();
try {
serviceCache.start();

View File

@@ -15,8 +15,12 @@
*/
package org.springframework.cloud.zookeeper.discovery.watcher;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery;
@@ -25,12 +29,10 @@ import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDepende
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration;
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier;
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* Provides hooks for observing dependency lifecycle in Zookeeper.
* Needs custom dependencies to be set in order to work.
@@ -56,8 +58,9 @@ public class DependencyWatcherAutoConfiguration {
}
@Bean(destroyMethod = "clearDependencyRegistrationHooks")
@ConditionalOnBean(ZookeeperServiceDiscovery.class)
@ConditionalOnMissingBean
public DependencyRegistrationHookProvider dependencyWatcher(
public DependencyRegistrationHookProvider dependencyWatcherDeprecated(
ZookeeperServiceDiscovery serviceDiscovery,
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
ZookeeperDependencies zookeeperDependencies) {
@@ -66,4 +69,16 @@ public class DependencyWatcherAutoConfiguration {
this.dependencyWatcherListeners,
zookeeperDependencies);
}
@Bean(destroyMethod = "clearDependencyRegistrationHooks")
@ConditionalOnMissingBean({ DependencyRegistrationHookProvider.class, ZookeeperServiceDiscovery.class })
public DependencyRegistrationHookProvider dependencyWatcher(
ZookeeperServiceRegistry serviceDiscovery,
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
ZookeeperDependencies zookeeperDependencies) {
return new DefaultDependencyWatcher(serviceDiscovery,
dependencyPresenceOnStartupVerifier,
this.dependencyWatcherListeners,
zookeeperDependencies);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
/**
* Zookeeper {@link org.springframework.cloud.client.discovery.DiscoveryLifecycle}
* that uses {@link org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery} to register and de-register instances.
*
* @author Spencer Gibb
* @since 1.0.0
*/
public class ZookeeperAutoServiceRegistration extends AbstractAutoServiceRegistration<ZookeeperRegistration> {
private static final Log log = LogFactory.getLog(ZookeeperAutoServiceRegistration.class);
private ZookeeperRegistration registration;
private ZookeeperDiscoveryProperties properties;
public ZookeeperAutoServiceRegistration(ZookeeperServiceRegistry registry,
ZookeeperRegistration registration,
ZookeeperDiscoveryProperties properties) {
super(registry);
this.registration = registration;
this.properties = properties;
if (this.properties.getInstancePort() != null) {
this.registration.setPort(this.properties.getInstancePort());
}
}
@Override
protected ZookeeperRegistration getRegistration() {
return this.registration;
}
@Override
protected ZookeeperRegistration getManagementRegistration() {
return null;
}
@Override
protected void register() {
if (!this.properties.isRegister()) {
log.debug("Registration disabled.");
return;
}
super.register();
}
@Override
protected void deregister() {
if (!this.properties.isRegister()) {
return;
}
super.deregister();
}
@Override
protected boolean isEnabled() {
return this.properties.isEnabled();
}
@Override
protected int getConfiguredPort() {
return this.registration.getPort();
}
@Override
protected void setConfiguredPort(int port) {
this.registration.setPort(port);
}
@Override
protected Object getConfiguration() {
return this.properties;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
/**
* @author Spencer Gibb
*/
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryAutoConfiguration;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.cloud.zookeeper.discovery.ZookeeperLifecycle")
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter(ZookeeperServiceRegistryAutoConfiguration.class)
@AutoConfigureBefore( {AutoServiceRegistrationAutoConfiguration.class, ZookeeperDiscoveryAutoConfiguration.class} )
public class ZookeeperAutoServiceRegistrationAutoConfiguration {
@Bean
public ZookeeperAutoServiceRegistration zookeeperAutoServiceRegistration(ZookeeperServiceRegistry registry, ZookeeperRegistration registration,
ZookeeperDiscoveryProperties properties) {
return new ZookeeperAutoServiceRegistration(registry, registration, properties);
}
@Bean
@ConditionalOnMissingBean
public ZookeeperServiceDiscovery zookeeperServiceDiscovery(CuratorFramework curator, ZookeeperDiscoveryProperties zookeeperDiscoveryProperties, InstanceSerializer<ZookeeperInstance> instanceSerializer) {
return new ZookeeperServiceDiscovery(curator, zookeeperDiscoveryProperties,
instanceSerializer);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceInstanceBuilder;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
/**
* @author Spencer Gibb
*/
public class ZookeeperBuilderRegistration implements ZookeeperRegistration {
protected ServiceInstance<ZookeeperInstance> serviceInstance;
protected ServiceInstanceBuilder<ZookeeperInstance> builder;
public ZookeeperBuilderRegistration(ServiceInstanceBuilder<ZookeeperInstance> builder) {
this.builder = builder;
}
public ServiceInstance<ZookeeperInstance> getServiceInstance() {
if (this.serviceInstance == null) {
build();
}
return this.serviceInstance;
}
protected void build() {
this.serviceInstance = this.builder.build();
}
public int getPort() {
return this.serviceInstance.getPort();
}
public void setPort(int port) {
this.builder.port(port);
this.build();
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
/**
* @author Spencer Gibb
*/
public interface ZookeeperRegistration extends Registration {
ServiceInstance<ZookeeperInstance> getServiceInstance();
int getPort();
void setPort(int port);
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.cloud.zookeeper.compat.ServiceDiscoveryHolder;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
* @author Spencer Gibb
*/
public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegistration>, SmartInitializingSingleton,
Closeable, ServiceDiscoveryHolder {
private ZookeeperServiceDiscovery serviceDiscovery;
private AtomicBoolean started = new AtomicBoolean();
protected CuratorFramework curator;
protected ZookeeperDiscoveryProperties properties;
protected InstanceSerializer<ZookeeperInstance> instanceSerializer;
@Deprecated
public ZookeeperServiceRegistry(ZookeeperServiceDiscovery serviceDiscovery, CuratorFramework curator,
ZookeeperDiscoveryProperties properties, InstanceSerializer<ZookeeperInstance> instanceSerializer) {
this.serviceDiscovery = serviceDiscovery;
this.curator = curator;
this.properties = properties;
this.instanceSerializer = instanceSerializer;
configureServiceDiscovery();
}
public ZookeeperServiceRegistry(CuratorFramework curator,
ZookeeperDiscoveryProperties properties, InstanceSerializer<ZookeeperInstance> instanceSerializer) {
this.curator = curator;
this.properties = properties;
this.instanceSerializer = instanceSerializer;
this.serviceDiscovery = new ZookeeperServiceDiscovery(curator, properties, instanceSerializer);
this.serviceDiscovery.setRegister(false);
configureServiceDiscovery();
}
/**
* TODO: add when ZookeeperServiceDiscovery is removed
* One can override this method to provide custom way of registering {@link ServiceDiscovery}
*/
protected void configureServiceDiscovery() {
// @formatter:off
/*this.serviceDiscovery = ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)
.client(this.curator)
.basePath(this.properties.getRoot())
.serializer(this.instanceSerializer)
.build();
// @formatter:on*/
this.serviceDiscovery.configureServiceDiscovery(this.serviceDiscovery.getServiceDiscoveryRef(),
this.curator, this.properties, this.instanceSerializer, this.serviceDiscovery.getServiceInstanceRef());
}
@Override
public void register(ZookeeperRegistration registration) {
try {
this.serviceDiscovery.getServiceDiscoveryRef().get().registerService(registration.getServiceInstance());
} catch (Exception e) {
rethrowRuntimeException(e);
}
}
@Override
public void deregister(ZookeeperRegistration registration) {
try {
this.serviceDiscovery.getServiceDiscoveryRef().get().unregisterService(registration.getServiceInstance());
} catch (Exception e) {
rethrowRuntimeException(e);
}
}
@Override
public void afterSingletonsInstantiated() {
try {
this.serviceDiscovery.getServiceDiscoveryRef().get().start();
} catch (Exception e) {
rethrowRuntimeException(e);
}
}
@Override
public void close() {
try {
this.serviceDiscovery.getServiceDiscoveryRef().get().close();
} catch (IOException e) {
rethrowRuntimeException(e);
}
}
@Override
public void setStatus(ZookeeperRegistration registration, String status) {
//TODO:
}
@Override
public Object getStatus(ZookeeperRegistration registration) {
//TODO:
return null;
}
/**
* @deprecated for backwards compatibility. Visibility will be tightened when ZookeeperServiceDiscovery is removed.
*/
@Deprecated
public CuratorFramework getCurator() {
return this.curator;
}
/**
* @deprecated for backwards compatibility. Visibility will be tightened when ZookeeperServiceDiscovery is removed.
*/
@Deprecated
public AtomicReference<ServiceDiscovery<ZookeeperInstance>> getServiceDiscoveryRef() {
return this.serviceDiscovery.getServiceDiscoveryRef();
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Spencer Gibb
*/
@Configuration
@ConditionalOnProperty(value = "spring.cloud.service-registry.enabled", matchIfMissing = true)
public class ZookeeperServiceRegistryAutoConfiguration implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
@Bean
public ZookeeperServiceRegistry zookeeperServiceRegistry(
ZookeeperDiscoveryProperties properties, CuratorFramework curator,
InstanceSerializer<ZookeeperInstance> instanceSerializer) {
try {
ZookeeperServiceDiscovery serviceDiscovery = this.context.getBean(ZookeeperServiceDiscovery.class);
return new ZookeeperServiceRegistry(serviceDiscovery, curator, properties,
instanceSerializer);
} catch (NoSuchBeanDefinitionException e) {
}
// for when auto-registration == false
return new ZookeeperServiceRegistry(curator, properties, instanceSerializer);
}
@Bean
@ConditionalOnMissingBean
public InstanceSerializer<ZookeeperInstance> instanceSerializer() {
return new JsonInstanceSerializer<>(ZookeeperInstance.class);
}
@Bean
@ConditionalOnMissingBean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(InetUtils inetUtils) {
return new ZookeeperDiscoveryProperties(inetUtils);
}
}

View File

@@ -1,11 +1,14 @@
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.zookeeper.discovery.dependency.DependencyRibbonAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.RibbonZookeeperAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.dependency.DependencyFeignClientAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.dependency.DependencyRibbonAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.dependency.DependencyRestTemplateAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.dependency.DependencyFeignClientAutoConfiguration,\
org.springframework.cloud.zookeeper.discovery.dependency.DependencyRestTemplateAutoConfiguration
org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistrationAutoConfiguration,\
org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistryAutoConfiguration
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\

View File

@@ -3,12 +3,18 @@ package org.springframework.cloud.zookeeper.discovery;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.UriSpec;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.context.ApplicationContext;
public class CustomZookeeperServiceDiscovery extends ZookeeperServiceDiscovery {
@@ -16,10 +22,9 @@ public class CustomZookeeperServiceDiscovery extends ZookeeperServiceDiscovery {
private final String basePath;
public CustomZookeeperServiceDiscovery(String applicationName, String basePath, CuratorFramework curator) {
super(curator, null, null);
super(curator, new ZookeeperDiscoveryProperties(new InetUtils(new InetUtilsProperties())), null);
this.applicationName = applicationName;
this.basePath = basePath;
build();
}
public CustomZookeeperServiceDiscovery(String applicationName, CuratorFramework curator) {
@@ -27,28 +32,31 @@ public class CustomZookeeperServiceDiscovery extends ZookeeperServiceDiscovery {
}
@Override
public void build(){
public void configureServiceInstance(AtomicReference<ServiceInstance<ZookeeperInstance>> serviceInstance, String appName, ApplicationContext context, AtomicInteger port, String host, UriSpec uriSpec) {
setPort(10);
try {
setPort(10);
ServiceInstance instance = ServiceInstance.builder().uriSpec(new UriSpec("{scheme}://{address}:{port}/"))
.address("anyUrl")
.port(10)
.name(this.applicationName)
.build();
getServiceInstanceRef().set(instance);
ServiceDiscovery discovery = ServiceDiscoveryBuilder
.builder(Void.class)
.basePath(this.basePath)
.client(getCurator())
.thisInstance(instance)
.build();
getServiceDiscoveryRef().set(discovery);
discovery.start();
serviceInstance.set(instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void configureServiceDiscovery(AtomicReference<ServiceDiscovery<ZookeeperInstance>> serviceDiscovery, CuratorFramework curator, ZookeeperDiscoveryProperties properties, InstanceSerializer<ZookeeperInstance> instanceSerializer, AtomicReference<ServiceInstance<ZookeeperInstance>> serviceInstance) {
ServiceDiscovery discovery = ServiceDiscoveryBuilder
.builder(ZookeeperInstance.class)
.basePath(this.basePath)
.client(getCurator())
//.thisInstance(serviceInstance.get())
.build();
serviceDiscovery.set(discovery);
}
@PreDestroy
void close() {
try {
@@ -58,4 +66,4 @@ public class CustomZookeeperServiceDiscovery extends ZookeeperServiceDiscovery {
throw new RuntimeException(e);
}
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.zookeeper.discovery;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Spencer Gibb
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryAutoRegistrationFalseTests.Config.class,
properties = { "spring.application.name=testzkautoregfalse", "debug=true" },
webEnvironment = RANDOM_PORT)
@DirtiesContext
public class ZookeeperDiscoveryAutoRegistrationFalseTests {
@Autowired DiscoveryClient discoveryClient;
@Value("${spring.application.name}") String springAppName;
@Test public void discovery_client_is_zookeeper() {
//given: this.discoveryClient
//expect:
then(discoveryClient).isInstanceOf(ZookeeperDiscoveryClient.class);
}
@Test public void application_should_not_have_been_registered() {
//given:
List<ServiceInstance> instances = this.discoveryClient.getInstances(springAppName);
//expect:
then(instances).isEmpty();
}
@Test public void should_not_find_local_instance() {
//given
ServiceInstance serviceInstance = this.discoveryClient.getLocalServiceInstance();
//expect:
then(serviceInstance).isNull();
}
@Configuration
@EnableAutoConfiguration
@Import(CommonTestConfig.class)
@EnableDiscoveryClient(autoRegister = false)
static class Config {
}
@Controller
@Profile("ribbon")
class PingController {
@RequestMapping("/ping") String ping() {
return "pong";
}
}
}

View File

@@ -8,6 +8,9 @@ import javax.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceInstanceBuilder;
import org.apache.curator.x.discovery.UriSpec;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,6 +21,9 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperBuilderRegistration;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -26,7 +32,6 @@ import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import static com.toomuchcoding.jsonassert.JsonAssertion.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
/**
@@ -61,21 +66,30 @@ public class ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests {
@Profile("nestedstructure")
static class Config {
@Autowired CuratorFramework curatorFramework;
CustomZookeeperServiceDiscovery customZookeeperServiceDiscovery;
@Autowired
ZookeeperServiceRegistry serviceRegistry;
private ZookeeperRegistration registration;
@PostConstruct
void registerNestedDependency() {
this.customZookeeperServiceDiscovery = new CustomZookeeperServiceDiscovery("/a/b/c/d/anotherservice",
"/services", this.curatorFramework);
this.customZookeeperServiceDiscovery.build();
try {
ServiceInstanceBuilder<ZookeeperInstance> builder = ServiceInstance.<ZookeeperInstance>builder()
.uriSpec(new UriSpec("{scheme}://{address}:{port}/"))
.address("anyUrl")
.port(10)
.name("/a/b/c/d/anotherservice");
this.registration = new ZookeeperBuilderRegistration(builder);
this.serviceRegistry.register(registration);
} catch (Exception e) {
throw new RuntimeException(e);
}
//this.customZookeeperServiceDiscovery = new CustomZookeeperServiceDiscovery(,
// "/services", this.curatorFramework);
}
@PreDestroy
void unregisterServiceDiscovery() {
if (this.customZookeeperServiceDiscovery != null) {
this.customZookeeperServiceDiscovery.close();
}
this.serviceRegistry.deregister(this.registration);
}
@Bean TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate,

View File

@@ -15,6 +15,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.cloud.zookeeper.compat.ServiceInstanceHolder;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient;
import org.springframework.context.annotation.Bean;
@@ -32,6 +33,7 @@ import com.jayway.awaitility.Awaitility;
import com.toomuchcoding.jsonassert.JsonPath;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Marcin Grzejszczak
@@ -39,13 +41,13 @@ import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryTests.Config.class,
properties = "feign.hystrix.enabled=false",
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
webEnvironment = RANDOM_PORT)
@ActiveProfiles("ribbon")
public class ZookeeperDiscoveryTests {
@Autowired TestRibbonClient testRibbonClient;
@Autowired DiscoveryClient discoveryClient;
@Autowired ZookeeperServiceDiscovery serviceDiscovery;
@Autowired ServiceInstanceHolder serviceDiscovery;
@Value("${spring.application.name}") String springAppName;
@Autowired IdUsingFeignClient idUsingFeignClient;
@@ -91,7 +93,7 @@ public class ZookeeperDiscoveryTests {
@Test public void should_properly_find_local_instance() {
//expect:
then(this.serviceDiscovery.getServiceInstance().getAddress()).isEqualTo(this.discoveryClient.getLocalServiceInstance().getHost());
then(this.serviceDiscovery.getServiceInstanceRef().get().getAddress()).isEqualTo(this.discoveryClient.getLocalServiceInstance().getHost());
}

View File

@@ -0,0 +1,134 @@
/*
* 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.zookeeper.discovery;
import java.util.List;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.zookeeper.compat.ServiceInstanceHolder;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import com.toomuchcoding.jsonassert.JsonPath;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* Test for backwards compatibility
* @author Marcin Grzejszczak
* @author Spencer Gibb
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryWithZookeeperLifecycleTests.Config.class,
properties = "spring.application.name=testzkwithzookeeperlifecycle",
webEnvironment = RANDOM_PORT)
@ActiveProfiles("ribbon")
public class ZookeeperDiscoveryWithZookeeperLifecycleTests {
@Autowired TestRibbonClient testRibbonClient;
@Autowired DiscoveryClient discoveryClient;
@Autowired ServiceInstanceHolder serviceDiscovery;
@Value("${spring.application.name}") String springAppName;
@Test public void should_find_the_app_by_its_name_via_Ribbon() {
//expect:
then(registeredServiceStatusViaServiceName()).isEqualTo("UP");
}
@Test public void should_find_a_collaborator_via_discovery_client() {
//given:
List<ServiceInstance> instances = this.discoveryClient.getInstances(this.springAppName);
ServiceInstance instance = instances.get(0);
//expect:
then(registeredServiceStatus(instance)).isEqualTo("UP");
then(instance.getMetadata().get("testMetadataKey")).isEqualTo("testMetadataValue");
}
@Test public void should_present_application_name_as_id_of_the_service_instance() {
//given:
ServiceInstance instance = this.discoveryClient.getLocalServiceInstance();
//expect:
then(this.springAppName).isEqualTo(instance.getServiceId());
}
private String registeredServiceStatusViaServiceName() {
return JsonPath.builder(this.testRibbonClient.thisHealthCheck()).field("status").read(String.class);
}
private String registeredServiceStatus(ServiceInstance instance) {
return JsonPath.builder(this.testRibbonClient.callOnUrl(instance.getHost()+":"+instance.getPort(), "health")).field("status").read(String.class);
}
@Test public void should_properly_find_local_instance() {
//expect:
then(this.serviceDiscovery.getServiceInstanceRef().get().getAddress()).isEqualTo(this.discoveryClient.getLocalServiceInstance().getHost());
}
@Configuration
@EnableAutoConfiguration
@Import(CommonTestConfig.class)
@EnableDiscoveryClient
@Profile("ribbon")
static class Config {
@Bean
public ZookeeperServiceDiscovery zookeeperServiceDiscovery(ZookeeperDiscoveryProperties properties, CuratorFramework curator,
InstanceSerializer<ZookeeperInstance> instanceSerializer) {
return new ZookeeperServiceDiscovery(curator, properties, instanceSerializer);
}
@Bean
public ZookeeperLifecycle zookeeperLifecycle(ZookeeperDiscoveryProperties properties,
ZookeeperServiceDiscovery serviceDiscovery) {
return new ZookeeperLifecycle(properties, serviceDiscovery);
}
@Bean TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate,
@Value("${spring.application.name}") String springAppName) {
return new TestRibbonClient(restTemplate, springAppName);
}
}
@Controller
@Profile("ribbon")
class PingController {
@RequestMapping("/ping") String ping() {
return "pong";
}
}
}

View File

@@ -24,8 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
@@ -55,10 +57,7 @@ public class ZookeeperLifecycleRegistrationDisabledTests {
@Configuration
@EnableAutoConfiguration
@Import({ CommonTestConfig.class, ZookeeperAutoConfiguration.class, ZookeeperDiscoveryClientConfiguration.class })
static class TestPropsConfig {
}
@EnableDiscoveryClient
@Import({ CommonTestConfig.class })
static class TestPropsConfig { }
}

View File

@@ -1,4 +1,20 @@
package org.springframework.cloud.zookeeper.discovery.issues.issue91;
/*
* 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.zookeeper.discovery;
import org.apache.curator.test.TestingServer;
import org.junit.After;
@@ -25,9 +41,10 @@ import com.jayway.awaitility.Awaitility;
import static org.assertj.core.api.BDDAssertions.then;
/**
* Test for gh-91, using s-c-zookeeper in a non-web app.
* @author Marcin Grzejszczak
*/
public class Issue91Tests {
public class ZookeeprDiscoveryNonWebAppTests {
TestingServer server;
String connectionString;
@@ -71,31 +88,34 @@ public class Issue91Tests {
}
}
}
}
@EnableAutoConfiguration(exclude = {EndpointMBeanExportAutoConfiguration.class,
JmxAutoConfiguration.class})
@EnableDiscoveryClient
@Configuration
class HelloClient {
@LoadBalanced @Bean RestTemplate restTemplate() {
return new RestTemplate();
@EnableAutoConfiguration(exclude = {EndpointMBeanExportAutoConfiguration.class,
JmxAutoConfiguration.class})
@EnableDiscoveryClient
@Configuration
static class HelloClient {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
DiscoveryClient discoveryClient;
@Autowired RestTemplate restTemplate;
}
@Autowired DiscoveryClient discoveryClient;
@EnableAutoConfiguration(exclude = {EndpointMBeanExportAutoConfiguration.class,
JmxAutoConfiguration.class})
@EnableDiscoveryClient
@RestController
static class HelloProducer {
@Autowired RestTemplate restTemplate;
}
@RequestMapping("/")
public String foo() {
return "foo";
}
@EnableAutoConfiguration(exclude = {EndpointMBeanExportAutoConfiguration.class,
JmxAutoConfiguration.class})
@EnableDiscoveryClient
@RestController
class HelloProducer {
@RequestMapping("/")
public String foo() {
return "foo";
}
}
}

View File

@@ -12,13 +12,17 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.zookeeper.discovery.CustomZookeeperServiceDiscovery;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperLifecycle;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery;
import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
import org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.ActiveProfiles;
@@ -29,12 +33,13 @@ import org.springframework.web.client.RestTemplate;
import com.jayway.awaitility.Awaitility;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Marcin Grzejszczak
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DefaultDependencyWatcherSpringTests.Config.class)
@SpringBootTest(classes = DefaultDependencyWatcherSpringTests.Config.class, webEnvironment = RANDOM_PORT)
@ActiveProfiles("watcher")
public class DefaultDependencyWatcherSpringTests {
@@ -42,6 +47,7 @@ public class DefaultDependencyWatcherSpringTests {
@Autowired AssertableDependencyWatcherListener dependencyWatcherListener;
@Autowired ZookeeperServiceDiscovery serviceDiscovery;
@Test public void should_verify_that_presence_of_a_dependency_has_been_checked() {
then(this.dependencyPresenceOnStartupVerifier.startupPresenceVerified).isTrue();
}
@@ -49,7 +55,7 @@ public class DefaultDependencyWatcherSpringTests {
@Test public void should_verify_that_dependency_watcher_listener_is_successfully_registered_and_operational()
throws Exception {
//when:
this.serviceDiscovery.getServiceDiscovery().unregisterService(this.serviceDiscovery.getServiceInstance());
this.serviceDiscovery.getServiceDiscoveryRef().get().unregisterService(this.serviceDiscovery.getServiceInstanceRef().get());
//then:
Awaitility.await().until(new Callable<Boolean>() {
@@ -61,9 +67,14 @@ public class DefaultDependencyWatcherSpringTests {
}
@Configuration
@EnableDiscoveryClient
@EnableAutoConfiguration
@Profile("watcher")
static class Config {
@Bean
public ZookeeperLifecycle zookeeperLifecycle(ZookeeperDiscoveryProperties properties, ZookeeperServiceDiscovery serviceDiscovery) {
return new ZookeeperLifecycle(properties, serviceDiscovery);
}
@Bean
@LoadBalanced RestTemplate loadBalancedRestTemplate() {
@@ -79,6 +90,7 @@ public class DefaultDependencyWatcherSpringTests {
return new TestingServer(SocketUtils.findAvailableTcpPort());
}
@Primary
@Bean ZookeeperServiceDiscovery zookeeperServiceDiscovery() throws Exception {
return new MyZookeeperServiceDiscovery(curatorFramework());
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2013-2016 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.zookeeper.serviceregistry;
import java.util.Collection;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Spencer Gibb
*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = { "spring.application.name=myTestService1-F" },
webEnvironment = RANDOM_PORT)
public class ZookeeperAutoServiceRegistrationTests {
@Autowired
private ZookeeperRegistration registration;
@Autowired
private ZookeeperServiceRegistry registry;
@Autowired
private ZookeeperDiscoveryProperties properties;
@Test
public void contextLoads() throws Exception {
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = registry.getServiceDiscoveryRef().get();
Collection<ServiceInstance<ZookeeperInstance>> instances = serviceDiscovery.queryForInstances("myTestService1-F");
assertThat(instances).hasSize(1);
ServiceInstance<ZookeeperInstance> instance = instances.iterator().next();
assertThat(instance).isNotNull();
assertThat(instance.getName()).isEqualTo("myTestService1-F");
/*Response<Map<String, Service>> response = consul.getAgentServices();
Map<String, Service> services = response.getValue();
Service service = services.get(registration.getServiceId());
assertNotNull("service was null", service);
assertNotEquals("service port is 0", 0, service.getPort().intValue());
assertFalse("service id contained invalid character: " + service.getId(), service.getId().contains(":"));
assertEquals("service id was wrong", registration.getServiceId(), service.getId());
assertEquals("service name was wrong", "myTestService1-FF-something", service.getService());
assertFalse("service address must not be empty", StringUtils.isEmpty(service.getAddress()));
assertEquals("service address must equals hostname from discovery properties", discoveryProperties.getHostname(), service.getAddress());*/
}
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableDiscoveryClient
@Import({CommonTestConfig.class})
/*@ImportAutoConfiguration({AutoServiceRegistrationAutoConfiguration.class, ZookeeperAutoServiceRegistration.class,
ZookeeperServiceRegistryAutoConfiguration.class})*/
protected static class TestConfig { }
}

View File

@@ -1,2 +1,5 @@
spring.cloud.zookeeper.dependency.enabled: false
spring.application.name: me
management:
security:
enabled: false

View File

@@ -2,4 +2,5 @@
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.cloud.zookeeper" level="DEBUG"/>
</configuration>
<logger name="org.apache.zookeeper" level="WARN"/>
</configuration>