Applied checkstyle and turned it on by default
This commit is contained in:
@@ -37,4 +37,4 @@ jobs:
|
||||
destination: artifacts
|
||||
- store_test_results:
|
||||
path: ~/junit/
|
||||
destination: testartifacts
|
||||
destination: testartifacts
|
||||
|
||||
14
.editorconfig
Normal file
14
.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
128
.settings.xml
128
.settings.xml
@@ -1,66 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<settings>
|
||||
<servers>
|
||||
<server>
|
||||
<id>repo.spring.io</id>
|
||||
<username>${env.CI_DEPLOY_USERNAME}</username>
|
||||
<password>${env.CI_DEPLOY_PASSWORD}</password>
|
||||
</server>
|
||||
</servers>
|
||||
<profiles>
|
||||
<profile>
|
||||
<!--
|
||||
N.B. this profile is only here to support users and IDEs that do not use Maven 3.3.
|
||||
It isn't needed on the command line if you use the wrapper script (mvnw) or if you use
|
||||
a native Maven with the right version. Eclipse users should points their Maven tooling to
|
||||
this settings file, or copy the profile into their ~/.m2/settings.xml.
|
||||
-->
|
||||
<id>spring</id>
|
||||
<activation><activeByDefault>true</activeByDefault></activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>http://repo.spring.io/libs-snapshot-local</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>http://repo.spring.io/libs-milestone-local</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-releases</id>
|
||||
<name>Spring Releases</name>
|
||||
<url>http://repo.spring.io/release</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>http://repo.spring.io/libs-snapshot-local</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>http://repo.spring.io/libs-milestone-local</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
</profiles>
|
||||
<servers>
|
||||
<server>
|
||||
<id>repo.spring.io</id>
|
||||
<username>${env.CI_DEPLOY_USERNAME}</username>
|
||||
<password>${env.CI_DEPLOY_PASSWORD}</password>
|
||||
</server>
|
||||
</servers>
|
||||
<profiles>
|
||||
<profile>
|
||||
<!--
|
||||
N.B. this profile is only here to support users and IDEs that do not use Maven 3.3.
|
||||
It isn't needed on the command line if you use the wrapper script (mvnw) or if you use
|
||||
a native Maven with the right version. Eclipse users should points their Maven tooling to
|
||||
this settings file, or copy the profile into their ~/.m2/settings.xml.
|
||||
-->
|
||||
<id>spring</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>http://repo.spring.io/libs-snapshot-local</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>http://repo.spring.io/libs-milestone-local</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-releases</id>
|
||||
<name>Spring Releases</name>
|
||||
<url>http://repo.spring.io/release</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>http://repo.spring.io/libs-snapshot-local</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>http://repo.spring.io/libs-milestone-local</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
</profiles>
|
||||
</settings>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
40
pom.xml
40
pom.xml
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons-parent</artifactId>
|
||||
@@ -16,12 +18,18 @@
|
||||
</parent>
|
||||
<scm>
|
||||
<url>https://github.com/spring-cloud/spring-cloud-commons</url>
|
||||
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git</developerConnection>
|
||||
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git
|
||||
</connection>
|
||||
<developerConnection>
|
||||
scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git
|
||||
</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
<properties>
|
||||
<bintray.package>commons</bintray.package>
|
||||
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
|
||||
<maven-checkstyle-plugin.failsOnViolation>true
|
||||
</maven-checkstyle-plugin.failsOnViolation>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -33,17 +41,39 @@
|
||||
<additionalConfig>
|
||||
<file>
|
||||
<name>.settings/org.eclipse.jdt.ui.prefs</name>
|
||||
<location>${maven.multiModuleProjectDirectory}/eclipse/org.eclipse.jdt.ui.prefs</location>
|
||||
<location>
|
||||
${maven.multiModuleProjectDirectory}/eclipse/org.eclipse.jdt.ui.prefs
|
||||
</location>
|
||||
</file>
|
||||
<file>
|
||||
<name>.settings/org.eclipse.jdt.core.prefs</name>
|
||||
<location>${maven.multiModuleProjectDirectory}/eclipse/org.eclipse.jdt.core.prefs</location>
|
||||
<location>
|
||||
${maven.multiModuleProjectDirectory}/eclipse/org.eclipse.jdt.core.prefs
|
||||
</location>
|
||||
</file>
|
||||
</additionalConfig>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>io.spring.javaformat</groupId>
|
||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>spring</id>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>2.1.3.BUILD-SNAPSHOT</version>
|
||||
<relativePath/>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-commons-dependencies</artifactId>
|
||||
<version>2.1.1.BUILD-SNAPSHOT</version>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
|
||||
@@ -57,10 +57,12 @@ public class CommonsClientAutoConfiguration {
|
||||
@ConditionalOnBean(DiscoveryClient.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.discovery.enabled", matchIfMissing = true)
|
||||
protected static class DiscoveryLoadBalancerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.cloud.discovery.client.health-indicator.enabled", matchIfMissing = true)
|
||||
public DiscoveryClientHealthIndicator discoveryClientHealthIndicator(
|
||||
ObjectProvider<DiscoveryClient> discoveryClient, DiscoveryClientHealthIndicatorProperties properties) {
|
||||
ObjectProvider<DiscoveryClient> discoveryClient,
|
||||
DiscoveryClientHealthIndicatorProperties properties) {
|
||||
return new DiscoveryClientHealthIndicator(discoveryClient, properties);
|
||||
}
|
||||
|
||||
@@ -77,12 +79,14 @@ public class CommonsClientAutoConfiguration {
|
||||
return HasFeatures.abstractFeatures(DiscoveryClient.class,
|
||||
LoadBalancerClient.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(Endpoint.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.features.enabled", matchIfMissing = true)
|
||||
protected static class ActuatorConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<HasFeatures> hasFeatures = new ArrayList<>();
|
||||
|
||||
@@ -91,6 +95,7 @@ public class CommonsClientAutoConfiguration {
|
||||
public FeaturesEndpoint featuresEndpoint() {
|
||||
return new FeaturesEndpoint(this.hasFeatures);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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,7 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.client;
|
||||
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -50,8 +49,8 @@ public class DefaultServiceInstance implements ServiceInstance {
|
||||
* @param secure indicates whether or not the connection needs to be secure.
|
||||
* @param metadata a map containing metadata.
|
||||
*/
|
||||
public DefaultServiceInstance(String instanceId, String serviceId, String host, int port, boolean secure,
|
||||
Map<String, String> metadata) {
|
||||
public DefaultServiceInstance(String instanceId, String serviceId, String host,
|
||||
int port, boolean secure, Map<String, String> metadata) {
|
||||
this.instanceId = instanceId;
|
||||
this.serviceId = serviceId;
|
||||
this.host = host;
|
||||
@@ -67,7 +66,8 @@ public class DefaultServiceInstance implements ServiceInstance {
|
||||
* @param port the port on which the service is running.
|
||||
* @param secure indicates whether or not the connection needs to be secure.
|
||||
*/
|
||||
public DefaultServiceInstance(String instanceId, String serviceId, String host, int port, boolean secure) {
|
||||
public DefaultServiceInstance(String instanceId, String serviceId, String host,
|
||||
int port, boolean secure) {
|
||||
this(instanceId, serviceId, host, port, secure, new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class DefaultServiceInstance implements ServiceInstance {
|
||||
* @param port the port on which the service is running.
|
||||
* @param secure indicates whether or not the connection needs to be secure.
|
||||
* @param metadata a map containing metadata.
|
||||
* @deprecated
|
||||
* @deprecated - use other constructors
|
||||
*/
|
||||
@Deprecated
|
||||
public DefaultServiceInstance(String serviceId, String host, int port, boolean secure,
|
||||
@@ -90,7 +90,7 @@ public class DefaultServiceInstance implements ServiceInstance {
|
||||
* @param host the host where the service instance can be found.
|
||||
* @param port the port on which the service is running.
|
||||
* @param secure indicates whether or not the connection needs to be secure.
|
||||
* @deprecated
|
||||
* @deprecated - use other constructors
|
||||
*/
|
||||
@Deprecated
|
||||
public DefaultServiceInstance(String serviceId, String host, int port,
|
||||
@@ -98,16 +98,6 @@ public class DefaultServiceInstance implements ServiceInstance {
|
||||
this(serviceId, host, port, secure, new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return getUri(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URI from the given ServiceInstance's host:port.
|
||||
* @param instance the ServiceInstance.
|
||||
@@ -120,58 +110,69 @@ public class DefaultServiceInstance implements ServiceInstance {
|
||||
return URI.create(uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return getUri(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceId() {
|
||||
return instanceId;
|
||||
return this.instanceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return serviceId;
|
||||
return this.serviceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
return host;
|
||||
return this.host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return port;
|
||||
return this.port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return secure;
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DefaultServiceInstance{" +
|
||||
"instanceId='" + instanceId + '\'' +
|
||||
", serviceId='" + serviceId + '\'' +
|
||||
", host='" + host + '\'' +
|
||||
", port=" + port +
|
||||
", secure=" + secure +
|
||||
", metadata=" + metadata +
|
||||
'}';
|
||||
return "DefaultServiceInstance{" + "instanceId='" + this.instanceId + '\''
|
||||
+ ", serviceId='" + this.serviceId + '\'' + ", host='" + this.host + '\''
|
||||
+ ", port=" + this.port + ", secure=" + this.secure + ", metadata="
|
||||
+ this.metadata + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
DefaultServiceInstance that = (DefaultServiceInstance) o;
|
||||
return port == that.port &&
|
||||
secure == that.secure &&
|
||||
Objects.equals(instanceId, that.instanceId) &&
|
||||
Objects.equals(serviceId, that.serviceId) &&
|
||||
Objects.equals(host, that.host) &&
|
||||
Objects.equals(metadata, that.metadata);
|
||||
return this.port == that.port && this.secure == that.secure
|
||||
&& Objects.equals(this.instanceId, that.instanceId)
|
||||
&& Objects.equals(this.serviceId, that.serviceId)
|
||||
&& Objects.equals(this.host, that.host)
|
||||
&& Objects.equals(this.metadata, that.metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(instanceId, serviceId, host, port, secure, metadata);
|
||||
return Objects.hash(this.instanceId, this.serviceId, this.host, this.port,
|
||||
this.secure, this.metadata);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -50,4 +66,5 @@ public class HostInfoEnvironmentPostProcessor
|
||||
return utils.findFirstNonLoopbackHostInfo();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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.
|
||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents an instance of a service in a discovery system.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
@@ -69,4 +70,5 @@ public interface ServiceInstance {
|
||||
default String getScheme() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@@ -17,4 +38,5 @@ import java.lang.annotation.*;
|
||||
@EnableDiscoveryClient
|
||||
@EnableCircuitBreaker
|
||||
public @interface SpringCloudApplication {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -26,15 +26,14 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Endpoint(id = "features")
|
||||
public class FeaturesEndpoint
|
||||
implements ApplicationContextAware {
|
||||
public class FeaturesEndpoint implements ApplicationContextAware {
|
||||
|
||||
private final List<HasFeatures> hasFeaturesList;
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
public FeaturesEndpoint(List<HasFeatures> hasFeaturesList) {
|
||||
@@ -90,26 +89,32 @@ public class FeaturesEndpoint
|
||||
}
|
||||
|
||||
static class Features {
|
||||
|
||||
final List<Feature> enabled = new ArrayList<>();
|
||||
|
||||
final List<String> disabled = new ArrayList<>();
|
||||
|
||||
public List<Feature> getEnabled() {
|
||||
return enabled;
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public List<String> getDisabled() {
|
||||
return disabled;
|
||||
return this.disabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static class Feature {
|
||||
|
||||
final String type;
|
||||
|
||||
final String name;
|
||||
|
||||
final String version;
|
||||
|
||||
final String vendor;
|
||||
|
||||
public Feature(String name, String type, String version, String vendor) {
|
||||
Feature(String name, String type, String version, String vendor) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
@@ -117,51 +122,64 @@ public class FeaturesEndpoint
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public String getVendor() {
|
||||
return vendor;
|
||||
return this.vendor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Feature{" +
|
||||
"type='" + type + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
", vendor='" + vendor + '\'' +
|
||||
'}';
|
||||
return "Feature{" + "type='" + this.type + '\'' + ", name='" + this.name
|
||||
+ '\'' + ", version='" + this.version + '\'' + ", vendor='"
|
||||
+ this.vendor + '\'' + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Feature feature = (Feature) o;
|
||||
|
||||
if (type != null ? !type.equals(feature.type) : feature.type != null) return false;
|
||||
if (name != null ? !name.equals(feature.name) : feature.name != null) return false;
|
||||
if (version != null ? !version.equals(feature.version) : feature.version != null) return false;
|
||||
return vendor != null ? vendor.equals(feature.vendor) : feature.vendor == null;
|
||||
if (this.type != null ? !this.type.equals(feature.type)
|
||||
: feature.type != null) {
|
||||
return false;
|
||||
}
|
||||
if (this.name != null ? !this.name.equals(feature.name)
|
||||
: feature.name != null) {
|
||||
return false;
|
||||
}
|
||||
if (this.version != null ? !this.version.equals(feature.version)
|
||||
: feature.version != null) {
|
||||
return false;
|
||||
}
|
||||
return this.vendor != null ? this.vendor.equals(feature.vendor)
|
||||
: feature.vendor == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = type != null ? type.hashCode() : 0;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
result = 31 * result + (version != null ? version.hashCode() : 0);
|
||||
result = 31 * result + (vendor != null ? vendor.hashCode() : 0);
|
||||
int result = this.type != null ? this.type.hashCode() : 0;
|
||||
result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
|
||||
result = 31 * result + (this.version != null ? this.version.hashCode() : 0);
|
||||
result = 31 * result + (this.vendor != null ? this.vendor.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.actuator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -14,13 +30,19 @@ public class HasFeatures {
|
||||
|
||||
private final List<NamedFeature> namedFeatures = new ArrayList<>();
|
||||
|
||||
public HasFeatures(List<Class<?>> abstractFeatures,
|
||||
List<NamedFeature> namedFeatures) {
|
||||
this.abstractFeatures.addAll(abstractFeatures);
|
||||
this.namedFeatures.addAll(namedFeatures);
|
||||
}
|
||||
|
||||
public static HasFeatures abstractFeatures(Class<?>... abstractFeatures) {
|
||||
return new HasFeatures(Arrays.asList(abstractFeatures),
|
||||
Collections.<NamedFeature> emptyList());
|
||||
Collections.<NamedFeature>emptyList());
|
||||
}
|
||||
|
||||
public static HasFeatures namedFeatures(NamedFeature... namedFeatures) {
|
||||
return new HasFeatures(Collections.<Class<?>> emptyList(),
|
||||
return new HasFeatures(Collections.<Class<?>>emptyList(),
|
||||
Arrays.asList(namedFeatures));
|
||||
}
|
||||
|
||||
@@ -34,12 +56,6 @@ public class HasFeatures {
|
||||
new NamedFeature(name2, type2));
|
||||
}
|
||||
|
||||
public HasFeatures(List<Class<?>> abstractFeatures,
|
||||
List<NamedFeature> namedFeatures) {
|
||||
this.abstractFeatures.addAll(abstractFeatures);
|
||||
this.namedFeatures.addAll(namedFeatures);
|
||||
}
|
||||
|
||||
public List<Class<?>> getAbstractFeatures() {
|
||||
return this.abstractFeatures;
|
||||
}
|
||||
@@ -47,4 +63,5 @@ public class HasFeatures {
|
||||
public List<NamedFeature> getNamedFeatures() {
|
||||
return this.namedFeatures;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,14 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.client.actuator;
|
||||
|
||||
package org.springframework.cloud.client.actuator;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class NamedFeature {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
public NamedFeature(String name, Class<?> type) {
|
||||
@@ -29,10 +31,11 @@ public class NamedFeature {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
return this.type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,16 +22,17 @@ import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Imports a single circuit breaker implementation configuration.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 100)
|
||||
public class EnableCircuitBreakerImportSelector extends
|
||||
SpringFactoryImportSelector<EnableCircuitBreaker> {
|
||||
public class EnableCircuitBreakerImportSelector
|
||||
extends SpringFactoryImportSelector<EnableCircuitBreaker> {
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled() {
|
||||
return getEnvironment().getProperty(
|
||||
"spring.cloud.circuit.breaker.enabled", Boolean.class, Boolean.TRUE);
|
||||
return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled",
|
||||
Boolean.class, Boolean.TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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.
|
||||
@@ -30,18 +30,19 @@ import org.springframework.core.Ordered;
|
||||
*/
|
||||
public interface DiscoveryClient extends Ordered {
|
||||
|
||||
/**
|
||||
* Default order of the discovery client.
|
||||
*/
|
||||
int DEFAULT_ORDER = 0;
|
||||
|
||||
/**
|
||||
* A human-readable description of the implementation, used in HealthIndicator.
|
||||
*
|
||||
* @return The description.
|
||||
*/
|
||||
String description();
|
||||
|
||||
/**
|
||||
* Gets all ServiceInstances associated with a particular serviceId.
|
||||
*
|
||||
* @param serviceId The serviceId to query.
|
||||
* @return A List of ServiceInstance.
|
||||
*/
|
||||
@@ -54,11 +55,11 @@ public interface DiscoveryClient extends Ordered {
|
||||
|
||||
/**
|
||||
* Default implementation for getting order of discovery clients.
|
||||
*
|
||||
* @return order
|
||||
*/
|
||||
@Override
|
||||
default int getOrder() {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ public @interface EnableDiscoveryClient {
|
||||
|
||||
/**
|
||||
* If true, the ServiceRegistry will automatically register the local server.
|
||||
* @return - {@code true} if you want to automatically register.
|
||||
*/
|
||||
boolean autoRegister() default true;
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
package org.springframework.cloud.client.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.commons.util.SpringFactoryImportSelector;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
@@ -25,11 +30,6 @@ import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@@ -48,12 +48,14 @@ public class EnableDiscoveryClientImportSelector
|
||||
|
||||
if (autoRegister) {
|
||||
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
|
||||
importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
|
||||
importsList.add(
|
||||
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
|
||||
imports = importsList.toArray(new String[0]);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Environment env = getEnvironment();
|
||||
if(ConfigurableEnvironment.class.isInstance(env)) {
|
||||
ConfigurableEnvironment configEnv = (ConfigurableEnvironment)env;
|
||||
if (ConfigurableEnvironment.class.isInstance(env)) {
|
||||
ConfigurableEnvironment configEnv = (ConfigurableEnvironment) env;
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("spring.cloud.service-registry.auto-registration.enabled", false);
|
||||
MapPropertySource propertySource = new MapPropertySource(
|
||||
@@ -68,8 +70,8 @@ public class EnableDiscoveryClientImportSelector
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled() {
|
||||
return getEnvironment().getProperty(
|
||||
"spring.cloud.discovery.enabled", Boolean.class, Boolean.TRUE);
|
||||
return getEnvironment().getProperty("spring.cloud.discovery.enabled",
|
||||
Boolean.class, Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,23 +23,34 @@ import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* FIXME:
|
||||
* Utility class for management server ports.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ManagementServerPortUtils {
|
||||
/** for testing */ static final boolean hasActuator;
|
||||
public final class ManagementServerPortUtils {
|
||||
|
||||
// for testing
|
||||
static final boolean hasActuator;
|
||||
|
||||
static {
|
||||
boolean hasEndpointClass = hasClass("org.springframework.boot.actuate.endpoint.annotation.Endpoint");
|
||||
boolean hasManagementServerPropertiesClass = hasClass("org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties");
|
||||
boolean hasEndpointClass = hasClass(
|
||||
"org.springframework.boot.actuate.endpoint.annotation.Endpoint");
|
||||
boolean hasManagementServerPropertiesClass = hasClass(
|
||||
"org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties");
|
||||
hasActuator = hasEndpointClass && hasManagementServerPropertiesClass;
|
||||
}
|
||||
|
||||
private ManagementServerPortUtils() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
private static boolean hasClass(String className) {
|
||||
boolean hasClass;
|
||||
try {
|
||||
Class.forName(className);
|
||||
hasClass = true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
hasClass = false;
|
||||
}
|
||||
return hasClass;
|
||||
@@ -76,9 +87,26 @@ public class ManagementServerPortUtils {
|
||||
}
|
||||
|
||||
// TODO: copied from EndpointWebMvcAutoConfiguration.ManagementServerPort
|
||||
public static enum ManagementServerPort {
|
||||
|
||||
DISABLE, SAME, DIFFERENT;
|
||||
/**
|
||||
* Enumeration for management server ports.
|
||||
*/
|
||||
public enum ManagementServerPort {
|
||||
|
||||
/**
|
||||
* Disabled management server port.
|
||||
*/
|
||||
DISABLE,
|
||||
|
||||
/**
|
||||
* Add it. TODO: Add it
|
||||
*/
|
||||
SAME,
|
||||
|
||||
/**
|
||||
* Add it. TODO: Add it
|
||||
*/
|
||||
DIFFERENT;
|
||||
|
||||
public static ManagementServerPort get(BeanFactory beanFactory) {
|
||||
if (!hasActuator) {
|
||||
@@ -113,8 +141,9 @@ public class ManagementServerPortUtils {
|
||||
return ((port == null)
|
||||
|| (serverProperties.getPort() == null && port.equals(8080))
|
||||
|| (port != 0 && port.equals(serverProperties.getPort())) ? SAME
|
||||
: DIFFERENT);
|
||||
: DIFFERENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -28,7 +28,7 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
/**
|
||||
* A {@link DiscoveryClient} that is composed of other discovery clients and delegates
|
||||
* calls to each of them in order.
|
||||
*
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@@ -49,7 +49,7 @@ public class CompositeDiscoveryClient implements DiscoveryClient {
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
if (this.discoveryClients != null) {
|
||||
for (DiscoveryClient discoveryClient : discoveryClients) {
|
||||
for (DiscoveryClient discoveryClient : this.discoveryClients) {
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
|
||||
if (instances != null && !instances.isEmpty()) {
|
||||
return instances;
|
||||
@@ -63,7 +63,7 @@ public class CompositeDiscoveryClient implements DiscoveryClient {
|
||||
public List<String> getServices() {
|
||||
LinkedHashSet<String> services = new LinkedHashSet<>();
|
||||
if (this.discoveryClients != null) {
|
||||
for (DiscoveryClient discoveryClient : discoveryClients) {
|
||||
for (DiscoveryClient discoveryClient : this.discoveryClients) {
|
||||
List<String> serviceForClient = discoveryClient.getServices();
|
||||
if (serviceForClient != null) {
|
||||
services.addAll(serviceForClient);
|
||||
@@ -74,6 +74,7 @@ public class CompositeDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
|
||||
public List<DiscoveryClient> getDiscoveryClients() {
|
||||
return discoveryClients;
|
||||
return this.discoveryClients;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.discovery.composite;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
|
||||
@@ -7,22 +25,21 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Auto-configuration for composite discovery client.
|
||||
*
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
|
||||
public class CompositeDiscoveryClientAutoConfiguration {
|
||||
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public CompositeDiscoveryClient compositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
|
||||
public CompositeDiscoveryClient compositeDiscoveryClient(
|
||||
List<DiscoveryClient> discoveryClients) {
|
||||
return new CompositeDiscoveryClient(discoveryClients);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ package org.springframework.cloud.client.discovery.event;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* An event that a DiscoveryClient implementation can broadcast if it supports
|
||||
* heartbeats from the discovery server. Provides listeners with a basic indication
|
||||
* of a state change in the service catalog.
|
||||
* An event that a DiscoveryClient implementation can broadcast if it supports heartbeats
|
||||
* from the discovery server. Provides listeners with a basic indication of a state change
|
||||
* in the service catalog.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
@@ -34,7 +34,6 @@ public class HeartbeatEvent extends ApplicationEvent {
|
||||
/**
|
||||
* Creates a new event with a source (for example, a discovery client) and a value.
|
||||
* Neither parameter should be relied on to have specific content or format.
|
||||
*
|
||||
* @param source The source of the event.
|
||||
* @param state The value indicating state of the catalog.
|
||||
*/
|
||||
@@ -46,10 +45,9 @@ public class HeartbeatEvent extends ApplicationEvent {
|
||||
/**
|
||||
* A value representing the state of the service catalog. The only requirement is that
|
||||
* it changes when the catalog is updated; it can be as simple as a version counter or
|
||||
* a hash. Implementations can provide information to help users visualize
|
||||
* what is going on in the catalog, but users should not rely on the content (since
|
||||
* the implementation of the underlying discovery might change).
|
||||
*
|
||||
* a hash. Implementations can provide information to help users visualize what is
|
||||
* going on in the catalog, but users should not rely on the content (since the
|
||||
* implementation of the underlying discovery might change).
|
||||
* @return A value representing state of the service catalog.
|
||||
*/
|
||||
public Object getValue() {
|
||||
|
||||
@@ -19,8 +19,8 @@ package org.springframework.cloud.client.discovery.event;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Helper class for listeners to the {@link HeartbeatEvent}, providing a convenient way
|
||||
* to determine if there has been a change in state.
|
||||
* Helper class for listeners to the {@link HeartbeatEvent}, providing a convenient way to
|
||||
* determine if there has been a change in state.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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.
|
||||
@@ -21,6 +21,7 @@ import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* An event to fire before a service is registered.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class InstancePreRegisteredEvent extends ApplicationEvent {
|
||||
@@ -29,8 +30,8 @@ public class InstancePreRegisteredEvent extends ApplicationEvent {
|
||||
|
||||
/**
|
||||
* Create a new pre registration event.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param registration the registration meta data
|
||||
*/
|
||||
public InstancePreRegisteredEvent(Object source, Registration registration) {
|
||||
super(source);
|
||||
@@ -42,6 +43,7 @@ public class InstancePreRegisteredEvent extends ApplicationEvent {
|
||||
* @return the registration data
|
||||
*/
|
||||
public Registration getRegistration() {
|
||||
return registration;
|
||||
return this.registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.context.ApplicationEvent;
|
||||
* discovery service.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @param <T> - type of configuration
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class InstanceRegisteredEvent<T> extends ApplicationEvent {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
@@ -29,23 +30,24 @@ import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator, Ordered,
|
||||
ApplicationListener<InstanceRegisteredEvent<?>> {
|
||||
|
||||
private AtomicBoolean discoveryInitialized = new AtomicBoolean(false);
|
||||
|
||||
private int order = Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
private final ObjectProvider<DiscoveryClient> discoveryClient;
|
||||
|
||||
private final DiscoveryClientHealthIndicatorProperties properties;
|
||||
|
||||
private final Log log = LogFactory.getLog(DiscoveryClientHealthIndicator.class);
|
||||
|
||||
public DiscoveryClientHealthIndicator(ObjectProvider<DiscoveryClient> discoveryClient, DiscoveryClientHealthIndicatorProperties properties) {
|
||||
private AtomicBoolean discoveryInitialized = new AtomicBoolean(false);
|
||||
|
||||
private int order = Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
public DiscoveryClientHealthIndicator(ObjectProvider<DiscoveryClient> discoveryClient,
|
||||
DiscoveryClientHealthIndicatorProperties properties) {
|
||||
this.discoveryClient = discoveryClient;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -53,7 +55,7 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator,
|
||||
@Override
|
||||
public void onApplicationEvent(InstanceRegisteredEvent<?> event) {
|
||||
if (this.discoveryInitialized.compareAndSet(false, true)) {
|
||||
log.debug("Discovery Client has been initialized");
|
||||
this.log.debug("Discovery Client has been initialized");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +67,13 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator,
|
||||
try {
|
||||
DiscoveryClient client = this.discoveryClient.getIfAvailable();
|
||||
List<String> services = client.getServices();
|
||||
String description = (this.properties.isIncludeDescription()) ? client.description() : "";
|
||||
builder.status(new Status("UP", description))
|
||||
.withDetail("services", services);
|
||||
String description = (this.properties.isIncludeDescription())
|
||||
? client.description() : "";
|
||||
builder.status(new Status("UP", description)).withDetail("services",
|
||||
services);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Error", e);
|
||||
this.log.error("Error", e);
|
||||
builder.down(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.discovery.health;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -13,7 +29,7 @@ public class DiscoveryClientHealthIndicatorProperties {
|
||||
private boolean includeDescription = false;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
@@ -21,7 +37,7 @@ public class DiscoveryClientHealthIndicatorProperties {
|
||||
}
|
||||
|
||||
public boolean isIncludeDescription() {
|
||||
return includeDescription;
|
||||
return this.includeDescription;
|
||||
}
|
||||
|
||||
public void setIncludeDescription(boolean includeDescription) {
|
||||
@@ -30,10 +46,12 @@ public class DiscoveryClientHealthIndicatorProperties {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("DiscoveryClientHealthIndicatorProperties{");
|
||||
sb.append("enabled=").append(enabled);
|
||||
sb.append(", includeDescription=").append(includeDescription);
|
||||
final StringBuffer sb = new StringBuffer(
|
||||
"DiscoveryClientHealthIndicatorProperties{");
|
||||
sb.append("enabled=").append(this.enabled);
|
||||
sb.append(", includeDescription=").append(this.includeDescription);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,11 +26,12 @@ import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
|
||||
/**
|
||||
* Gathers all instances of DiscoveryHealthIndicator from a DiscoveryClient
|
||||
* implementation and aggregates the statuses.
|
||||
* Gathers all instances of DiscoveryHealthIndicator from a DiscoveryClient implementation
|
||||
* and aggregates the statuses.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
//TODO: do we need this? Can they just be independent HealthIndicators?
|
||||
// TODO: do we need this? Can they just be independent HealthIndicators?
|
||||
public class DiscoveryCompositeHealthIndicator extends CompositeHealthIndicator {
|
||||
|
||||
private final ArrayList<Holder> healthIndicators = new ArrayList<>();
|
||||
@@ -42,15 +43,19 @@ public class DiscoveryCompositeHealthIndicator extends CompositeHealthIndicator
|
||||
for (DiscoveryHealthIndicator indicator : indicators) {
|
||||
Holder holder = new Holder(indicator);
|
||||
addHealthIndicator(indicator.getName(), holder);
|
||||
healthIndicators.add(holder);
|
||||
this.healthIndicators.add(holder);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Holder> getHealthIndicators() {
|
||||
return healthIndicators;
|
||||
return this.healthIndicators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holder for the Health Indicator.
|
||||
*/
|
||||
public static class Holder implements HealthIndicator {
|
||||
|
||||
private DiscoveryHealthIndicator delegate;
|
||||
|
||||
public Holder(DiscoveryHealthIndicator delegate) {
|
||||
@@ -63,8 +68,9 @@ public class DiscoveryCompositeHealthIndicator extends CompositeHealthIndicator
|
||||
}
|
||||
|
||||
public DiscoveryHealthIndicator getDelegate() {
|
||||
return delegate;
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.boot.actuate.health.Health;
|
||||
|
||||
/**
|
||||
* A health indicator interface specific to a DiscoveryClient implementation.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface DiscoveryHealthIndicator {
|
||||
|
||||
@@ -25,8 +25,9 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
/**
|
||||
* DiscoveryClient used when no implementations are found on the classpath.
|
||||
*
|
||||
* @deprecated Use {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClient instead}.
|
||||
*
|
||||
* @deprecated Use
|
||||
* {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClient
|
||||
* instead}.
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@@ -39,10 +40,9 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated Use
|
||||
* {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration instead}.
|
||||
*
|
||||
* {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration
|
||||
* instead}.
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@@ -52,6 +52,8 @@ import org.springframework.core.env.Environment;
|
||||
public class NoopDiscoveryClientAutoConfiguration
|
||||
implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private final Log log = LogFactory.getLog(NoopDiscoveryClientAutoConfiguration.class);
|
||||
|
||||
@Autowired(required = false)
|
||||
private ServerProperties server;
|
||||
|
||||
@@ -66,8 +68,6 @@ public class NoopDiscoveryClientAutoConfiguration
|
||||
|
||||
private DefaultServiceInstance serviceInstance;
|
||||
|
||||
private final Log log = LogFactory.getLog(NoopDiscoveryClientAutoConfiguration.class);
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
String host = "localhost";
|
||||
@@ -75,7 +75,7 @@ public class NoopDiscoveryClientAutoConfiguration
|
||||
host = InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
log.warn("Cannot get host info: (" + e.getMessage() + ")");
|
||||
this.log.warn("Cannot get host info: (" + e.getMessage() + ")");
|
||||
}
|
||||
int port = findPort();
|
||||
this.serviceInstance = new DefaultServiceInstance(
|
||||
@@ -96,8 +96,8 @@ public class NoopDiscoveryClientAutoConfiguration
|
||||
}
|
||||
else {
|
||||
// Apparently spring-web is not on the classpath
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug(
|
||||
"Could not locate port in embedded container (spring-web not available)");
|
||||
}
|
||||
}
|
||||
@@ -109,18 +109,21 @@ public class NoopDiscoveryClientAutoConfiguration
|
||||
this.context.publishEvent(new InstanceRegisteredEvent<>(this, this.environment));
|
||||
}
|
||||
|
||||
private interface PortFinder {
|
||||
Integer findPort();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient discoveryClient() {
|
||||
return new NoopDiscoveryClient(this.serviceInstance);
|
||||
}
|
||||
|
||||
private interface PortFinder {
|
||||
|
||||
Integer findPort();
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(name = {"org.springframework.web.context.support.GenericWebApplicationContext",
|
||||
"org.springframework.boot.context.embedded.EmbeddedWebApplicationContext"})
|
||||
@ConditionalOnClass(name = {
|
||||
"org.springframework.web.context.support.GenericWebApplicationContext",
|
||||
"org.springframework.boot.context.embedded.EmbeddedWebApplicationContext" })
|
||||
protected static class Boot15PortFinderConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -129,16 +132,18 @@ public class NoopDiscoveryClientAutoConfiguration
|
||||
@Override
|
||||
public Integer findPort() {
|
||||
// TODO: support reactive
|
||||
/*if (context instanceof EmbeddedWebApplicationContext) {
|
||||
EmbeddedServletContainer container = ((EmbeddedWebApplicationContext) context)
|
||||
.getEmbeddedServletContainer();
|
||||
if (container != null) {
|
||||
return container.getPort();
|
||||
}
|
||||
}*/
|
||||
/*
|
||||
* if (context instanceof EmbeddedWebApplicationContext) {
|
||||
* EmbeddedServletContainer container =
|
||||
* ((EmbeddedWebApplicationContext) context)
|
||||
* .getEmbeddedServletContainer(); if (container != null) { return
|
||||
* container.getPort(); } }
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -64,4 +64,5 @@ public class SimpleDiscoveryClient implements DiscoveryClient {
|
||||
public int getOrder() {
|
||||
return this.simpleDiscoveryProperties.getOrder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.discovery.simple;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
// import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
// import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
@@ -14,9 +30,9 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.net.URI;
|
||||
// import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
// import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
|
||||
/**
|
||||
* Spring Boot auto-configuration for simple properties-based discovery client.
|
||||
@@ -58,18 +74,15 @@ public class SimpleDiscoveryClientAutoConfiguration {
|
||||
}
|
||||
|
||||
private int findPort() {
|
||||
//FIXME: is what is the boot 2.0 equiv?
|
||||
/*if (ClassUtils.isPresent(
|
||||
"org.springframework.boot.context.embedded.EmbeddedWebApplicationContext",
|
||||
null)) {
|
||||
if (this.context instanceof EmbeddedWebApplicationContext) {
|
||||
EmbeddedServletContainer container = ((EmbeddedWebApplicationContext) this.context)
|
||||
.getEmbeddedServletContainer();
|
||||
if (container != null) {
|
||||
return container.getPort();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// FIXME: is what is the boot 2.0 equiv?
|
||||
/*
|
||||
* if (ClassUtils.isPresent(
|
||||
* "org.springframework.boot.context.embedded.EmbeddedWebApplicationContext",
|
||||
* null)) { if (this.context instanceof EmbeddedWebApplicationContext) {
|
||||
* EmbeddedServletContainer container = ((EmbeddedWebApplicationContext)
|
||||
* this.context) .getEmbeddedServletContainer(); if (container != null) { return
|
||||
* container.getPort(); } } }
|
||||
*/
|
||||
if (this.server != null && this.server.getPort() != null
|
||||
&& this.server.getPort() > 0) {
|
||||
return this.server.getPort();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -31,10 +31,9 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
/**
|
||||
* Properties to hold the details of a
|
||||
* {@link org.springframework.cloud.client.discovery.DiscoveryClient} service instances
|
||||
* for a given service.
|
||||
* It also holds the user-configurable order that will be used to establish the
|
||||
* precedence of this client in the list of clients
|
||||
* used by {@link org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient}.
|
||||
* for a given service. It also holds the user-configurable order that will be used to
|
||||
* establish the precedence of this client in the list of clients used by
|
||||
* {@link org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient}.
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
@@ -43,6 +42,7 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
@ConfigurationProperties(prefix = "spring.cloud.discovery.client.simple")
|
||||
public class SimpleDiscoveryProperties {
|
||||
|
||||
private Map<String, List<SimpleServiceInstance>> instances = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -83,25 +83,34 @@ public class SimpleDiscoveryProperties {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic implementation of {@link ServiceInstance}.
|
||||
*/
|
||||
public static class SimpleServiceInstance implements ServiceInstance {
|
||||
|
||||
/**
|
||||
* The URI of the service instance. Will be parsed to extract the scheme, host,
|
||||
* and port.
|
||||
* and port.
|
||||
*/
|
||||
private URI uri;
|
||||
|
||||
private String host;
|
||||
|
||||
private int port;
|
||||
|
||||
private boolean secure;
|
||||
|
||||
/**
|
||||
* Metadata for the service instance. Can be used by discovery clients to modify
|
||||
* their behaviour per instance, e.g. when load balancing.
|
||||
*/
|
||||
private Map<String, String> metadata = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* The unique identifier or name for the service instance.
|
||||
*/
|
||||
private String instanceId;
|
||||
|
||||
/**
|
||||
* The identifier or name for the service. Multiple instances might share the same
|
||||
* service ID.
|
||||
@@ -115,16 +124,6 @@ public class SimpleDiscoveryProperties {
|
||||
setUri(uri);
|
||||
}
|
||||
|
||||
public void setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
this.host = this.uri.getHost();
|
||||
this.port = this.uri.getPort();
|
||||
String scheme = this.uri.getScheme();
|
||||
if ("https".equals(scheme)) {
|
||||
this.secure = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceId() {
|
||||
return this.instanceId;
|
||||
@@ -163,9 +162,21 @@ public class SimpleDiscoveryProperties {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public void setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
this.host = this.uri.getHost();
|
||||
this.port = this.uri.getPort();
|
||||
String scheme = this.uri.getScheme();
|
||||
if ("https".equals(scheme)) {
|
||||
this.secure = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,8 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -29,9 +29,10 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Registers a default {@link RemoteResourceRefresher} if at least one {@link RemoteResource} is declared in the system.
|
||||
* Applies verification timings defined in the application properties.
|
||||
*
|
||||
* Registers a default {@link RemoteResourceRefresher} if at least one
|
||||
* {@link RemoteResource} is declared in the system. Applies verification timings defined
|
||||
* in the application properties.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
@@ -39,36 +40,47 @@ import org.springframework.context.annotation.Configuration;
|
||||
@EnableConfigurationProperties(CloudHypermediaProperties.class)
|
||||
public class CloudHypermediaAutoConfiguration {
|
||||
|
||||
@Autowired(required = false) List<RemoteResource> discoveredResources = Collections.emptyList();
|
||||
@Autowired CloudHypermediaProperties properties;
|
||||
@Autowired(required = false)
|
||||
List<RemoteResource> discoveredResources = Collections.emptyList();
|
||||
|
||||
@Autowired
|
||||
CloudHypermediaProperties properties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RemoteResourceRefresher discoveredResourceRefresher() {
|
||||
return new RemoteResourceRefresher(discoveredResources, properties.getRefresh().getFixedDelay(),
|
||||
properties.getRefresh().getInitialDelay());
|
||||
return new RemoteResourceRefresher(this.discoveredResources,
|
||||
this.properties.getRefresh().getFixedDelay(),
|
||||
this.properties.getRefresh().getInitialDelay());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for Cloud hypermedia.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.cloud.hypermedia")
|
||||
public static class CloudHypermediaProperties {
|
||||
|
||||
private Refresh refresh = new Refresh();
|
||||
|
||||
public Refresh getRefresh() {
|
||||
return refresh;
|
||||
return this.refresh;
|
||||
}
|
||||
|
||||
public void setRefresh(Refresh refresh) {
|
||||
this.refresh = refresh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for Cloud hypermedia refresh.
|
||||
*/
|
||||
public static class Refresh {
|
||||
|
||||
private int fixedDelay = 5000;
|
||||
|
||||
private int initialDelay = 10000;
|
||||
|
||||
public int getFixedDelay() {
|
||||
return fixedDelay;
|
||||
return this.fixedDelay;
|
||||
}
|
||||
|
||||
public void setFixedDelay(int fixedDelay) {
|
||||
@@ -76,12 +88,15 @@ public class CloudHypermediaAutoConfiguration {
|
||||
}
|
||||
|
||||
public int getInitialDelay() {
|
||||
return initialDelay;
|
||||
return this.initialDelay;
|
||||
}
|
||||
|
||||
public void setInitialDelay(int initialDelay) {
|
||||
this.initialDelay = initialDelay;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,12 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
@@ -29,51 +31,55 @@ import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* A REST resource that is defined by a service reference and a traversal operation within that service.
|
||||
* A REST resource that is defined by a service reference and a traversal operation within
|
||||
* that service.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DiscoveredResource implements RemoteResource {
|
||||
|
||||
private final ServiceInstanceProvider provider;
|
||||
private final TraversalDefinition traversal;
|
||||
|
||||
|
||||
private RestOperations restOperations = new RestTemplate();
|
||||
private Link link = null;
|
||||
private final TraversalDefinition traversal;
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(DiscoveredResource.class);
|
||||
|
||||
private RestOperations restOperations = new RestTemplate();
|
||||
|
||||
public DiscoveredResource(ServiceInstanceProvider provider, TraversalDefinition traversal) {
|
||||
private Link link = null;
|
||||
|
||||
public DiscoveredResource(ServiceInstanceProvider provider,
|
||||
TraversalDefinition traversal) {
|
||||
this.provider = provider;
|
||||
this.traversal = traversal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link RestOperations} to use to execute the traversal and verifying HEAD calls.
|
||||
*
|
||||
* @param restOperations Can be {@literal null}; resorts to a default {@link RestTemplate} in that case.
|
||||
*/
|
||||
public void setRestOperations(RestOperations restOperations) {
|
||||
this.restOperations = restOperations == null ? new RestTemplate() : restOperations;
|
||||
}
|
||||
|
||||
public ServiceInstanceProvider getProvider() {
|
||||
return provider;
|
||||
return this.provider;
|
||||
}
|
||||
|
||||
public TraversalDefinition getTraversal() {
|
||||
return traversal;
|
||||
return this.traversal;
|
||||
}
|
||||
|
||||
public RestOperations getRestOperations() {
|
||||
return restOperations;
|
||||
return this.restOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link RestOperations} to use to execute the traversal and verifying
|
||||
* HEAD calls.
|
||||
* @param restOperations Can be {@literal null}; resorts to a default
|
||||
* {@link RestTemplate} in that case.
|
||||
*/
|
||||
public void setRestOperations(RestOperations restOperations) {
|
||||
this.restOperations = restOperations == null ? new RestTemplate()
|
||||
: restOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Link getLink() {
|
||||
return link;
|
||||
return this.link;
|
||||
}
|
||||
|
||||
public void setLink(Link link) {
|
||||
@@ -84,14 +90,13 @@ public class DiscoveredResource implements RemoteResource {
|
||||
* Verifies the link to the current.
|
||||
*/
|
||||
public void verifyOrDiscover() {
|
||||
this.link = link == null ? discoverLink() : verify(link);
|
||||
this.link = this.link == null ? discoverLink() : verify(this.link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the given {@link Link} by issuing an HTTP HEAD request to the resource.
|
||||
*
|
||||
* @param link Must not be {@literal null}.
|
||||
* @return
|
||||
* @return - link to the resource
|
||||
*/
|
||||
private Link verify(Link link) {
|
||||
|
||||
@@ -101,15 +106,16 @@ public class DiscoveredResource implements RemoteResource {
|
||||
|
||||
String uri = link.expand().getHref();
|
||||
|
||||
log.debug("Verifying link pointing to {}…", uri);
|
||||
restOperations.headForHeaders(uri);
|
||||
log.debug("Successfully verified link!");
|
||||
this.log.debug("Verifying link pointing to {}…", uri);
|
||||
this.restOperations.headForHeaders(uri);
|
||||
this.log.debug("Successfully verified link!");
|
||||
|
||||
return link;
|
||||
|
||||
} catch (RestClientException o_O) {
|
||||
}
|
||||
catch (RestClientException o_O) {
|
||||
|
||||
log.debug("Verification failed, marking as outdated!");
|
||||
this.log.debug("Verification failed, marking as outdated!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +124,7 @@ public class DiscoveredResource implements RemoteResource {
|
||||
|
||||
try {
|
||||
|
||||
ServiceInstance service = provider.getServiceInstance();
|
||||
ServiceInstance service = this.provider.getServiceInstance();
|
||||
|
||||
if (service == null) {
|
||||
return null;
|
||||
@@ -127,21 +133,24 @@ public class DiscoveredResource implements RemoteResource {
|
||||
URI uri = service.getUri();
|
||||
String serviceId = service.getServiceId();
|
||||
|
||||
log.debug("Discovered {} system at {}. Discovering resource…", serviceId, uri);
|
||||
this.log.debug("Discovered {} system at {}. Discovering resource…", serviceId,
|
||||
uri);
|
||||
|
||||
Traverson traverson = new Traverson(uri, MediaTypes.HAL_JSON);
|
||||
Link link = traversal.buildTraversal(traverson).asTemplatedLink();
|
||||
Link link = this.traversal.buildTraversal(traverson).asTemplatedLink();
|
||||
|
||||
log.debug("Found link pointing to {}.", link.getHref());
|
||||
this.log.debug("Found link pointing to {}.", link.getHref());
|
||||
|
||||
return link;
|
||||
|
||||
} catch (RuntimeException o_O) {
|
||||
}
|
||||
catch (RuntimeException o_O) {
|
||||
|
||||
this.link = null;
|
||||
log.debug("Target system unavailable. Got: ", o_O.getMessage());
|
||||
this.log.debug("Target system unavailable. Got: ", o_O.getMessage());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import java.util.List;
|
||||
@@ -21,14 +22,16 @@ import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
/**
|
||||
* {@link ServiceInstanceProvider} to work with a {@link DiscoveryClient} to look up a service by name. Picks the
|
||||
* first one returned by the configured {@link DiscoveryClient}.
|
||||
*
|
||||
* {@link ServiceInstanceProvider} to work with a {@link DiscoveryClient} to look up a
|
||||
* service by name. Picks the first one returned by the configured
|
||||
* {@link DiscoveryClient}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DynamicServiceInstanceProvider implements ServiceInstanceProvider {
|
||||
|
||||
private final DiscoveryClient client;
|
||||
|
||||
private final String serviceName;
|
||||
|
||||
public DynamicServiceInstanceProvider(DiscoveryClient client, String serviceName) {
|
||||
@@ -36,20 +39,23 @@ public class DynamicServiceInstanceProvider implements ServiceInstanceProvider {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
|
||||
*/
|
||||
@Override
|
||||
public ServiceInstance getServiceInstance() {
|
||||
|
||||
try {
|
||||
|
||||
List<ServiceInstance> instances = client.getInstances(serviceName);
|
||||
List<ServiceInstance> instances = this.client.getInstances(this.serviceName);
|
||||
return instances.isEmpty() ? null : instances.get(0);
|
||||
|
||||
} catch (RuntimeException o_O) {
|
||||
}
|
||||
catch (RuntimeException o_O) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import org.springframework.hateoas.Link;
|
||||
@@ -25,15 +26,17 @@ import org.springframework.hateoas.Link;
|
||||
public interface RemoteResource {
|
||||
|
||||
/**
|
||||
* Returns the {@link Link} to the resource if it is available, or {@literal null}
|
||||
* if it is gone (i.e. it either is generally unavailable or can't be discovered).
|
||||
* Returns the {@link Link} to the resource if it is available, or {@literal null} if
|
||||
* it is gone (i.e. it either is generally unavailable or can't be discovered).
|
||||
* @return a link to the resource.
|
||||
*/
|
||||
Link getLink();
|
||||
|
||||
/**
|
||||
* Discovers the resource if it hasn't been discovered yet or has become
|
||||
* unavailable. If a link has been discovered previously, it is verified and either
|
||||
* confirmed or removed to indicate that it's not available anymore.
|
||||
* Discovers the resource if it hasn't been discovered yet or has become unavailable.
|
||||
* If a link has been discovered previously, it is verified and either confirmed or
|
||||
* removed to indicate that it's not available anymore.
|
||||
*/
|
||||
void verifyOrDiscover();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import java.util.List;
|
||||
@@ -22,39 +23,46 @@ import org.springframework.scheduling.config.IntervalTask;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
|
||||
/**
|
||||
* A {@link ScheduledTaskRegistrar} that verifies all {@link DiscoveredResource} instances in the system, based
|
||||
* on the given timing configuration.
|
||||
*
|
||||
* A {@link ScheduledTaskRegistrar} that verifies all {@link DiscoveredResource} instances
|
||||
* in the system, based on the given timing configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class RemoteResourceRefresher extends ContextLifecycleScheduledTaskRegistrar {
|
||||
|
||||
private final List<RemoteResource> discoveredResources;
|
||||
private final int fixedDelay, initialDelay;
|
||||
|
||||
public RemoteResourceRefresher(List<RemoteResource> discoveredResources, int fixedDelay, int initialDelay) {
|
||||
private final int fixedDelay;
|
||||
|
||||
private final int initialDelay;
|
||||
|
||||
public RemoteResourceRefresher(List<RemoteResource> discoveredResources,
|
||||
int fixedDelay, int initialDelay) {
|
||||
this.discoveredResources = discoveredResources;
|
||||
this.fixedDelay = fixedDelay;
|
||||
this.initialDelay = initialDelay;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar#afterPropertiesSet()
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar#
|
||||
* afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
for (final RemoteResource resource : discoveredResources) {
|
||||
for (final RemoteResource resource : this.discoveredResources) {
|
||||
addFixedDelayTask(new IntervalTask(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
resource.verifyOrDiscover();
|
||||
}
|
||||
}, fixedDelay, initialDelay));
|
||||
}, this.fixedDelay, this.initialDelay));
|
||||
}
|
||||
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,22 +13,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* A component that will provide a {@link ServiceInstance}, or can express the absence of one by
|
||||
* returning {@literal null}.
|
||||
*
|
||||
* A component that will provide a {@link ServiceInstance}, or can express the absence of
|
||||
* one by returning {@literal null}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface ServiceInstanceProvider {
|
||||
|
||||
/**
|
||||
* Returns the service instance or {@literal null} if the service is currently unavailable.
|
||||
*
|
||||
* @return The service instance, or {@literal null} if the service is currently unavailable.
|
||||
* Returns the service instance or {@literal null} if the service is currently
|
||||
* unavailable.
|
||||
* @return The service instance, or {@literal null} if the service is currently
|
||||
* unavailable.
|
||||
*/
|
||||
ServiceInstance getServiceInstance();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,13 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* A {@link ServiceInstanceProvider} that will always return the configured {@link ServiceInstance}.
|
||||
*
|
||||
* A {@link ServiceInstanceProvider} that will always return the configured
|
||||
* {@link ServiceInstance}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class StaticServiceInstanceProvider implements ServiceInstanceProvider {
|
||||
@@ -30,12 +32,14 @@ public class StaticServiceInstanceProvider implements ServiceInstanceProvider {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
|
||||
*/
|
||||
@Override
|
||||
public ServiceInstance getServiceInstance() {
|
||||
return instance;
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.hypermedia;
|
||||
|
||||
import org.springframework.hateoas.client.Traverson;
|
||||
@@ -27,6 +28,8 @@ public interface TraversalDefinition {
|
||||
|
||||
/**
|
||||
* @param traverson The Traverson instance to run the traversal on.
|
||||
* @return the builder for traversing
|
||||
*/
|
||||
TraversalBuilder buildTraversal(Traverson traverson);
|
||||
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ import org.springframework.web.client.AsyncRestTemplate;
|
||||
@ConditionalOnClass(AsyncRestTemplate.class)
|
||||
public class AsyncLoadBalancerAutoConfiguration {
|
||||
|
||||
|
||||
@Configuration
|
||||
static class AsyncRestTemplateCustomizerConfig {
|
||||
|
||||
@LoadBalanced
|
||||
@Autowired(required = false)
|
||||
private List<AsyncRestTemplate> restTemplates = Collections.emptyList();
|
||||
@@ -60,12 +60,15 @@ public class AsyncLoadBalancerAutoConfiguration {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class LoadBalancerInterceptorConfig {
|
||||
|
||||
@Bean
|
||||
public AsyncLoadBalancerInterceptor asyncLoadBalancerInterceptor(LoadBalancerClient loadBalancerClient) {
|
||||
public AsyncLoadBalancerInterceptor asyncLoadBalancerInterceptor(
|
||||
LoadBalancerClient loadBalancerClient) {
|
||||
return new AsyncLoadBalancerInterceptor(loadBalancerClient);
|
||||
}
|
||||
|
||||
@@ -82,5 +85,7 @@ public class AsyncLoadBalancerAutoConfiguration {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.AsyncClientHttpRequestExecution;
|
||||
@@ -23,9 +26,6 @@ import org.springframework.http.client.AsyncClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
@@ -38,21 +38,22 @@ public class AsyncLoadBalancerInterceptor implements AsyncClientHttpRequestInter
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<ClientHttpResponse> intercept(final HttpRequest request, final byte[] body,
|
||||
final AsyncClientHttpRequestExecution execution) throws IOException {
|
||||
public ListenableFuture<ClientHttpResponse> intercept(final HttpRequest request,
|
||||
final byte[] body, final AsyncClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
final URI originalUri = request.getURI();
|
||||
String serviceName = originalUri.getHost();
|
||||
return this.loadBalancer.execute(serviceName,
|
||||
new LoadBalancerRequest<ListenableFuture<ClientHttpResponse>>() {
|
||||
@Override
|
||||
public ListenableFuture<ClientHttpResponse> apply(final ServiceInstance instance)
|
||||
throws Exception {
|
||||
public ListenableFuture<ClientHttpResponse> apply(
|
||||
final ServiceInstance instance) throws Exception {
|
||||
HttpRequest serviceRequest = new ServiceRequestWrapper(request,
|
||||
instance, loadBalancer);
|
||||
instance, AsyncLoadBalancerInterceptor.this.loadBalancer);
|
||||
return execution.executeAsync(serviceRequest, body);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.web.client.AsyncRestTemplate;
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
public interface AsyncRestTemplateCustomizer {
|
||||
void customize(AsyncRestTemplate restTemplate);
|
||||
}
|
||||
|
||||
void customize(AsyncRestTemplate restTemplate);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,72 +13,81 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.client.AbstractClientHttpResponse;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
/**
|
||||
* {@link RetryableStatusCodeException} that captures a {@link ClientHttpResponse}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class ClientHttpResponseStatusCodeException extends RetryableStatusCodeException {
|
||||
|
||||
private ClientHttpResponseWrapper response;
|
||||
private final ClientHttpResponseWrapper response;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param serviceId The service ID.
|
||||
* @param response The response object.
|
||||
* @throws IOException Thrown if the {@link ClientHttpResponse} response code cannot be retrieved.
|
||||
* @param body The response body.
|
||||
* @throws IOException Thrown if the {@link ClientHttpResponse} response code cannot
|
||||
* be retrieved.
|
||||
*/
|
||||
public ClientHttpResponseStatusCodeException(String serviceId, ClientHttpResponse response, byte[] body) throws IOException {
|
||||
public ClientHttpResponseStatusCodeException(String serviceId,
|
||||
ClientHttpResponse response, byte[] body) throws IOException {
|
||||
super(serviceId, response.getRawStatusCode(), response, null);
|
||||
this.response = new ClientHttpResponseWrapper(response, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse getResponse() {
|
||||
return response;
|
||||
return this.response;
|
||||
}
|
||||
|
||||
static class ClientHttpResponseWrapper extends AbstractClientHttpResponse {
|
||||
|
||||
private ClientHttpResponse response;
|
||||
|
||||
private byte[] body;
|
||||
|
||||
public ClientHttpResponseWrapper(ClientHttpResponse response, byte[] body) {
|
||||
ClientHttpResponseWrapper(ClientHttpResponse response, byte[] body) {
|
||||
this.response = response;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() throws IOException {
|
||||
return response.getRawStatusCode();
|
||||
return this.response.getRawStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return response.getStatusText();
|
||||
return this.response.getStatusText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
response.close();
|
||||
this.response.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
return new ByteArrayInputStream(body);
|
||||
return new ByteArrayInputStream(this.body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return response.getHeaders();
|
||||
return this.response.getHeaders();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.http.HttpRequest;
|
||||
@@ -20,83 +21,99 @@ import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.RetryPolicy;
|
||||
|
||||
/**
|
||||
* {@link RetryPolicy} used by the {@link LoadBalancerClient} when retrying failed requests.
|
||||
* {@link RetryPolicy} used by the {@link LoadBalancerClient} when retrying failed
|
||||
* requests.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class InterceptorRetryPolicy implements RetryPolicy {
|
||||
|
||||
private HttpRequest request;
|
||||
private LoadBalancedRetryPolicy policy;
|
||||
private ServiceInstanceChooser serviceInstanceChooser;
|
||||
private String serviceName;
|
||||
private HttpRequest request;
|
||||
|
||||
/**
|
||||
* Creates a new retry policy.
|
||||
* @param request The request that will be retried.
|
||||
* @param policy The retry policy from the load balancer.
|
||||
* @param serviceInstanceChooser The load balancer client.
|
||||
* @param serviceName The name of the service.
|
||||
*/
|
||||
public InterceptorRetryPolicy(HttpRequest request, LoadBalancedRetryPolicy policy,
|
||||
ServiceInstanceChooser serviceInstanceChooser, String serviceName) {
|
||||
this.request = request;
|
||||
this.policy = policy;
|
||||
this.serviceInstanceChooser = serviceInstanceChooser;
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
private LoadBalancedRetryPolicy policy;
|
||||
|
||||
@Override
|
||||
public boolean canRetry(RetryContext context) {
|
||||
LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext)context;
|
||||
if(lbContext.getRetryCount() == 0 && lbContext.getServiceInstance() == null) {
|
||||
//We haven't even tried to make the request yet so return true so we do
|
||||
lbContext.setServiceInstance(serviceInstanceChooser.choose(serviceName));
|
||||
return true;
|
||||
}
|
||||
return policy.canRetryNextServer(lbContext);
|
||||
}
|
||||
private ServiceInstanceChooser serviceInstanceChooser;
|
||||
|
||||
@Override
|
||||
public RetryContext open(RetryContext parent) {
|
||||
return new LoadBalancedRetryContext(parent, request);
|
||||
}
|
||||
private String serviceName;
|
||||
|
||||
/**
|
||||
* Creates a new retry policy.
|
||||
* @param request The request that will be retried.
|
||||
* @param policy The retry policy from the load balancer.
|
||||
* @param serviceInstanceChooser The load balancer client.
|
||||
* @param serviceName The name of the service.
|
||||
*/
|
||||
public InterceptorRetryPolicy(HttpRequest request, LoadBalancedRetryPolicy policy,
|
||||
ServiceInstanceChooser serviceInstanceChooser, String serviceName) {
|
||||
this.request = request;
|
||||
this.policy = policy;
|
||||
this.serviceInstanceChooser = serviceInstanceChooser;
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(RetryContext context) {
|
||||
policy.close((LoadBalancedRetryContext)context);
|
||||
}
|
||||
@Override
|
||||
public boolean canRetry(RetryContext context) {
|
||||
LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext) context;
|
||||
if (lbContext.getRetryCount() == 0 && lbContext.getServiceInstance() == null) {
|
||||
// We haven't even tried to make the request yet so return true so we do
|
||||
lbContext.setServiceInstance(
|
||||
this.serviceInstanceChooser.choose(this.serviceName));
|
||||
return true;
|
||||
}
|
||||
return this.policy.canRetryNextServer(lbContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RetryContext open(RetryContext parent) {
|
||||
return new LoadBalancedRetryContext(parent, this.request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerThrowable(RetryContext context, Throwable throwable) {
|
||||
LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext) context;
|
||||
//this is important as it registers the last exception in the context and also increases the retry count
|
||||
lbContext.registerThrowable(throwable);
|
||||
//let the policy know about the exception as well
|
||||
policy.registerThrowable(lbContext, throwable);
|
||||
}
|
||||
@Override
|
||||
public void close(RetryContext context) {
|
||||
this.policy.close((LoadBalancedRetryContext) context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
@Override
|
||||
public void registerThrowable(RetryContext context, Throwable throwable) {
|
||||
LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext) context;
|
||||
// this is important as it registers the last exception in the context and also
|
||||
// increases the retry count
|
||||
lbContext.registerThrowable(throwable);
|
||||
// let the policy know about the exception as well
|
||||
this.policy.registerThrowable(lbContext, throwable);
|
||||
}
|
||||
|
||||
InterceptorRetryPolicy that = (InterceptorRetryPolicy) o;
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!request.equals(that.request)) return false;
|
||||
if (!policy.equals(that.policy)) return false;
|
||||
if (!serviceInstanceChooser.equals(that.serviceInstanceChooser)) return false;
|
||||
return serviceName.equals(that.serviceName);
|
||||
InterceptorRetryPolicy that = (InterceptorRetryPolicy) o;
|
||||
|
||||
}
|
||||
if (!this.request.equals(that.request)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.policy.equals(that.policy)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.serviceInstanceChooser.equals(that.serviceInstanceChooser)) {
|
||||
return false;
|
||||
}
|
||||
return this.serviceName.equals(that.serviceName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.request.hashCode();
|
||||
result = 31 * result + this.policy.hashCode();
|
||||
result = 31 * result + this.serviceInstanceChooser.hashCode();
|
||||
result = 31 * result + this.serviceName.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = request.hashCode();
|
||||
result = 31 * result + policy.hashCode();
|
||||
result = 31 * result + serviceInstanceChooser.hashCode();
|
||||
result = 31 * result + serviceName.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
@@ -25,6 +23,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
/**
|
||||
* Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient.
|
||||
* @author Spencer Gibb
|
||||
@@ -35,4 +35,5 @@ import java.lang.annotation.Target;
|
||||
@Inherited
|
||||
@Qualifier
|
||||
public @interface LoadBalanced {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,18 +13,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.retry.RecoveryCallback;
|
||||
import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.RetryException;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* An implementation of {@link RecoveryCallback} which relies on an implementation
|
||||
* of {@link RetryableStatusCodeException} to contain the last response object from
|
||||
* the request.
|
||||
* An implementation of {@link RecoveryCallback} which relies on an implementation of
|
||||
* {@link RetryableStatusCodeException} to contain the last response object from the
|
||||
* request.
|
||||
*
|
||||
* @param <T> - response type to return
|
||||
* @param <R> - response type from the HTTP client
|
||||
* @author LiYuan Lee
|
||||
*/
|
||||
public abstract class LoadBalancedRecoveryCallback<T, R> implements RecoveryCallback<T> {
|
||||
@@ -44,10 +48,12 @@ public abstract class LoadBalancedRecoveryCallback<T, R> implements RecoveryCall
|
||||
if (lastThrowable instanceof RetryableStatusCodeException) {
|
||||
RetryableStatusCodeException ex = (RetryableStatusCodeException) lastThrowable;
|
||||
return createResponse((R) ex.getResponse(), ex.getUri());
|
||||
} else if (lastThrowable instanceof Exception){
|
||||
throw (Exception)lastThrowable;
|
||||
}
|
||||
else if (lastThrowable instanceof Exception) {
|
||||
throw (Exception) lastThrowable;
|
||||
}
|
||||
}
|
||||
throw new RetryException("Could not recover", lastThrowable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
@@ -22,52 +23,55 @@ import org.springframework.retry.context.RetryContextSupport;
|
||||
|
||||
/**
|
||||
* {@link RetryContext} for load-balanced retries.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class LoadBalancedRetryContext extends RetryContextSupport {
|
||||
|
||||
private HttpRequest request;
|
||||
private ServiceInstance serviceInstance;
|
||||
private HttpRequest request;
|
||||
|
||||
/**
|
||||
* Creates a new load-balanced context.
|
||||
* @param parent The parent context.
|
||||
* @param request The request that is being load-balanced.
|
||||
*/
|
||||
public LoadBalancedRetryContext(RetryContext parent, HttpRequest request) {
|
||||
super(parent);
|
||||
this.request = request;
|
||||
}
|
||||
private ServiceInstance serviceInstance;
|
||||
|
||||
/**
|
||||
* Gets the request that is being load-balanced.
|
||||
* @return The request that is being load-balanced.
|
||||
*/
|
||||
public HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
/**
|
||||
* Creates a new load-balanced context.
|
||||
* @param parent The parent context.
|
||||
* @param request The request that is being load-balanced.
|
||||
*/
|
||||
public LoadBalancedRetryContext(RetryContext parent, HttpRequest request) {
|
||||
super(parent);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request that is being load-balanced.
|
||||
* @param request The request to be load balanced.
|
||||
*/
|
||||
public void setRequest(HttpRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
/**
|
||||
* Gets the request that is being load-balanced.
|
||||
* @return The request that is being load-balanced.
|
||||
*/
|
||||
public HttpRequest getRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service instance used during the retry.
|
||||
* @return The service instance used during the retry.
|
||||
*/
|
||||
public ServiceInstance getServiceInstance() {
|
||||
return serviceInstance;
|
||||
}
|
||||
/**
|
||||
* Sets the request that is being load-balanced.
|
||||
* @param request The request to be load balanced.
|
||||
*/
|
||||
public void setRequest(HttpRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service instance used during the retry.
|
||||
* @return The service instance used during the retry.
|
||||
*/
|
||||
public ServiceInstance getServiceInstance() {
|
||||
return this.serviceInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service instance to use during the retry.
|
||||
* @param serviceInstance The service instance to use during the retry.
|
||||
*/
|
||||
public void setServiceInstance(ServiceInstance serviceInstance) {
|
||||
this.serviceInstance = serviceInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service instance to use during the retry.
|
||||
* @param serviceInstance The service instance to use during the retry.
|
||||
*/
|
||||
public void setServiceInstance(ServiceInstance serviceInstance) {
|
||||
this.serviceInstance = serviceInstance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.retry.RetryListener;
|
||||
@@ -21,6 +22,7 @@ import org.springframework.retry.backoff.NoBackOffPolicy;
|
||||
|
||||
/**
|
||||
* Factory class used to customize the retry functionality throughout Spring Cloud.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface LoadBalancedRetryFactory {
|
||||
@@ -31,7 +33,8 @@ public interface LoadBalancedRetryFactory {
|
||||
* @param serviceInstanceChooser Used to get the next server from a load balancer.
|
||||
* @return A retry policy for the service.
|
||||
*/
|
||||
default LoadBalancedRetryPolicy createRetryPolicy(String service, ServiceInstanceChooser serviceInstanceChooser) {
|
||||
default LoadBalancedRetryPolicy createRetryPolicy(String service,
|
||||
ServiceInstanceChooser serviceInstanceChooser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -52,4 +55,5 @@ public interface LoadBalancedRetryFactory {
|
||||
default BackOffPolicy createBackOffPolicy(String service) {
|
||||
return new NoBackOffPolicy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,51 +13,56 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
/**
|
||||
* Retry logic to use for the {@link LoadBalancerClient}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface LoadBalancedRetryPolicy {
|
||||
|
||||
/**
|
||||
* Return true to retry the failed request on the same server.
|
||||
* This method may be called more than once when executing a single operation.
|
||||
* @param context The context for the retry operation.
|
||||
* @return True to retry the failed request on the same server; false otherwise.
|
||||
*/
|
||||
public boolean canRetrySameServer(LoadBalancedRetryContext context);
|
||||
/**
|
||||
* Return true to retry the failed request on the same server. This method may be
|
||||
* called more than once when executing a single operation.
|
||||
* @param context The context for the retry operation.
|
||||
* @return True to retry the failed request on the same server; false otherwise.
|
||||
*/
|
||||
boolean canRetrySameServer(LoadBalancedRetryContext context);
|
||||
|
||||
/**
|
||||
* Return true to retry the failed request on the next server from the load balancer.
|
||||
* This method may be called more than once when executing a single operation.
|
||||
* @param context The context for the retry operation.
|
||||
* @return True to retry the failed request on the next server from the load balancer; false otherwise.
|
||||
*/
|
||||
public boolean canRetryNextServer(LoadBalancedRetryContext context);
|
||||
/**
|
||||
* Return true to retry the failed request on the next server from the load balancer.
|
||||
* This method may be called more than once when executing a single operation.
|
||||
* @param context The context for the retry operation.
|
||||
* @return True to retry the failed request on the next server from the load balancer;
|
||||
* false otherwise.
|
||||
*/
|
||||
boolean canRetryNextServer(LoadBalancedRetryContext context);
|
||||
|
||||
/**
|
||||
* Called when the retry operation has ended.
|
||||
* @param context The context for the retry operation.
|
||||
*/
|
||||
public abstract void close(LoadBalancedRetryContext context);
|
||||
/**
|
||||
* Called when the retry operation has ended.
|
||||
* @param context The context for the retry operation.
|
||||
*/
|
||||
void close(LoadBalancedRetryContext context);
|
||||
|
||||
/**
|
||||
* Called when the execution fails.
|
||||
* @param context The context for the retry operation.
|
||||
* @param throwable The throwable from the failed execution.
|
||||
*/
|
||||
public abstract void registerThrowable(LoadBalancedRetryContext context, Throwable throwable);
|
||||
/**
|
||||
* Called when the execution fails.
|
||||
* @param context The context for the retry operation.
|
||||
* @param throwable The throwable from the failed execution.
|
||||
*/
|
||||
void registerThrowable(LoadBalancedRetryContext context, Throwable throwable);
|
||||
|
||||
/**
|
||||
* If an exception is not thrown when making a request, this method will be called to
|
||||
* see if the client would like to retry the request based on the status code
|
||||
* returned. For example, in Cloud Foundry, the router will return a <code>404</code>
|
||||
* when an app is not available. Since HTTP clients do not throw an exception when a
|
||||
* <code>404</code> is returned, <code>retryableStatusCode</code> allows clients to
|
||||
* force a retry.
|
||||
* @param statusCode The HTTP status code.
|
||||
* @return True if a retry should be attempted; false to just return the response.
|
||||
*/
|
||||
boolean retryableStatusCode(int statusCode);
|
||||
|
||||
/**
|
||||
* If an exception is not thrown when making a request, this method will be called to see if the
|
||||
* client would like to retry the request based on the status code returned. For example, in
|
||||
* Cloud Foundry, the router will return a <code>404</code> when an app is not available. Since
|
||||
* HTTP clients do not throw an exception when a <code>404</code> is returned,
|
||||
* <code>retryableStatusCode</code> allows clients to force a retry.
|
||||
* @param statusCode The HTTP status code.
|
||||
* @return True if a retry should be attempted; false to just return the response.
|
||||
*/
|
||||
public boolean retryableStatusCode(int statusCode);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -27,14 +31,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.retry.backoff.BackOffPolicy;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Ribbon (client-side load balancing).
|
||||
*
|
||||
@@ -53,31 +52,32 @@ public class LoadBalancerAutoConfiguration {
|
||||
@Autowired(required = false)
|
||||
private List<RestTemplate> restTemplates = Collections.emptyList();
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
|
||||
|
||||
@Bean
|
||||
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
|
||||
final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
|
||||
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
|
||||
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
|
||||
for (RestTemplateCustomizer customizer : customizers) {
|
||||
customizer.customize(restTemplate);
|
||||
}
|
||||
}
|
||||
});
|
||||
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
|
||||
for (RestTemplateCustomizer customizer : customizers) {
|
||||
customizer.customize(restTemplate);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public LoadBalancerRequestFactory loadBalancerRequestFactory(
|
||||
LoadBalancerClient loadBalancerClient) {
|
||||
return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
|
||||
return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
|
||||
static class LoadBalancerInterceptorConfig {
|
||||
|
||||
@Bean
|
||||
public LoadBalancerInterceptor ribbonInterceptor(
|
||||
LoadBalancerClient loadBalancerClient,
|
||||
@@ -90,14 +90,18 @@ public class LoadBalancerAutoConfiguration {
|
||||
public RestTemplateCustomizer restTemplateCustomizer(
|
||||
final LoadBalancerInterceptor loadBalancerInterceptor) {
|
||||
return restTemplate -> {
|
||||
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
|
||||
restTemplate.getInterceptors());
|
||||
list.add(loadBalancerInterceptor);
|
||||
restTemplate.setInterceptors(list);
|
||||
};
|
||||
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
|
||||
restTemplate.getInterceptors());
|
||||
list.add(loadBalancerInterceptor);
|
||||
restTemplate.setInterceptors(list);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto configuration for retry mechanism.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(RetryTemplate.class)
|
||||
public static class RetryAutoConfiguration {
|
||||
@@ -105,17 +109,24 @@ public class LoadBalancerAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public LoadBalancedRetryFactory loadBalancedRetryFactory() {
|
||||
return new LoadBalancedRetryFactory() {};
|
||||
return new LoadBalancedRetryFactory() {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto configuration for retry intercepting mechanism.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(RetryTemplate.class)
|
||||
public static class RetryInterceptorAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RetryLoadBalancerInterceptor ribbonInterceptor(
|
||||
LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,
|
||||
LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancerRetryProperties properties,
|
||||
LoadBalancerRequestFactory requestFactory,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory) {
|
||||
return new RetryLoadBalancerInterceptor(loadBalancerClient, properties,
|
||||
@@ -127,11 +138,13 @@ public class LoadBalancerAutoConfiguration {
|
||||
public RestTemplateCustomizer restTemplateCustomizer(
|
||||
final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
|
||||
return restTemplate -> {
|
||||
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
|
||||
restTemplate.getInterceptors());
|
||||
list.add(loadBalancerInterceptor);
|
||||
restTemplate.setInterceptors(list);
|
||||
};
|
||||
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
|
||||
restTemplate.getInterceptors());
|
||||
list.add(loadBalancerInterceptor);
|
||||
restTemplate.setInterceptors(list);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* Represents a client-side load balancer.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface LoadBalancerClient extends ServiceInstanceChooser {
|
||||
@@ -33,6 +34,8 @@ public interface LoadBalancerClient extends ServiceInstanceChooser {
|
||||
* @param serviceId The service ID to look up the LoadBalancer.
|
||||
* @param request Allows implementations to execute pre and post actions, such as
|
||||
* incrementing metrics.
|
||||
* @param <T> type of the response
|
||||
* @throws IOException in case of IO issues.
|
||||
* @return The result of the LoadBalancerRequest callback on the selected
|
||||
* ServiceInstance.
|
||||
*/
|
||||
@@ -45,19 +48,23 @@ public interface LoadBalancerClient extends ServiceInstanceChooser {
|
||||
* @param serviceInstance The service to execute the request to.
|
||||
* @param request Allows implementations to execute pre and post actions, such as
|
||||
* incrementing metrics.
|
||||
* @param <T> type of the response
|
||||
* @throws IOException in case of IO issues.
|
||||
* @return The result of the LoadBalancerRequest callback on the selected
|
||||
* ServiceInstance.
|
||||
*/
|
||||
<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
|
||||
<T> T execute(String serviceId, ServiceInstance serviceInstance,
|
||||
LoadBalancerRequest<T> request) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a proper URI with a real host and port for systems to utilize.
|
||||
* Some systems use a URI with the logical service name as the host,
|
||||
* such as http://myservice/path/to/service. This will replace the
|
||||
* service name with the host:port from the ServiceInstance.
|
||||
* @param instance
|
||||
* Creates a proper URI with a real host and port for systems to utilize. Some systems
|
||||
* use a URI with the logical service name as the host, such as
|
||||
* http://myservice/path/to/service. This will replace the service name with the
|
||||
* host:port from the ServiceInstance.
|
||||
* @param instance service instance to reconstruct the URI
|
||||
* @param original A URI with the host as a logical service name.
|
||||
* @return A reconstructed URI.
|
||||
*/
|
||||
URI reconstructURI(ServiceInstance instance, URI original);
|
||||
|
||||
}
|
||||
|
||||
@@ -34,9 +34,11 @@ import org.springframework.util.Assert;
|
||||
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private LoadBalancerClient loadBalancer;
|
||||
|
||||
private LoadBalancerRequestFactory requestFactory;
|
||||
|
||||
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
|
||||
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer,
|
||||
LoadBalancerRequestFactory requestFactory) {
|
||||
this.loadBalancer = loadBalancer;
|
||||
this.requestFactory = requestFactory;
|
||||
}
|
||||
@@ -51,7 +53,10 @@ public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
|
||||
final ClientHttpRequestExecution execution) throws IOException {
|
||||
final URI originalUri = request.getURI();
|
||||
String serviceName = originalUri.getHost();
|
||||
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
|
||||
return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
|
||||
Assert.state(serviceName != null,
|
||||
"Request URI does not contain a valid hostname: " + originalUri);
|
||||
return this.loadBalancer.execute(serviceName,
|
||||
this.requestFactory.createRequest(request, body, execution));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,12 +19,14 @@ package org.springframework.cloud.client.loadbalancer;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* Simple interface used by LoadBalancerClient to apply metrics or pre and post
|
||||
* actions around load balancer requests.
|
||||
* Simple interface used by LoadBalancerClient to apply metrics or pre and post actions
|
||||
* around load balancer requests.
|
||||
*
|
||||
* @param <T> type of the response
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface LoadBalancerRequest<T> {
|
||||
|
||||
public T apply(ServiceInstance instance) throws Exception;
|
||||
T apply(ServiceInstance instance) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -18,23 +18,22 @@ package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
/**
|
||||
* Creates {@link LoadBalancerRequest}s for {@link LoadBalancerInterceptor} and
|
||||
* {@link RetryLoadBalancerInterceptor}. Applies
|
||||
* {@link LoadBalancerRequestTransformer}s to the intercepted
|
||||
* {@link HttpRequest}.
|
||||
*
|
||||
* {@link RetryLoadBalancerInterceptor}. Applies {@link LoadBalancerRequestTransformer}s
|
||||
* to the intercepted {@link HttpRequest}.
|
||||
*
|
||||
* @author William Tran
|
||||
*
|
||||
*/
|
||||
public class LoadBalancerRequestFactory {
|
||||
|
||||
private LoadBalancerClient loadBalancer;
|
||||
|
||||
private List<LoadBalancerRequestTransformer> transformers;
|
||||
|
||||
public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer,
|
||||
@@ -47,17 +46,20 @@ public class LoadBalancerRequestFactory {
|
||||
this.loadBalancer = loadBalancer;
|
||||
}
|
||||
|
||||
public LoadBalancerRequest<ClientHttpResponse> createRequest(final HttpRequest request,
|
||||
final byte[] body, final ClientHttpRequestExecution execution) {
|
||||
public LoadBalancerRequest<ClientHttpResponse> createRequest(
|
||||
final HttpRequest request, final byte[] body,
|
||||
final ClientHttpRequestExecution execution) {
|
||||
return instance -> {
|
||||
HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance, loadBalancer);
|
||||
if (transformers != null) {
|
||||
for (LoadBalancerRequestTransformer transformer : transformers) {
|
||||
serviceRequest = transformer.transformRequest(serviceRequest, instance);
|
||||
}
|
||||
}
|
||||
return execution.execute(serviceRequest, body);
|
||||
};
|
||||
HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance,
|
||||
this.loadBalancer);
|
||||
if (this.transformers != null) {
|
||||
for (LoadBalancerRequestTransformer transformer : this.transformers) {
|
||||
serviceRequest = transformer.transformRequest(serviceRequest,
|
||||
instance);
|
||||
}
|
||||
}
|
||||
return execution.execute(serviceRequest, body);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
@@ -20,14 +21,19 @@ import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* Allows applications to transform the load-balanced {@link HttpRequest} given
|
||||
* the chosen {@link ServiceInstance}.
|
||||
*
|
||||
* Allows applications to transform the load-balanced {@link HttpRequest} given the chosen
|
||||
* {@link ServiceInstance}.
|
||||
*
|
||||
* @author Will Tran
|
||||
*/
|
||||
@Order(LoadBalancerRequestTransformer.DEFAULT_ORDER)
|
||||
public interface LoadBalancerRequestTransformer {
|
||||
public static final int DEFAULT_ORDER = 0;
|
||||
|
||||
/**
|
||||
* Order for the load balancer request tranformer.
|
||||
*/
|
||||
int DEFAULT_ORDER = 0;
|
||||
|
||||
HttpRequest transformRequest(HttpRequest request, ServiceInstance instance);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -13,31 +13,35 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configuration properties for the {@link LoadBalancerClient}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.loadbalancer.retry")
|
||||
public class LoadBalancerRetryProperties {
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Returns true if the load balancer should retry failed requests.
|
||||
* @return True if the load balancer should retry failed requests; false otherwise.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Returns true if the load balancer should retry failed requests.
|
||||
* @return True if the load balancer should retry failed requests; false otherwise.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the load balancer should retry failed requests.
|
||||
* @param enabled Whether the load balancer should retry failed requests.
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the load balancer should retry failed requests.
|
||||
* @param enabled Whether the load balancer should retry failed requests.
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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.client.loadbalancer;
|
||||
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
@@ -6,5 +22,7 @@ import org.springframework.web.client.RestTemplate;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface RestTemplateCustomizer {
|
||||
|
||||
void customize(RestTemplate restTemplate);
|
||||
|
||||
}
|
||||
|
||||
@@ -40,29 +40,33 @@ import org.springframework.util.StreamUtils;
|
||||
public class RetryLoadBalancerInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private LoadBalancerClient loadBalancer;
|
||||
|
||||
private LoadBalancerRetryProperties lbProperties;
|
||||
|
||||
private LoadBalancerRequestFactory requestFactory;
|
||||
|
||||
private LoadBalancedRetryFactory lbRetryFactory;
|
||||
|
||||
public RetryLoadBalancerInterceptor(LoadBalancerClient loadBalancer,
|
||||
LoadBalancerRetryProperties lbProperties,
|
||||
LoadBalancerRequestFactory requestFactory,
|
||||
LoadBalancedRetryFactory lbRetryFactory) {
|
||||
this.loadBalancer = loadBalancer;
|
||||
this.lbProperties = lbProperties;
|
||||
this.requestFactory = requestFactory;
|
||||
this.lbRetryFactory = lbRetryFactory;
|
||||
LoadBalancerRetryProperties lbProperties,
|
||||
LoadBalancerRequestFactory requestFactory,
|
||||
LoadBalancedRetryFactory lbRetryFactory) {
|
||||
this.loadBalancer = loadBalancer;
|
||||
this.lbProperties = lbProperties;
|
||||
this.requestFactory = requestFactory;
|
||||
this.lbRetryFactory = lbRetryFactory;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
|
||||
final ClientHttpRequestExecution execution) throws IOException {
|
||||
final ClientHttpRequestExecution execution) throws IOException {
|
||||
final URI originalUri = request.getURI();
|
||||
final String serviceName = originalUri.getHost();
|
||||
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
|
||||
final LoadBalancedRetryPolicy retryPolicy = lbRetryFactory.createRetryPolicy(serviceName,
|
||||
loadBalancer);
|
||||
Assert.state(serviceName != null,
|
||||
"Request URI does not contain a valid hostname: " + originalUri);
|
||||
final LoadBalancedRetryPolicy retryPolicy = this.lbRetryFactory
|
||||
.createRetryPolicy(serviceName, this.loadBalancer);
|
||||
RetryTemplate template = createRetryTemplate(serviceName, request, retryPolicy);
|
||||
return template.execute(context -> {
|
||||
ServiceInstance serviceInstance = null;
|
||||
@@ -71,41 +75,48 @@ public class RetryLoadBalancerInterceptor implements ClientHttpRequestIntercepto
|
||||
serviceInstance = lbContext.getServiceInstance();
|
||||
}
|
||||
if (serviceInstance == null) {
|
||||
serviceInstance = loadBalancer.choose(serviceName);
|
||||
serviceInstance = this.loadBalancer.choose(serviceName);
|
||||
}
|
||||
ClientHttpResponse response = RetryLoadBalancerInterceptor.this.loadBalancer.execute(
|
||||
serviceName, serviceInstance,
|
||||
requestFactory.createRequest(request, body, execution));
|
||||
ClientHttpResponse response = RetryLoadBalancerInterceptor.this.loadBalancer
|
||||
.execute(serviceName, serviceInstance,
|
||||
this.requestFactory.createRequest(request, body, execution));
|
||||
int statusCode = response.getRawStatusCode();
|
||||
if (retryPolicy != null && retryPolicy.retryableStatusCode(statusCode)) {
|
||||
byte[] bodyCopy = StreamUtils.copyToByteArray(response.getBody());
|
||||
response.close();
|
||||
throw new ClientHttpResponseStatusCodeException(serviceName, response, bodyCopy);
|
||||
throw new ClientHttpResponseStatusCodeException(serviceName, response,
|
||||
bodyCopy);
|
||||
}
|
||||
return response;
|
||||
}, new LoadBalancedRecoveryCallback<ClientHttpResponse, ClientHttpResponse>() {
|
||||
//This is a special case, where both parameters to LoadBalancedRecoveryCallback are
|
||||
//the same. In most cases they would be different.
|
||||
// This is a special case, where both parameters to
|
||||
// LoadBalancedRecoveryCallback are
|
||||
// the same. In most cases they would be different.
|
||||
@Override
|
||||
protected ClientHttpResponse createResponse(ClientHttpResponse response, URI uri) {
|
||||
protected ClientHttpResponse createResponse(ClientHttpResponse response,
|
||||
URI uri) {
|
||||
return response;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private RetryTemplate createRetryTemplate(String serviceName, HttpRequest request, LoadBalancedRetryPolicy retryPolicy) {
|
||||
private RetryTemplate createRetryTemplate(String serviceName, HttpRequest request,
|
||||
LoadBalancedRetryPolicy retryPolicy) {
|
||||
RetryTemplate template = new RetryTemplate();
|
||||
BackOffPolicy backOffPolicy = lbRetryFactory.createBackOffPolicy(serviceName);
|
||||
template.setBackOffPolicy(backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
|
||||
BackOffPolicy backOffPolicy = this.lbRetryFactory
|
||||
.createBackOffPolicy(serviceName);
|
||||
template.setBackOffPolicy(
|
||||
backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
|
||||
template.setThrowLastExceptionOnExhausted(true);
|
||||
RetryListener[] retryListeners = lbRetryFactory.createRetryListeners(serviceName);
|
||||
RetryListener[] retryListeners = this.lbRetryFactory
|
||||
.createRetryListeners(serviceName);
|
||||
if (retryListeners != null && retryListeners.length != 0) {
|
||||
template.setListeners(retryListeners);
|
||||
}
|
||||
template.setRetryPolicy(
|
||||
!lbProperties.isEnabled() || retryPolicy == null ? new NeverRetryPolicy()
|
||||
: new InterceptorRetryPolicy(request, retryPolicy, loadBalancer,
|
||||
serviceName));
|
||||
template.setRetryPolicy(!this.lbProperties.isEnabled() || retryPolicy == null
|
||||
? new NeverRetryPolicy() : new InterceptorRetryPolicy(request,
|
||||
retryPolicy, this.loadBalancer, serviceName));
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -20,27 +21,30 @@ import java.net.URI;
|
||||
|
||||
/**
|
||||
* Exception to be thrown when the status code is deemed to be retryable.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class RetryableStatusCodeException extends IOException {
|
||||
|
||||
private static final String MESSAGE = "Service %s returned a status code of %d";
|
||||
|
||||
private Object response;
|
||||
private final Object response;
|
||||
|
||||
private URI uri;
|
||||
private final URI uri;
|
||||
|
||||
public RetryableStatusCodeException(String serviceId, int statusCode, Object response, URI uri) {
|
||||
public RetryableStatusCodeException(String serviceId, int statusCode, Object response,
|
||||
URI uri) {
|
||||
super(String.format(MESSAGE, serviceId, statusCode));
|
||||
this.response = response;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public Object getResponse() {
|
||||
return response;
|
||||
return this.response;
|
||||
}
|
||||
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,17 +19,18 @@ package org.springframework.cloud.client.loadbalancer;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* Implemented by classes which use a load balancer to choose a server to
|
||||
* send a request to.
|
||||
* Implemented by classes which use a load balancer to choose a server to send a request
|
||||
* to.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface ServiceInstanceChooser {
|
||||
|
||||
/**
|
||||
* Chooses a ServiceInstance from the LoadBalancer for the specified service.
|
||||
* @param serviceId The service ID to look up the LoadBalancer.
|
||||
* @return A ServiceInstance that matches the serviceId.
|
||||
*/
|
||||
ServiceInstance choose(String serviceId);
|
||||
/**
|
||||
* Chooses a ServiceInstance from the LoadBalancer for the specified service.
|
||||
* @param serviceId The service ID to look up the LoadBalancer.
|
||||
* @return A ServiceInstance that matches the serviceId.
|
||||
*/
|
||||
ServiceInstance choose(String serviceId);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.loadbalancer;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -10,11 +26,13 @@ import org.springframework.http.client.support.HttpRequestWrapper;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class ServiceRequestWrapper extends HttpRequestWrapper {
|
||||
|
||||
private final ServiceInstance instance;
|
||||
|
||||
private final LoadBalancerClient loadBalancer;
|
||||
|
||||
public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance,
|
||||
LoadBalancerClient loadBalancer) {
|
||||
LoadBalancerClient loadBalancer) {
|
||||
super(request);
|
||||
this.instance = instance;
|
||||
this.loadBalancer = loadBalancer;
|
||||
@@ -22,8 +40,8 @@ public class ServiceRequestWrapper extends HttpRequestWrapper {
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
URI uri = this.loadBalancer.reconstructURI(
|
||||
this.instance, getRequest().getURI());
|
||||
URI uri = this.loadBalancer.reconstructURI(this.instance, getRequest().getURI());
|
||||
return uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,19 +21,11 @@ import org.springframework.core.style.ToStringCreator;
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
//TODO: add metrics
|
||||
// TODO: add metrics
|
||||
public class CompletionContext {
|
||||
|
||||
public enum Status {
|
||||
/** Request was handled successfully */
|
||||
SUCCESSS,
|
||||
/** Request reached the server but failed due to timeout or internal error */
|
||||
FAILED,
|
||||
/** Request did not go off box and should not be counted for statistics */
|
||||
DISCARD,
|
||||
}
|
||||
|
||||
private final Status status;
|
||||
|
||||
private final Throwable throwable;
|
||||
|
||||
public CompletionContext(Status status) {
|
||||
@@ -46,19 +38,33 @@ public class CompletionContext {
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public Throwable getThrowable() {
|
||||
return throwable;
|
||||
return this.throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringCreator to = new ToStringCreator(this);
|
||||
to.append("status", status);
|
||||
to.append("throwable", throwable);
|
||||
to.append("status", this.status);
|
||||
to.append("throwable", this.throwable);
|
||||
return to.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request status state.
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
/** Request was handled successfully. */
|
||||
SUCCESSS,
|
||||
/** Request reached the server but failed due to timeout or internal error. */
|
||||
FAILED,
|
||||
/** Request did not go off box and should not be counted for statistics. */
|
||||
DISCARD,
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public class DefaultResponse implements Response<ServiceInstance> {
|
||||
|
||||
@Override
|
||||
public void onComplete(CompletionContext completionContext) {
|
||||
//TODO: implement
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ public class EmptyResponse implements Response<ServiceInstance> {
|
||||
|
||||
@Override
|
||||
public void onComplete(CompletionContext completionContext) {
|
||||
//TODO: implement
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -12,8 +30,6 @@ import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFunction;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Ryan Baxter
|
||||
@@ -33,25 +49,30 @@ public class LoadBalancerExchangeFilterFunction implements ExchangeFilterFunctio
|
||||
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
||||
URI originalUrl = request.url();
|
||||
String serviceId = originalUrl.getHost();
|
||||
if(serviceId == null) {
|
||||
String msg = String.format("Request URI does not contain a valid hostname: %s", originalUrl.toString());
|
||||
if (serviceId == null) {
|
||||
String msg = String.format(
|
||||
"Request URI does not contain a valid hostname: %s",
|
||||
originalUrl.toString());
|
||||
logger.warn(msg);
|
||||
return Mono.just(ClientResponse.create(HttpStatus.BAD_REQUEST).body(msg).build());
|
||||
return Mono.just(
|
||||
ClientResponse.create(HttpStatus.BAD_REQUEST).body(msg).build());
|
||||
}
|
||||
//TODO: reactive lb client
|
||||
// TODO: reactive lb client
|
||||
ServiceInstance instance = this.loadBalancerClient.choose(serviceId);
|
||||
if(instance == null) {
|
||||
String msg = String.format("Load balancer does not contain an instance for the service %s", serviceId);
|
||||
if (instance == null) {
|
||||
String msg = String.format(
|
||||
"Load balancer does not contain an instance for the service %s",
|
||||
serviceId);
|
||||
logger.warn(msg);
|
||||
return Mono.just(ClientResponse.create(HttpStatus.SERVICE_UNAVAILABLE).body(msg).build());
|
||||
return Mono.just(ClientResponse.create(HttpStatus.SERVICE_UNAVAILABLE)
|
||||
.body(msg).build());
|
||||
}
|
||||
URI uri = this.loadBalancerClient.reconstructURI(instance, originalUrl);
|
||||
ClientRequest newRequest = ClientRequest.method(request.method(), uri)
|
||||
.headers(headers -> headers.addAll(request.headers()))
|
||||
.cookies(cookies -> cookies.addAll(request.cookies()))
|
||||
.attributes(attributes -> attributes.putAll(request.attributes()))
|
||||
.body(request.body())
|
||||
.build();
|
||||
.body(request.body()).build();
|
||||
return next.exchange(newRequest);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,20 +19,27 @@ package org.springframework.cloud.client.loadbalancer.reactive;
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
/**
|
||||
* Reactive load balancer.
|
||||
*
|
||||
* @param <T> type of the response
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface ReactiveLoadBalancer<T> {
|
||||
|
||||
/**
|
||||
* Default implementation of a request.
|
||||
*/
|
||||
Request REQUEST = new DefaultRequest();
|
||||
|
||||
/**
|
||||
* Choose the next server based on the load balancing algorithm
|
||||
* @param request
|
||||
* @return
|
||||
* Choose the next server based on the load balancing algorithm.
|
||||
* @param request - incoming request
|
||||
* @return publisher for the response
|
||||
*/
|
||||
Publisher<Response<T>> choose(Request request);
|
||||
|
||||
default Publisher<Response<T>> choose() { //conflicting name
|
||||
default Publisher<Response<T>> choose() { // conflicting name
|
||||
return choose(REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
@@ -10,9 +29,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@@ -26,7 +42,7 @@ public class ReactiveLoadBalancerAutoConfiguration {
|
||||
private List<WebClient.Builder> webClientBuilders = Collections.emptyList();
|
||||
|
||||
public List<WebClient.Builder> getBuilders() {
|
||||
return webClientBuilders;
|
||||
return this.webClientBuilders;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -42,12 +58,15 @@ public class ReactiveLoadBalancerAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebClientCustomizer loadbalanceClientWebClientCustomizer(LoadBalancerExchangeFilterFunction filterFunction) {
|
||||
public WebClientCustomizer loadbalanceClientWebClientCustomizer(
|
||||
LoadBalancerExchangeFilterFunction filterFunction) {
|
||||
return builder -> builder.filter(filterFunction);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(LoadBalancerClient client) {
|
||||
public LoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(
|
||||
LoadBalancerClient client) {
|
||||
return new LoadBalancerExchangeFilterFunction(client);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
/**
|
||||
* Marker interface for a request.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface Request {
|
||||
//TODO: define contents
|
||||
|
||||
// TODO: define contents
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,37 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
/**
|
||||
* Response created for each request.
|
||||
*/
|
||||
*
|
||||
* @param <T> type of the server
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface Response<T> {
|
||||
|
||||
boolean hasServer();
|
||||
|
||||
T getServer();
|
||||
|
||||
/**
|
||||
* Notification that the request completed
|
||||
* @param completionContext
|
||||
* Notification that the request completed.
|
||||
* @param completionContext - completion context
|
||||
*/
|
||||
void onComplete(CompletionContext completionContext);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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.
|
||||
@@ -23,7 +23,8 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
* {@link org.springframework.web.reactive.function.client.WebClient.Builder
|
||||
* WebClient.Builder}.
|
||||
*
|
||||
* See original {@link org.springframework.boot.web.reactive.function.client.WebClientCustomizer}
|
||||
* See original
|
||||
* {@link org.springframework.boot.web.reactive.function.client.WebClientCustomizer}
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.1.0
|
||||
@@ -40,4 +41,3 @@ public interface WebClientCustomizer {
|
||||
void customize(WebClient.Builder webClientBuilder);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -26,14 +42,17 @@ import org.springframework.core.env.Environment;
|
||||
* TODO: Document the lifecycle.
|
||||
*
|
||||
* @param <R> Registration type passed to the {@link ServiceRegistry}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {
|
||||
implements AutoServiceRegistration, ApplicationContextAware,
|
||||
ApplicationListener<WebServerInitializedEvent> {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(AbstractAutoServiceRegistration.class);
|
||||
|
||||
private final ServiceRegistry<R> serviceRegistry;
|
||||
|
||||
private boolean autoStartup = true;
|
||||
|
||||
private AtomicBoolean running = new AtomicBoolean(false);
|
||||
@@ -46,7 +65,6 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
|
||||
private AtomicInteger port = new AtomicInteger(0);
|
||||
|
||||
private final ServiceRegistry<R> serviceRegistry;
|
||||
private AutoServiceRegistrationProperties properties;
|
||||
|
||||
@Deprecated
|
||||
@@ -54,13 +72,14 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry, AutoServiceRegistrationProperties properties) {
|
||||
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry,
|
||||
AutoServiceRegistrationProperties properties) {
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
protected ApplicationContext getContext() {
|
||||
return context;
|
||||
return this.context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,8 +92,8 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
public void bind(WebServerInitializedEvent event) {
|
||||
ApplicationContext context = event.getApplicationContext();
|
||||
if (context instanceof ConfigurableWebServerApplicationContext) {
|
||||
if ("management".equals(
|
||||
((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {
|
||||
if ("management".equals(((ConfigurableWebServerApplicationContext) context)
|
||||
.getServerNamespace())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -91,12 +110,12 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
|
||||
@Deprecated
|
||||
protected Environment getEnvironment() {
|
||||
return environment;
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected AtomicInteger getPort() {
|
||||
return port;
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public boolean isAutoStartup() {
|
||||
@@ -114,7 +133,8 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
// only initialize if nonSecurePort is greater than 0 and it isn't already running
|
||||
// because of containerPortInitializer below
|
||||
if (!this.running.get()) {
|
||||
this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));
|
||||
this.context.publishEvent(
|
||||
new InstancePreRegisteredEvent(this, getRegistration()));
|
||||
register();
|
||||
if (shouldRegisterManagement()) {
|
||||
registerManagement();
|
||||
@@ -193,7 +213,7 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
}
|
||||
|
||||
protected AtomicBoolean getRunning() {
|
||||
return running;
|
||||
return this.running;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
@@ -255,4 +275,5 @@ public abstract class AbstractAutoServiceRegistration<R extends Registration>
|
||||
this.serviceRegistry.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface AutoServiceRegistration {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -23,8 +39,10 @@ public class AutoServiceRegistrationAutoConfiguration {
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
if (autoServiceRegistration == null && this.properties.isFailFast()) {
|
||||
throw new IllegalStateException("Auto Service Registration has been requested, but there is no AutoServiceRegistration bean");
|
||||
if (this.autoServiceRegistration == null && this.properties.isFailFast()) {
|
||||
throw new IllegalStateException("Auto Service Registration has "
|
||||
+ "been requested, but there is no AutoServiceRegistration bean");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -11,4 +27,5 @@ import org.springframework.context.annotation.Configuration;
|
||||
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||
public class AutoServiceRegistrationConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -14,11 +30,13 @@ public class AutoServiceRegistrationProperties {
|
||||
/** Whether to register the management as a service. Defaults to true. */
|
||||
private boolean registerManagement = true;
|
||||
|
||||
/** Whether startup fails if there is no AutoServiceRegistration. Defaults to false. */
|
||||
/**
|
||||
* Whether startup fails if there is no AutoServiceRegistration. Defaults to false.
|
||||
*/
|
||||
private boolean failFast = false;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
@@ -26,23 +44,24 @@ public class AutoServiceRegistrationProperties {
|
||||
}
|
||||
|
||||
public boolean isRegisterManagement() {
|
||||
return registerManagement;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean shouldRegisterManagement() {
|
||||
return registerManagement;
|
||||
return this.registerManagement;
|
||||
}
|
||||
|
||||
public void setRegisterManagement(boolean registerManagement) {
|
||||
this.registerManagement = registerManagement;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean shouldRegisterManagement() {
|
||||
return this.registerManagement;
|
||||
}
|
||||
|
||||
public boolean isFailFast() {
|
||||
return failFast;
|
||||
return this.failFast;
|
||||
}
|
||||
|
||||
public void setFailFast(boolean failFast) {
|
||||
this.failFast = failFast;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
@@ -9,4 +25,5 @@ import org.springframework.cloud.client.ServiceInstance;
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface Registration extends ServiceInstance {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
/**
|
||||
* Contract to register and deregister instances with a Service Registry.
|
||||
*
|
||||
* @param <R> registration meta data
|
||||
* @author Spencer Gibb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface ServiceRegistry<R extends Registration> {
|
||||
|
||||
/**
|
||||
* Registers the registration. A registration typically has information about
|
||||
* an instance, such as its hostname and port.
|
||||
* @param registration The registration.
|
||||
* Registers the registration. A registration typically has information about an
|
||||
* instance, such as its hostname and port.
|
||||
* @param registration registration meta data
|
||||
*/
|
||||
void register(R registration);
|
||||
|
||||
/**
|
||||
* Deregisters the registration.
|
||||
* @param registration
|
||||
* @param registration registration meta data
|
||||
*/
|
||||
void deregister(R registration);
|
||||
|
||||
@@ -27,22 +44,21 @@ public interface ServiceRegistry<R extends Registration> {
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Sets the status of the registration. The status values are determined
|
||||
* by the individual implementations.
|
||||
*
|
||||
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
|
||||
* Sets the status of the registration. The status values are determined by the
|
||||
* individual implementations.
|
||||
* @param registration The registration to update.
|
||||
* @param status The status to set.
|
||||
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
|
||||
*/
|
||||
void setStatus(R registration, String status);
|
||||
|
||||
/**
|
||||
* Gets the status of a particular registration.
|
||||
*
|
||||
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
|
||||
* @param registration The registration to query.
|
||||
* @param <T> The type of the status.
|
||||
* @return The status of the registration.
|
||||
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
|
||||
*/
|
||||
<T> T getStatus(R registration);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.client.serviceregistry;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -18,15 +34,20 @@ public class ServiceRegistryAutoConfiguration {
|
||||
@ConditionalOnBean(ServiceRegistry.class)
|
||||
@ConditionalOnClass(Endpoint.class)
|
||||
protected class ServiceRegistryEndpointConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private Registration registration;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledEndpoint
|
||||
public ServiceRegistryEndpoint serviceRegistryEndpoint(ServiceRegistry serviceRegistry) {
|
||||
ServiceRegistryEndpoint endpoint = new ServiceRegistryEndpoint(serviceRegistry);
|
||||
endpoint.setRegistration(registration);
|
||||
public ServiceRegistryEndpoint serviceRegistryEndpoint(
|
||||
ServiceRegistry serviceRegistry) {
|
||||
ServiceRegistryEndpoint endpoint = new ServiceRegistryEndpoint(
|
||||
serviceRegistry);
|
||||
endpoint.setRegistration(this.registration);
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -12,7 +12,6 @@
|
||||
* 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.client.serviceregistry.endpoint;
|
||||
@@ -52,7 +51,8 @@ public class ServiceRegistryEndpoint {
|
||||
Assert.notNull(status, "status may not by null");
|
||||
|
||||
if (this.registration == null) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("no registration found");
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("no registration found");
|
||||
}
|
||||
|
||||
this.serviceRegistry.setStatus(this.registration, status);
|
||||
@@ -62,10 +62,12 @@ public class ServiceRegistryEndpoint {
|
||||
@ReadOperation
|
||||
public ResponseEntity getStatus() {
|
||||
if (this.registration == null) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("no registration found");
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("no registration found");
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().body(this.serviceRegistry.getStatus(this.registration));
|
||||
return ResponseEntity.ok()
|
||||
.body(this.serviceRegistry.getStatus(this.registration));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* * 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.
|
||||
* 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.commons.httpclient;
|
||||
@@ -25,11 +23,20 @@ import org.apache.http.conn.HttpClientConnectionManager;
|
||||
|
||||
/**
|
||||
* Interface for creating an {@link HttpClientConnectionManager}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface ApacheHttpClientConnectionManagerFactory {
|
||||
public static final String HTTP_SCHEME = "http";
|
||||
public static final String HTTPS_SCHEME = "https";
|
||||
|
||||
/**
|
||||
* Scheme for HTTP based communication.
|
||||
*/
|
||||
String HTTP_SCHEME = "http";
|
||||
|
||||
/**
|
||||
* Scheme for HTTPS based communication.
|
||||
*/
|
||||
String HTTPS_SCHEME = "https";
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpClientConnectionManager}.
|
||||
@@ -38,10 +45,12 @@ public interface ApacheHttpClientConnectionManagerFactory {
|
||||
* @param maxConnectionsPerRoute The total number of connections per route.
|
||||
* @param timeToLive The time a connection is allowed to exist.
|
||||
* @param timeUnit The time unit for the time-to-live value.
|
||||
* @param registryBuilder The {@link RegistryBuilder} to use in the connection manager.
|
||||
* @param registryBuilder The {@link RegistryBuilder} to use in the connection
|
||||
* manager.
|
||||
* @return A new {@link HttpClientConnectionManager}.
|
||||
*/
|
||||
public HttpClientConnectionManager newConnectionManager(boolean disableSslValidation,
|
||||
HttpClientConnectionManager newConnectionManager(boolean disableSslValidation,
|
||||
int maxTotalConnections, int maxConnectionsPerRoute, long timeToLive,
|
||||
TimeUnit timeUnit, RegistryBuilder registryBuilder);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* * 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.
|
||||
* 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.commons.httpclient;
|
||||
@@ -23,13 +21,16 @@ import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
||||
/**
|
||||
* Factory for creating a new {@link CloseableHttpClient}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface ApacheHttpClientFactory {
|
||||
|
||||
/**
|
||||
* Creates an {@link HttpClientBuilder} that can be used to create a new {@link CloseableHttpClient}.
|
||||
* Creates an {@link HttpClientBuilder} that can be used to create a new
|
||||
* {@link CloseableHttpClient}.
|
||||
* @return A {@link HttpClientBuilder}.
|
||||
*/
|
||||
public HttpClientBuilder createBuilder();
|
||||
HttpClientBuilder createBuilder();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.commons.httpclient;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
@@ -6,9 +22,12 @@ import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
@@ -18,10 +37,10 @@ import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ApacheHttpClientConnectionManagerFactory}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
* @author Michael Wirth
|
||||
*/
|
||||
@@ -42,17 +61,17 @@ public class DefaultApacheHttpClientConnectionManagerFactory
|
||||
int maxTotalConnections, int maxConnectionsPerRoute, long timeToLive,
|
||||
TimeUnit timeUnit, RegistryBuilder registryBuilder) {
|
||||
if (registryBuilder == null) {
|
||||
registryBuilder = RegistryBuilder.<ConnectionSocketFactory> create()
|
||||
registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||
.register(HTTP_SCHEME, PlainConnectionSocketFactory.INSTANCE);
|
||||
}
|
||||
if (disableSslValidation) {
|
||||
try {
|
||||
final SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null,
|
||||
new TrustManager[] { new DisabledValidationTrustManager()},
|
||||
new SecureRandom());
|
||||
new TrustManager[] { new DisabledValidationTrustManager() },
|
||||
new SecureRandom());
|
||||
registryBuilder.register(HTTPS_SCHEME, new SSLConnectionSocketFactory(
|
||||
sslContext, NoopHostnameVerifier.INSTANCE));
|
||||
sslContext, NoopHostnameVerifier.INSTANCE));
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
LOG.warn("Error creating SSLContext", e);
|
||||
@@ -60,8 +79,10 @@ public class DefaultApacheHttpClientConnectionManagerFactory
|
||||
catch (KeyManagementException e) {
|
||||
LOG.warn("Error creating SSLContext", e);
|
||||
}
|
||||
} else {
|
||||
registryBuilder.register("https", SSLConnectionSocketFactory.getSocketFactory());
|
||||
}
|
||||
else {
|
||||
registryBuilder.register("https",
|
||||
SSLConnectionSocketFactory.getSocketFactory());
|
||||
}
|
||||
final Registry<ConnectionSocketFactory> registry = registryBuilder.build();
|
||||
|
||||
@@ -74,19 +95,22 @@ public class DefaultApacheHttpClientConnectionManagerFactory
|
||||
}
|
||||
|
||||
class DisabledValidationTrustManager implements X509TrustManager {
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates,
|
||||
String s) throws CertificateException {
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
|
||||
throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates,
|
||||
String s) throws CertificateException {
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
|
||||
throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.commons.httpclient;
|
||||
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ApacheHttpClientFactory}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultApacheHttpClientFactory implements ApacheHttpClientFactory {
|
||||
@@ -17,11 +34,12 @@ public class DefaultApacheHttpClientFactory implements ApacheHttpClientFactory {
|
||||
/**
|
||||
* A default {@link HttpClientBuilder}. The {@link HttpClientBuilder} returned will
|
||||
* have content compression disabled, have cookie management disabled, and use system
|
||||
* properties.
|
||||
* properties.
|
||||
*/
|
||||
@Override
|
||||
public HttpClientBuilder createBuilder() {
|
||||
return this.builder.disableContentCompression()
|
||||
.disableCookieManagement().useSystemProperties();
|
||||
return this.builder.disableContentCompression().disableCookieManagement()
|
||||
.useSystemProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link OkHttpClientConnectionPoolFactory}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultOkHttpClientConnectionPoolFactory implements OkHttpClientConnectionPoolFactory {
|
||||
public class DefaultOkHttpClientConnectionPoolFactory
|
||||
implements OkHttpClientConnectionPoolFactory {
|
||||
|
||||
@Override
|
||||
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
|
||||
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration,
|
||||
TimeUnit timeUnit) {
|
||||
return new ConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link OkHttpClientFactory}.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class DefaultOkHttpClientFactory implements OkHttpClientFactory {
|
||||
@@ -35,8 +53,9 @@ public class DefaultOkHttpClientFactory implements OkHttpClientFactory {
|
||||
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, trustManagers, new java.security.SecureRandom());
|
||||
SSLSocketFactory disabledSSLSocketFactory = sslContext.getSocketFactory();
|
||||
builder.sslSocketFactory(disabledSSLSocketFactory, disabledTrustManager);
|
||||
builder.hostnameVerifier(new TrustAllHostnames());
|
||||
this.builder.sslSocketFactory(disabledSSLSocketFactory,
|
||||
disabledTrustManager);
|
||||
this.builder.hostnameVerifier(new TrustAllHostnames());
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
LOG.warn("Error setting SSLSocketFactory in OKHttpClient", e);
|
||||
@@ -45,6 +64,7 @@ public class DefaultOkHttpClientFactory implements OkHttpClientFactory {
|
||||
LOG.warn("Error setting SSLSocketFactory in OKHttpClient", e);
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
return this.builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.commons.httpclient;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -35,9 +51,11 @@ public class HttpClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ApacheHttpClientFactory apacheHttpClientFactory(HttpClientBuilder builder) {
|
||||
public ApacheHttpClientFactory apacheHttpClientFactory(
|
||||
HttpClientBuilder builder) {
|
||||
return new DefaultApacheHttpClientFactory(builder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -62,5 +80,7 @@ public class HttpClientConfiguration {
|
||||
public OkHttpClientFactory okHttpClientFactory(OkHttpClient.Builder builder) {
|
||||
return new DefaultOkHttpClientFactory(builder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
|
||||
/**
|
||||
* Creates {@link ConnectionPool}s for {@link okhttp3.OkHttpClient}s.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface OkHttpClientConnectionPoolFactory {
|
||||
@@ -17,5 +34,7 @@ public interface OkHttpClientConnectionPoolFactory {
|
||||
* @param timeUnit The time unit for the keep-alive duration.
|
||||
* @return A new {@link ConnectionPool}.
|
||||
*/
|
||||
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit);
|
||||
ConnectionPool create(int maxIdleConnections, long keepAliveDuration,
|
||||
TimeUnit timeUnit);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,33 @@
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
package org.springframework.cloud.commons.httpclient;
|
||||
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* Creates new {@link OkHttpClient}s.
|
||||
*
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public interface OkHttpClientFactory {
|
||||
@@ -19,33 +37,40 @@ public interface OkHttpClientFactory {
|
||||
* @param disableSslValidation Disables SSL validation
|
||||
* @return A new {@link OkHttpClient.Builder}
|
||||
*/
|
||||
public OkHttpClient.Builder createBuilder(boolean disableSslValidation);
|
||||
OkHttpClient.Builder createBuilder(boolean disableSslValidation);
|
||||
|
||||
/**
|
||||
* A {@link X509TrustManager} that does not validate SSL certificates.
|
||||
*/
|
||||
public static class DisableValidationTrustManager implements X509TrustManager {
|
||||
class DisableValidationTrustManager implements X509TrustManager {
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
|
||||
throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
|
||||
throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link HostnameVerifier} that does not validate any hostnames.
|
||||
*/
|
||||
public static class TrustAllHostnames implements HostnameVerifier {
|
||||
class TrustAllHostnames implements HostnameVerifier {
|
||||
|
||||
@Override
|
||||
public boolean verify(String s, SSLSession sslSession) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.commons.util;
|
||||
|
||||
import org.springframework.core.env.PropertyResolver;
|
||||
@@ -6,15 +22,20 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class IdUtils {
|
||||
public final class IdUtils {
|
||||
|
||||
private static final String SEPARATOR = ":";
|
||||
|
||||
public static String getDefaultInstanceId(PropertyResolver resolver) {
|
||||
return getDefaultInstanceId(resolver, true);
|
||||
}
|
||||
private IdUtils() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
public static String getDefaultInstanceId(PropertyResolver resolver, boolean includeHostname) {
|
||||
public static String getDefaultInstanceId(PropertyResolver resolver) {
|
||||
return getDefaultInstanceId(resolver, true);
|
||||
}
|
||||
|
||||
public static String getDefaultInstanceId(PropertyResolver resolver,
|
||||
boolean includeHostname) {
|
||||
String vcapInstanceId = resolver.getProperty("vcap.application.instance_id");
|
||||
if (StringUtils.hasText(vcapInstanceId)) {
|
||||
return vcapInstanceId;
|
||||
@@ -34,13 +55,16 @@ public class IdUtils {
|
||||
return combineParts(namePart, SEPARATOR, indexPart);
|
||||
}
|
||||
|
||||
public static String combineParts(String firstPart, String separator, String secondPart) {
|
||||
public static String combineParts(String firstPart, String separator,
|
||||
String secondPart) {
|
||||
String combined = null;
|
||||
if (firstPart != null && secondPart != null) {
|
||||
combined = firstPart + separator + secondPart;
|
||||
} else if (firstPart != null) {
|
||||
}
|
||||
else if (firstPart != null) {
|
||||
combined = firstPart;
|
||||
} else if (secondPart != null) {
|
||||
}
|
||||
else if (secondPart != null) {
|
||||
combined = secondPart;
|
||||
}
|
||||
return combined;
|
||||
|
||||
@@ -25,11 +25,9 @@ import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -42,24 +40,24 @@ public class InetUtils implements Closeable {
|
||||
|
||||
// TODO: maybe shutdown the thread pool if it isn't being used?
|
||||
private final ExecutorService executorService;
|
||||
|
||||
private final InetUtilsProperties properties;
|
||||
|
||||
private final Log log = LogFactory.getLog(InetUtils.class);
|
||||
|
||||
|
||||
public InetUtils(final InetUtilsProperties properties) {
|
||||
this.properties = properties;
|
||||
this.executorService = Executors
|
||||
.newSingleThreadExecutor(r -> {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setName(InetUtilsProperties.PREFIX);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
this.executorService = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setName(InetUtilsProperties.PREFIX);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
executorService.shutdown();
|
||||
this.executorService.shutdown();
|
||||
}
|
||||
|
||||
public HostInfo findFirstNonLoopbackHostInfo() {
|
||||
@@ -81,7 +79,7 @@ public class InetUtils implements Closeable {
|
||||
.getNetworkInterfaces(); nics.hasMoreElements();) {
|
||||
NetworkInterface ifc = nics.nextElement();
|
||||
if (ifc.isUp()) {
|
||||
log.trace("Testing interface: " + ifc.getDisplayName());
|
||||
this.log.trace("Testing interface: " + ifc.getDisplayName());
|
||||
if (ifc.getIndex() < lowest || result == null) {
|
||||
lowest = ifc.getIndex();
|
||||
}
|
||||
@@ -97,7 +95,7 @@ public class InetUtils implements Closeable {
|
||||
if (address instanceof Inet4Address
|
||||
&& !address.isLoopbackAddress()
|
||||
&& isPreferredAddress(address)) {
|
||||
log.trace("Found non-loopback interface: "
|
||||
this.log.trace("Found non-loopback interface: "
|
||||
+ ifc.getDisplayName());
|
||||
result = address;
|
||||
}
|
||||
@@ -108,7 +106,7 @@ public class InetUtils implements Closeable {
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
log.error("Cannot get first non-loopback address", ex);
|
||||
this.log.error("Cannot get first non-loopback address", ex);
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
@@ -119,18 +117,19 @@ public class InetUtils implements Closeable {
|
||||
return InetAddress.getLocalHost();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
log.warn("Unable to retrieve localhost");
|
||||
this.log.warn("Unable to retrieve localhost");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** For testing. */ boolean isPreferredAddress(InetAddress address) {
|
||||
// For testing.
|
||||
boolean isPreferredAddress(InetAddress address) {
|
||||
|
||||
if (this.properties.isUseOnlySiteLocalInterfaces()) {
|
||||
final boolean siteLocalAddress = address.isSiteLocalAddress();
|
||||
if (!siteLocalAddress) {
|
||||
log.trace("Ignoring address: " + address.getHostAddress());
|
||||
this.log.trace("Ignoring address: " + address.getHostAddress());
|
||||
}
|
||||
return siteLocalAddress;
|
||||
}
|
||||
@@ -144,14 +143,15 @@ public class InetUtils implements Closeable {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
log.trace("Ignoring address: " + address.getHostAddress());
|
||||
this.log.trace("Ignoring address: " + address.getHostAddress());
|
||||
return false;
|
||||
}
|
||||
|
||||
/** For testing. */ boolean ignoreInterface(String interfaceName) {
|
||||
// For testing
|
||||
boolean ignoreInterface(String interfaceName) {
|
||||
for (String regex : this.properties.getIgnoredInterfaces()) {
|
||||
if (interfaceName.matches(regex)) {
|
||||
log.trace("Ignoring interface: " + interfaceName);
|
||||
this.log.trace("Ignoring interface: " + interfaceName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -160,14 +160,14 @@ public class InetUtils implements Closeable {
|
||||
|
||||
public HostInfo convertAddress(final InetAddress address) {
|
||||
HostInfo hostInfo = new HostInfo();
|
||||
Future<String> result = executorService.submit(address::getHostName);
|
||||
Future<String> result = this.executorService.submit(address::getHostName);
|
||||
|
||||
String hostname;
|
||||
try {
|
||||
hostname = result.get(this.properties.getTimeoutSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.info("Cannot determine local hostname");
|
||||
this.log.info("Cannot determine local hostname");
|
||||
hostname = "localhost";
|
||||
}
|
||||
hostInfo.setHostname(hostname);
|
||||
@@ -175,9 +175,18 @@ public class InetUtils implements Closeable {
|
||||
return hostInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Host information pojo.
|
||||
*/
|
||||
public static class HostInfo {
|
||||
|
||||
/**
|
||||
* Should override the host info.
|
||||
*/
|
||||
public boolean override;
|
||||
|
||||
private String ipAddress;
|
||||
|
||||
private String hostname;
|
||||
|
||||
public HostInfo(String hostname) {
|
||||
@@ -203,7 +212,7 @@ public class InetUtils implements Closeable {
|
||||
}
|
||||
|
||||
public boolean isOverride() {
|
||||
return override;
|
||||
return this.override;
|
||||
}
|
||||
|
||||
public void setOverride(boolean override) {
|
||||
@@ -211,7 +220,7 @@ public class InetUtils implements Closeable {
|
||||
}
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
return this.ipAddress;
|
||||
}
|
||||
|
||||
public void setIpAddress(String ipAddress) {
|
||||
@@ -219,12 +228,13 @@ public class InetUtils implements Closeable {
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
return this.hostname;
|
||||
}
|
||||
|
||||
public void setHostname(String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -24,10 +24,16 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for {@link InetUtils}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@ConfigurationProperties(InetUtilsProperties.PREFIX)
|
||||
public class InetUtilsProperties {
|
||||
|
||||
/**
|
||||
* Prefix for the Inet Utils properties.
|
||||
*/
|
||||
public static final String PREFIX = "spring.cloud.inetutils";
|
||||
|
||||
/**
|
||||
@@ -50,13 +56,13 @@ public class InetUtilsProperties {
|
||||
* List of Java regular expressions for network interfaces that will be ignored.
|
||||
*/
|
||||
private List<String> ignoredInterfaces = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* Whether to use only interfaces with site local addresses.
|
||||
* See {@link InetAddress#isSiteLocalAddress()} for more details.
|
||||
* Whether to use only interfaces with site local addresses. See
|
||||
* {@link InetAddress#isSiteLocalAddress()} for more details.
|
||||
*/
|
||||
private boolean useOnlySiteLocalInterfaces = false;
|
||||
|
||||
|
||||
/**
|
||||
* List of Java regular expressions for network addresses that will be preferred.
|
||||
*/
|
||||
@@ -67,7 +73,7 @@ public class InetUtilsProperties {
|
||||
}
|
||||
|
||||
public String getDefaultHostname() {
|
||||
return defaultHostname;
|
||||
return this.defaultHostname;
|
||||
}
|
||||
|
||||
public void setDefaultHostname(String defaultHostname) {
|
||||
@@ -75,7 +81,7 @@ public class InetUtilsProperties {
|
||||
}
|
||||
|
||||
public String getDefaultIpAddress() {
|
||||
return defaultIpAddress;
|
||||
return this.defaultIpAddress;
|
||||
}
|
||||
|
||||
public void setDefaultIpAddress(String defaultIpAddress) {
|
||||
@@ -83,7 +89,7 @@ public class InetUtilsProperties {
|
||||
}
|
||||
|
||||
public int getTimeoutSeconds() {
|
||||
return timeoutSeconds;
|
||||
return this.timeoutSeconds;
|
||||
}
|
||||
|
||||
public void setTimeoutSeconds(int timeoutSeconds) {
|
||||
@@ -91,7 +97,7 @@ public class InetUtilsProperties {
|
||||
}
|
||||
|
||||
public List<String> getIgnoredInterfaces() {
|
||||
return ignoredInterfaces;
|
||||
return this.ignoredInterfaces;
|
||||
}
|
||||
|
||||
public void setIgnoredInterfaces(List<String> ignoredInterfaces) {
|
||||
@@ -99,7 +105,7 @@ public class InetUtilsProperties {
|
||||
}
|
||||
|
||||
public boolean isUseOnlySiteLocalInterfaces() {
|
||||
return useOnlySiteLocalInterfaces;
|
||||
return this.useOnlySiteLocalInterfaces;
|
||||
}
|
||||
|
||||
public void setUseOnlySiteLocalInterfaces(boolean useOnlySiteLocalInterfaces) {
|
||||
@@ -107,10 +113,11 @@ public class InetUtilsProperties {
|
||||
}
|
||||
|
||||
public List<String> getPreferredNetworks() {
|
||||
return preferredNetworks;
|
||||
return this.preferredNetworks;
|
||||
}
|
||||
|
||||
public void setPreferredNetworks(List<String> preferredNetworks) {
|
||||
this.preferredNetworks = preferredNetworks;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.DeferredImportSelector;
|
||||
@@ -32,25 +33,25 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Selects configurations to load, defined by the generic type T. Loads implementations
|
||||
* using {@link SpringFactoriesLoader}.
|
||||
*
|
||||
* @param <T> type of annotation class
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public abstract class SpringFactoryImportSelector<T>
|
||||
implements DeferredImportSelector, BeanClassLoaderAware, EnvironmentAware {
|
||||
|
||||
private final Log log = LogFactory.getLog(SpringFactoryImportSelector.class);
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private Class<T> annotationClass;
|
||||
|
||||
private Environment environment;
|
||||
|
||||
private final Log log = LogFactory.getLog(SpringFactoryImportSelector.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected SpringFactoryImportSelector() {
|
||||
this.annotationClass = (Class<T>) GenericTypeResolver
|
||||
@@ -80,7 +81,7 @@ public abstract class SpringFactoryImportSelector<T>
|
||||
if (factories.size() > 1) {
|
||||
// there should only ever be one DiscoveryClient, but there might be more than
|
||||
// one factory
|
||||
log.warn("More than one implementation " + "of @" + getSimpleName()
|
||||
this.log.warn("More than one implementation " + "of @" + getSimpleName()
|
||||
+ " (now relying on @Conditionals to pick one): " + factories);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* 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.commons.util;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
@@ -26,4 +42,5 @@ public class UtilAutoConfiguration {
|
||||
public InetUtils inetUtils(InetUtilsProperties properties) {
|
||||
return new InetUtils(properties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user