Add support for retry in config client
If Spring Retry is on the classpath (and AspectJ) the config client will create a proxy for the ConfigServerPropertySourceLocator that retries a failed environment fetch. In this way the client can be made to wait for the config server to come up, even if failFast=true. (If failFast=false, the default, then it has no effect.) Fixes gh-90, fixes gh-129
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -41,6 +41,11 @@
|
||||
<artifactId>spring-cloud-config-server</artifactId>
|
||||
<version>1.0.1.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.retry</groupId>
|
||||
<artifactId>spring-retry</artifactId>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
|
||||
@@ -43,11 +43,21 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.retry</groupId>
|
||||
<artifactId>spring-retry</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
@@ -62,5 +62,5 @@ public class ConfigClientAutoConfiguration {
|
||||
return new ConfigServerHealthIndicator(locator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,12 +16,21 @@
|
||||
|
||||
package org.springframework.cloud.config.client;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.retry.interceptor.RetryInterceptorBuilder;
|
||||
import org.springframework.retry.interceptor.RetryOperationsInterceptor;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -48,4 +57,23 @@ public class ConfigServiceBootstrapConfiguration {
|
||||
return locator;
|
||||
}
|
||||
|
||||
@ConditionalOnClass({ Retryable.class, Aspect.class, AopAutoConfiguration.class })
|
||||
@Configuration
|
||||
@EnableRetry(proxyTargetClass = true)
|
||||
@Import(AopAutoConfiguration.class)
|
||||
@EnableConfigurationProperties(RetryProperties.class)
|
||||
protected static class RetryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "configServerRetryInterceptor")
|
||||
public RetryOperationsInterceptor configServerRetryInterceptor(
|
||||
RetryProperties properties) {
|
||||
return RetryInterceptorBuilder
|
||||
.stateless()
|
||||
.backOffOptions(properties.getInitialInterval(),
|
||||
properties.getMultiplier(), properties.getMaxInterval())
|
||||
.maxAttempts(properties.getMaxAttempts()).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.HttpServerErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
@@ -57,6 +58,7 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
|
||||
}
|
||||
|
||||
@Override
|
||||
@Retryable(interceptor="configServerRetryInterceptor")
|
||||
public org.springframework.core.env.PropertySource<?> locate(
|
||||
org.springframework.core.env.Environment environment) {
|
||||
ConfigClientProperties client = defaults.override(environment);
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.config.client;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("spring.config.retry")
|
||||
public class RetryProperties {
|
||||
|
||||
/**
|
||||
* Initial retry interval in milliseconds.
|
||||
*/
|
||||
long initialInterval = 1000;
|
||||
/**
|
||||
* Multiplier for next interval.
|
||||
*/
|
||||
double multiplier = 1.1;
|
||||
/**
|
||||
* Maximum interval for backoff.
|
||||
*/
|
||||
long maxInterval = 2000;
|
||||
/**
|
||||
* Maximum number of attempts.
|
||||
*/
|
||||
int maxAttempts = 6;
|
||||
|
||||
public long getInitialInterval() {
|
||||
return this.initialInterval;
|
||||
}
|
||||
|
||||
public void setInitialInterval(long initialInterval) {
|
||||
this.initialInterval = initialInterval;
|
||||
}
|
||||
|
||||
public double getMultiplier() {
|
||||
return this.multiplier;
|
||||
}
|
||||
|
||||
public void setMultiplier(double multiplier) {
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
public long getMaxInterval() {
|
||||
return this.maxInterval;
|
||||
}
|
||||
|
||||
public void setMaxInterval(long maxInterval) {
|
||||
this.maxInterval = maxInterval;
|
||||
}
|
||||
|
||||
public int getMaxAttempts() {
|
||||
return this.maxAttempts;
|
||||
}
|
||||
|
||||
public void setMaxAttempts(int maxAttempts) {
|
||||
this.maxAttempts = maxAttempts;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user