Extracted heartbeat and catalog watch auto-configuration. (#574)

* Extracted heartbeat and catalog watch auto-configuration.
Needed in order to have those beans running in the correct application context when SC Config discovery is enabled.

* Moved heartbeat config to support package
This commit is contained in:
Tim Ysewyn
2019-07-23 21:10:18 +02:00
committed by GitHub
parent b1ab6cdfc2
commit 8d74a85e79
7 changed files with 231 additions and 108 deletions

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2013-2019 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.consul.discovery;
import com.ecwid.consul.v1.ConsulClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.consul.ConditionalOnConsulEnabled;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* Auto configuration for the catalog watcher.
*
* @author Tim Ysewyn
*/
@Configuration
@ConditionalOnConsulEnabled
@ConditionalOnProperty(value = "spring.cloud.consul.discovery.catalog-services-watch.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@AutoConfigureAfter({ ConsulDiscoveryClientConfiguration.class })
public class ConsulCatalogWatchAutoConfiguration {
/**
* Name of the catalog watch task scheduler bean.
*/
public static final String CATALOG_WATCH_TASK_SCHEDULER_NAME = "catalogWatchTaskScheduler";
@Bean
@ConditionalOnMissingBean
public ConsulCatalogWatch consulCatalogWatch(
ConsulDiscoveryProperties discoveryProperties, ConsulClient consulClient,
@Qualifier(CATALOG_WATCH_TASK_SCHEDULER_NAME) TaskScheduler taskScheduler) {
return new ConsulCatalogWatch(discoveryProperties, consulClient, taskScheduler);
}
@Bean(name = CATALOG_WATCH_TASK_SCHEDULER_NAME)
public TaskScheduler catalogWatchTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
}

View File

@@ -18,8 +18,6 @@ package org.springframework.cloud.consul.discovery;
import com.ecwid.consul.v1.ConsulClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -31,12 +29,11 @@ import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.consul.ConditionalOnConsulEnabled;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @author Spencer Gibb
* @author Olga Maciaszek-Sharma
* @author Tim Ysewyn
*/
@Configuration
@ConditionalOnConsulEnabled
@@ -47,49 +44,24 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
CommonsClientAutoConfiguration.class })
public class ConsulDiscoveryClientConfiguration {
public static final String CATALOG_WATCH_TASK_SCHEDULER_NAME = "catalogWatchTaskScheduler";
@Autowired
private ConsulClient consulClient;
/**
* Name of the catalog watch task scheduler bean.
* @Deprecated Moved to {@link ConsulCatalogWatchAutoConfiguration}.
*/
@Deprecated
public static final String CATALOG_WATCH_TASK_SCHEDULER_NAME = ConsulCatalogWatchAutoConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME;
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty("spring.cloud.consul.discovery.heartbeat.enabled")
//TODO: move to service-registry for Edgware
public TtlScheduler ttlScheduler(HeartbeatProperties heartbeatProperties) {
return new TtlScheduler(heartbeatProperties, consulClient);
}
@Bean
//TODO: move to service-registry for Edgware
public HeartbeatProperties heartbeatProperties() {
return new HeartbeatProperties();
}
@Bean
//TODO: Split appropriate values to service-registry for Edgware
public ConsulDiscoveryProperties consulDiscoveryProperties(InetUtils inetUtils) {
return new ConsulDiscoveryProperties(inetUtils);
}
@Bean
@ConditionalOnMissingBean
public ConsulDiscoveryClient consulDiscoveryClient(ConsulDiscoveryProperties discoveryProperties) {
public ConsulDiscoveryClient consulDiscoveryClient(ConsulClient consulClient,
ConsulDiscoveryProperties discoveryProperties) {
return new ConsulDiscoveryClient(consulClient, discoveryProperties);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "spring.cloud.consul.discovery.catalog-services-watch.enabled", matchIfMissing = true)
public ConsulCatalogWatch consulCatalogWatch(
ConsulDiscoveryProperties discoveryProperties,
@Qualifier(CATALOG_WATCH_TASK_SCHEDULER_NAME) TaskScheduler taskScheduler) {
return new ConsulCatalogWatch(discoveryProperties, consulClient, taskScheduler);
}
@Bean(name = CATALOG_WATCH_TASK_SCHEDULER_NAME)
@ConditionalOnProperty(name = "spring.cloud.consul.discovery.catalog-services-watch.enabled", matchIfMissing = true)
public TaskScheduler catalogWatchTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.
@@ -16,6 +16,8 @@
package org.springframework.cloud.consul.serviceregistry;
import com.ecwid.consul.v1.ConsulClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -29,10 +31,9 @@ import org.springframework.cloud.consul.discovery.TtlScheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ecwid.consul.v1.ConsulClient;
/**
* @author Spencer Gibb
* @author Tim Ysewyn
*/
@Configuration
@ConditionalOnConsulEnabled
@@ -40,21 +41,13 @@ import com.ecwid.consul.v1.ConsulClient;
@AutoConfigureBefore(ServiceRegistryAutoConfiguration.class)
public class ConsulServiceRegistryAutoConfiguration {
@Autowired(required = false)
private TtlScheduler ttlScheduler;
@Bean
@ConditionalOnMissingBean
public ConsulServiceRegistry consulServiceRegistry(ConsulClient consulClient, ConsulDiscoveryProperties properties,
HeartbeatProperties heartbeatProperties) {
return new ConsulServiceRegistry(consulClient, properties, ttlScheduler, heartbeatProperties);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty("spring.cloud.consul.discovery.heartbeat.enabled")
public TtlScheduler ttlScheduler(ConsulClient consulClient, HeartbeatProperties heartbeatProperties) {
return new TtlScheduler(heartbeatProperties, consulClient);
public ConsulServiceRegistry consulServiceRegistry(ConsulClient consulClient,
ConsulDiscoveryProperties properties, HeartbeatProperties heartbeatProperties,
@Autowired(required = false) TtlScheduler ttlScheduler) {
return new ConsulServiceRegistry(consulClient, properties, ttlScheduler,
heartbeatProperties);
}
@Bean
@@ -65,6 +58,7 @@ public class ConsulServiceRegistryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
// TODO: Split appropriate values to service-registry for Edgware
public ConsulDiscoveryProperties consulDiscoveryProperties(InetUtils inetUtils) {
return new ConsulDiscoveryProperties(inetUtils);
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2013-2019 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
*
* https://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.support;
import com.ecwid.consul.v1.ConsulClient;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.consul.ConditionalOnConsulEnabled;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryClientConfiguration;
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
import org.springframework.cloud.consul.discovery.TtlScheduler;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto configuration for the heartbeat.
*
* @author Tim Ysewyn
*/
@Configuration
@ConditionalOnConsulEnabled
@ConditionalOnProperty("spring.cloud.consul.discovery.heartbeat.enabled")
@ConditionalOnDiscoveryEnabled
@AutoConfigureBefore({ ConsulServiceRegistryAutoConfiguration.class })
@AutoConfigureAfter({ ConsulDiscoveryClientConfiguration.class })
public class ConsulHeartbeatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public HeartbeatProperties heartbeatProperties() {
return new HeartbeatProperties();
}
@Bean
@ConditionalOnMissingBean
public TtlScheduler ttlScheduler(HeartbeatProperties heartbeatProperties,
ConsulClient consulClient) {
return new TtlScheduler(heartbeatProperties, consulClient);
}
}

View File

@@ -3,9 +3,9 @@ org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration,\
org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerAutoConfiguration,\
org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration,\
org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration,\
org.springframework.cloud.consul.discovery.ConsulDiscoveryClientConfiguration
org.springframework.cloud.consul.discovery.ConsulDiscoveryClientConfiguration,\
org.springframework.cloud.consul.discovery.ConsulCatalogWatchAutoConfiguration, \
org.springframework.cloud.consul.support.ConsulHeartbeatAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.consul.discovery.configclient.ConsulDiscoveryClientConfigServiceBootstrapConfiguration

View File

@@ -1,39 +1,54 @@
/*
* Copyright 2013-2019 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.consul.discovery;
import java.util.List;
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.test.context.SpringBootTest;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.consul.ConsulAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.QueryParams;
import com.ecwid.consul.v1.Response;
import com.ecwid.consul.v1.health.model.Check;
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.test.context.SpringBootTest;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.consul.ConsulAutoConfiguration;
import org.springframework.cloud.consul.support.ConsulHeartbeatAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import static com.ecwid.consul.v1.health.model.Check.CheckStatus.CRITICAL;
import static com.ecwid.consul.v1.health.model.Check.CheckStatus.PASSING;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Stéphane Leroy
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TtlSchedulerRemoveTests.TtlSchedulerRemoveTestConfig.class,
properties = { "spring.application.name=ttlSchedulerRemove",
@SpringBootTest(classes = TtlSchedulerRemoveTests.TtlSchedulerRemoveTestConfig.class, properties = {
"spring.application.name=ttlSchedulerRemove",
"spring.cloud.consul.discovery.instance-id=ttlSchedulerRemove-id",
"spring.cloud.consul.discovery.heartbeat.enabled=true",
"spring.cloud.consul.discovery.heartbeat.ttlValue=2" },
webEnvironment = RANDOM_PORT)
"spring.cloud.consul.discovery.heartbeat.ttlValue=2" }, webEnvironment = RANDOM_PORT)
public class TtlSchedulerRemoveTests {
@Autowired
@@ -46,20 +61,20 @@ public class TtlSchedulerRemoveTests {
public void should_not_send_check_if_service_removed() throws InterruptedException {
Thread.sleep(1000); // wait for Ttlscheduler to send a check to consul.
Check serviceCheck = getCheckForService("ttlSchedulerRemove");
assertThat("Service check is in wrong state", serviceCheck.getStatus(),
equalTo(PASSING));
assertThat(serviceCheck.getStatus()).as("Service check is in wrong state")
.isEqualTo(PASSING);
// Remove service from TtlScheduler and wait for TTL to expired.
ttlScheduler.remove("ttlSchedulerRemove-id");
this.ttlScheduler.remove("ttlSchedulerRemove-id");
Thread.sleep(2100);
serviceCheck = getCheckForService("ttlSchedulerRemove");
assertThat("Service check is in wrong state", serviceCheck.getStatus(),
equalTo(CRITICAL));
assertThat(serviceCheck.getStatus()).as("Service check is in wrong state")
.isEqualTo(CRITICAL);
}
private Check getCheckForService(String serviceId) {
Response<List<Check>> checkResponse = consul.getHealthChecksForService(serviceId,
QueryParams.DEFAULT);
Response<List<Check>> checkResponse = this.consul
.getHealthChecksForService(serviceId, QueryParams.DEFAULT);
if (checkResponse.getValue().size() > 0) {
return checkResponse.getValue().get(0);
}
@@ -68,9 +83,11 @@ public class TtlSchedulerRemoveTests {
@Configuration
@EnableAutoConfiguration
@Import({ AutoServiceRegistrationConfiguration.class,
ConsulAutoConfiguration.class,
ConsulDiscoveryClientConfiguration.class })
public static class TtlSchedulerRemoveTestConfig { }
}
@Import({ AutoServiceRegistrationConfiguration.class, ConsulAutoConfiguration.class,
ConsulDiscoveryClientConfiguration.class,
ConsulHeartbeatAutoConfiguration.class })
public static class TtlSchedulerRemoveTestConfig {
}
}

View File

@@ -1,22 +1,39 @@
/*
* Copyright 2013-2019 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.consul.discovery;
import java.util.List;
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.test.context.SpringBootTest;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.consul.ConsulAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.QueryParams;
import com.ecwid.consul.v1.Response;
import com.ecwid.consul.v1.health.model.Check;
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.test.context.SpringBootTest;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.consul.ConsulAutoConfiguration;
import org.springframework.cloud.consul.support.ConsulHeartbeatAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import static com.ecwid.consul.v1.health.model.Check.CheckStatus.PASSING;
import static org.assertj.core.api.Assertions.assertThat;
@@ -26,12 +43,12 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Stéphane Leroy
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TtlSchedulerTests.TtlSchedulerTestConfig.class,
properties = { "spring.application.name=ttlScheduler",
@SpringBootTest(classes = TtlSchedulerTests.TtlSchedulerTestConfig.class, properties = {
"spring.application.name=ttlScheduler",
"spring.cloud.consul.discovery.instance-id=ttlScheduler-id",
"spring.cloud.consul.discovery.heartbeat.enabled=true",
"spring.cloud.consul.discovery.heartbeat.ttlValue=2", "management.server.port=0" },
webEnvironment = RANDOM_PORT)
"spring.cloud.consul.discovery.heartbeat.ttlValue=2",
"management.server.port=0" }, webEnvironment = RANDOM_PORT)
public class TtlSchedulerTests {
@Autowired
@@ -53,8 +70,8 @@ public class TtlSchedulerTests {
}
private Check getCheckForService(String serviceId) {
Response<List<Check>> checkResponse = consul.getHealthChecksForService(serviceId,
QueryParams.DEFAULT);
Response<List<Check>> checkResponse = this.consul
.getHealthChecksForService(serviceId, QueryParams.DEFAULT);
if (checkResponse.getValue().size() > 0) {
return checkResponse.getValue().get(0);
}
@@ -63,10 +80,11 @@ public class TtlSchedulerTests {
@Configuration
@EnableAutoConfiguration
@Import({ AutoServiceRegistrationConfiguration.class,
ConsulAutoConfiguration.class,
ConsulDiscoveryClientConfiguration.class })
public static class TtlSchedulerTestConfig { }
@Import({ AutoServiceRegistrationConfiguration.class, ConsulAutoConfiguration.class,
ConsulDiscoveryClientConfiguration.class,
ConsulHeartbeatAutoConfiguration.class })
public static class TtlSchedulerTestConfig {
}
}