Cache config client health indicator.
So config server isn't bombarded with requests.
This commit is contained in:
@@ -1166,6 +1166,10 @@ If you use another form of security you might need to <<custom-rest-template,pro
|
||||
`RestTemplate`>> to the `ConfigServicePropertySourceLocator` (e.g. by
|
||||
grabbing it in the bootstrap context and injecting one).
|
||||
|
||||
==== Health Indicator
|
||||
|
||||
The Config Client supplies a Spring Boot Health Indicator that attempts to load configuration from Config Server. The health indicator can be disabled by setting `health.config.enabled=false`. The response is also cached for performance reasons. The default cache time to live is 5 minutes. To change that value set the `health.config.time-to-live` property (in milliseconds).
|
||||
|
||||
[[custom-rest-template]]
|
||||
==== Providing A Custom RestTemplate
|
||||
|
||||
|
||||
@@ -53,6 +53,11 @@ public class ConfigClientAutoConfiguration {
|
||||
return client;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigClientHealthProperties configClientHealthProperties() {
|
||||
return new ConfigClientHealthProperties();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(HealthIndicator.class)
|
||||
@ConditionalOnBean(ConfigServicePropertySourceLocator.class)
|
||||
@@ -61,24 +66,9 @@ public class ConfigClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ConfigServerHealthIndicator configServerHealthIndicator(
|
||||
ConfigServicePropertySourceLocator locator, Environment environment) {
|
||||
return new ConfigServerHealthIndicator(locator, environment);
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigurationProperties("health.config")
|
||||
public static class Health {
|
||||
/**
|
||||
* Flag to indicate that the config server health indicator should be installed.
|
||||
*/
|
||||
boolean enabled;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
ConfigServicePropertySourceLocator locator,
|
||||
ConfigClientHealthProperties properties, Environment environment) {
|
||||
return new ConfigServerHealthIndicator(locator, environment, properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.config.client;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@ConfigurationProperties("health.config")
|
||||
public class ConfigClientHealthProperties {
|
||||
/**
|
||||
* Flag to indicate that the config server health indicator should be installed.
|
||||
*/
|
||||
boolean enabled;
|
||||
|
||||
/**
|
||||
* Time to live for cached result, in milliseconds. Default 300000 (5 min).
|
||||
*/
|
||||
private long timeToLive = 60 * 5 * 1000;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public long getTimeToLive() {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
public void setTimeToLive(long timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,23 @@ import org.springframework.core.env.PropertySource;
|
||||
public class ConfigServerHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
private ConfigServicePropertySourceLocator locator;
|
||||
private ConfigClientHealthProperties properties;
|
||||
private Environment environment;
|
||||
|
||||
private long lastAccess = 0;
|
||||
|
||||
private PropertySource<?> cached;
|
||||
|
||||
public ConfigServerHealthIndicator(ConfigServicePropertySourceLocator locator,
|
||||
Environment environment) {
|
||||
Environment environment, ConfigClientHealthProperties properties) {
|
||||
this.environment = environment;
|
||||
this.locator = locator;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Builder builder) throws Exception {
|
||||
PropertySource<?> propertySource = locator.locate(this.environment);
|
||||
PropertySource<?> propertySource = getPropertySource();
|
||||
builder.up();
|
||||
if (propertySource instanceof CompositePropertySource) {
|
||||
List<String> sources = new ArrayList<>();
|
||||
@@ -40,4 +46,21 @@ public class ConfigServerHealthIndicator extends AbstractHealthIndicator {
|
||||
builder.unknown().withDetail("error", "no property sources located");
|
||||
}
|
||||
}
|
||||
|
||||
private PropertySource<?> getPropertySource() {
|
||||
long accessTime = System.currentTimeMillis();
|
||||
if (isCacheStale(accessTime)) {
|
||||
this.lastAccess = accessTime;
|
||||
this.cached = locator.locate(this.environment);
|
||||
}
|
||||
return this.cached;
|
||||
}
|
||||
|
||||
private boolean isCacheStale(long accessTime) {
|
||||
if (this.cached == null) {
|
||||
return true;
|
||||
}
|
||||
return (accessTime - this.lastAccess) >= this.properties.getTimeToLive();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,11 +17,16 @@
|
||||
package org.springframework.cloud.config.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
@@ -34,11 +39,11 @@ import org.springframework.core.env.PropertySource;
|
||||
*/
|
||||
public class ConfigServerHealthIndicatorTests {
|
||||
|
||||
private ConfigServicePropertySourceLocator locator = Mockito
|
||||
.mock(ConfigServicePropertySourceLocator.class);
|
||||
private Environment environment = Mockito.mock(Environment.class);
|
||||
private ConfigServicePropertySourceLocator locator =
|
||||
mock(ConfigServicePropertySourceLocator.class);
|
||||
private Environment environment = mock(Environment.class);
|
||||
private ConfigServerHealthIndicator indicator = new ConfigServerHealthIndicator(
|
||||
locator, environment);
|
||||
locator, environment, new ConfigClientHealthProperties());
|
||||
|
||||
@Test
|
||||
public void testDefaultStatus() {
|
||||
@@ -48,15 +53,32 @@ public class ConfigServerHealthIndicatorTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionStatus() {
|
||||
Mockito.doThrow(new IllegalStateException()).when(locator).locate(Mockito.any(Environment.class));
|
||||
doThrow(new IllegalStateException()).when(locator).locate(any(Environment.class));
|
||||
assertEquals(Status.DOWN, indicator.health().getStatus());
|
||||
verify(locator, times(1)).locate(any(Environment.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerUp() {
|
||||
PropertySource<?> source = new MapPropertySource("foo", Collections.<String,Object>emptyMap());
|
||||
Mockito.doReturn(source).when(locator).locate(Mockito.any(Environment.class));
|
||||
doReturn(source).when(locator).locate(any(Environment.class));
|
||||
assertEquals(Status.UP, indicator.health().getStatus());
|
||||
verify(locator, times(1)).locate(any(Environment.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthIsCached() {
|
||||
PropertySource<?> source = new MapPropertySource("foo", Collections.<String,Object>emptyMap());
|
||||
doReturn(source).when(locator).locate(any(Environment.class));
|
||||
|
||||
// not cached
|
||||
assertEquals(Status.UP, indicator.health().getStatus());
|
||||
|
||||
// cached
|
||||
assertEquals(Status.UP, indicator.health().getStatus());
|
||||
|
||||
verify(locator, times(1)).locate(any(Environment.class));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user