Add evictor based loadbalancer caching (#644)

* Add Evictor dependency. Implement EvictorCache.

* Add EvictorBasedLoadBalancerCacheManager. Add evictor to starter.

* Set caffeine InitialCapacity from properties.

* Add tests. Add javadocs. Fix creating multiple cache instances.

* Reformat. Change property name. Add documentation.

* Add more tests.

* Move evictor version to parent. Add more tests.

* Ignore .flattened-pom.xml.

* Encapsulate Evictor and switch to non-evictor specific class naming.

* Adjust the docs.

* Fix after code review.
This commit is contained in:
Olga Maciaszek-Sharma
2019-11-25 20:34:19 +01:00
committed by GitHub
parent 05d936803f
commit da0e06eb7a
24 changed files with 599 additions and 1393 deletions

View File

@@ -1,131 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath></relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Commons Parent</name>
<description>Spring Cloud Commons Parent</description>
<url>https://projects.spring.io/spring-cloud/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<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>
<url>https://github.com/spring-cloud/spring-cloud-commons</url>
</scm>
<profiles>
<profile>
<id>spring</id>
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
</repository>
</repositories>
</profile>
</profiles>
</project>

1
.gitignore vendored
View File

@@ -20,3 +20,4 @@ _site/
/spring-cloud-release-tools*.jar
antrun
.vscode/
.flattened-pom.xml

View File

@@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-docs</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Commons Docs</name>
<description>Spring Cloud Commons Docs</description>
<url>https://projects.spring.io/spring-cloud/spring-cloud-commons-docs/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons-docs</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons-docs</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-commons-docs</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -803,19 +803,32 @@ in the following sections:
=== Spring Cloud LoadBalancer Caching
Apart from the basic `ServiceInstanceListSupplier` implementation that retrieves instances
via `DiscoveryClient` each time it has to choose an instance, we provide a https://github.com/ben-manes/caffeine[Caffeine-backed]
implementation.
To make use of it, you need to have `com.github.ben-manes.caffeine:caffeine` in the classpath.
The default setup includes `expireAfterWrite` set to 30 seconds and records set to soft references.
Apart from the basic `ServiceInstanceListSupplier` implementation that retrieves instances via `DiscoveryClient` each time it has to choose an instance, we provide two caching implementations.
You can set your own `TTL` value (the time after write after which entries should be expired), expressed as `Duration`, by passing a `String` compliant with the https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-conversion-duration[Spring Boot `String` to `Duration` converter syntax].
as the value of `spring.cloud.loadbalancer.cache.ttl` property.
==== https://github.com/ben-manes/caffeine[Caffeine]-backed LoadBalancer Cache Implementation
If you have `com.github.ben-manes.caffeine:caffeine` in the classpath, Caffeine-based implementation will be used.
See the <<loadbalancer-cache-configuration, LoadBalancerCacheConfiguration>> section for information on how to configure it.
You can also override the default Caffeine Cache setup for the LoadBalancer by passing your own https://static.javadoc.io/com.github.ben-manes.caffeine/caffeine/2.2.2/com/github/benmanes/caffeine/cache/CaffeineSpec.html[Caffeine Specification]
If you are using Caffeine, you can also override the default Caffeine Cache setup for the LoadBalancer by passing your own https://static.javadoc.io/com.github.ben-manes.caffeine/caffeine/2.2.2/com/github/benmanes/caffeine/cache/CaffeineSpec.html[Caffeine Specification]
in the `spring.cloud.loadbalancer.cache.caffeine.spec` property.
WARN: Passing your own Caffeine specification will override any other LoadBalancerCache settings, including `TTL`.
WARN: Passing your own Caffeine specification will override any other LoadBalancerCache settings, including <<loadbalancer-cache-configuration, General LoadBalancer Cache Configuration>> fields, such as `ttl` and `capacity`.
==== Default LoadBalancer Cache Implementation
If you do not have Caffeine in the classpath, the `DefaultLoadBalancerCache`, which comes automatically with `spring-cloud-starter-loadbalancer`, will be used.
See the <<loadbalancer-cache-configuration, LoadBalancerCacheConfiguration>> section for information on how to configure it.
TIP: To use Caffeine instead of the default cache, add the `com.github.ben-manes.caffeine:caffeine` dependency to classpath.
[[loadbalancer-cache-configuration]]
==== LoadBalancer Cache Configuration
You can set your own `ttl` value (the time after write after which entries should be expired), expressed as `Duration`, by passing a `String` compliant with the https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-conversion-duration[Spring Boot `String` to `Duration` converter syntax].
as the value of the `spring.cloud.loadbalancer.cache.ttl` property.
You can also set your own LoadBalancer cache initial capacity by setting the value of the `spring.cloud.loadbalancer.cache.capacity` property.
The default setup includes `ttl` set to 30 seconds and the default `initialCapacity` is `256`.
You can also altogether disable loadBalancer caching by setting the value of `spring.cloud.loadbalancer.cache.enabled`
to `false`.
@@ -831,7 +844,8 @@ In order to use it, just add `org.springframework.cloud:spring-cloud-starter-loa
Cloud dependencies in your build file.
NOTE: Spring Cloud LoadBalancer starter includes
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html[Spring Boot Caching].
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html[Spring Boot Caching]
and https://github.com/stoyanr[Evictor].
WARNING: If you have both Ribbon and Spring Cloud LoadBalancer int the classpath, in order to maintain
backward compatibility, Ribbon-based implementations will be used by default. In order

View File

@@ -27,6 +27,7 @@
</scm>
<properties>
<bintray.package>commons</bintray.package>
<evictor.version>1.0.0</evictor.version>
</properties>
<build>
<plugins>

View File

@@ -1,227 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>Spring Cloud Commons</name>
<description>Spring Cloud Commons</description>
<url>https://projects.spring.io/spring-cloud/spring-cloud-commons/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-commons</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
<version>1.0.7.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-crypto</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.4.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.6.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>3.6.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -68,6 +68,7 @@
<properties>
<okhttp3.version>3.6.0</okhttp3.version>
<apachehttpclient.version>4.5.4</apachehttpclient.version>
<evictor.version>1.0.0</evictor.version>
</properties>
<dependencies>
<dependency>

View File

@@ -1,138 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context-integration-tests</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>spring-cloud-context-integration-tests</name>
<description>Spring Cloud Context</description>
<url>https://projects.spring.io/spring-cloud/spring-cloud-context-integration-tests/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context-integration-tests</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context-integration-tests</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-context-integration-tests</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -1,172 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>Spring Cloud Context</name>
<description>Spring Cloud Context</description>
<url>https://projects.spring.io/spring-cloud/spring-cloud-context/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-context</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>log4j-to-slf4j</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
<version>1.0.7.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-crypto</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -1,173 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>Spring Cloud Load Balancer</name>
<description>Spring Cloud Balancer</description>
<url>https://projects.spring.io/spring-cloud/spring-cloud-loadbalancer/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-loadbalancer</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-loadbalancer</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-loadbalancer</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>log4j-to-slf4j</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.3.0.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.projectreactor.addons</groupId>
<artifactId>reactor-extra</artifactId>
<version>3.3.0.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.8.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -3,7 +3,6 @@
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
@@ -68,6 +67,12 @@
<artifactId>caffeine</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.stoyanr</groupId>
<artifactId>evictor</artifactId>
<version>${evictor.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@@ -29,6 +29,9 @@ import static org.springframework.cloud.loadbalancer.core.CachingServiceInstance
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
* @see <a href="https://github.com/ben-manes/caffeine>Caffeine</a>
* @see CaffeineCacheManager
* @see Caffeine
*/
public class CaffeineBasedLoadBalancerCacheManager extends CaffeineCacheManager
implements LoadBalancerCacheManager {
@@ -40,8 +43,8 @@ public class CaffeineBasedLoadBalancerCacheManager extends CaffeineCacheManager
setCacheSpecification(properties.getCaffeine().getSpec());
}
else {
setCaffeine(Caffeine.newBuilder().expireAfterWrite(properties.getTtl())
.softValues());
setCaffeine(Caffeine.newBuilder().initialCapacity(properties.getCapacity())
.expireAfterWrite(properties.getTtl()).softValues());
}
}

View File

@@ -0,0 +1,176 @@
/*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.loadbalancer.cache;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import javax.validation.constraints.Null;
import com.stoyanr.evictor.ConcurrentMapWithTimedEviction;
import com.stoyanr.evictor.map.ConcurrentHashMapWithTimedEviction;
import com.stoyanr.evictor.scheduler.DelayedTaskEvictionScheduler;
import org.springframework.cache.Cache;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.AbstractValueAdaptingCache;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* A default {@link Cache} implementation used by Spring Cloud LoadBalancer. The current
* implementation uses {@link ConcurrentMapWithTimedEviction} underneath. Based on
* {@link ConcurrentMapCache}.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
* @see <a href="https://github.com/stoyanr/Evictor">Evictor</a>
* @see ConcurrentMapWithTimedEviction
* @see ConcurrentMapCache
*/
public class DefaultLoadBalancerCache extends AbstractValueAdaptingCache {
private final String name;
private final ConcurrentMapWithTimedEviction<Object, Object> cache;
private final long evictMs;
DefaultLoadBalancerCache(String name,
ConcurrentMapWithTimedEviction<Object, Object> cache, long evictMs,
boolean allowNullValues) {
super(allowNullValues);
Assert.notNull(name, "Name must not be null");
Assert.notNull(cache, "Cache must not be null");
this.name = name;
this.cache = cache;
this.evictMs = evictMs;
}
/**
* Create a new DefaultCache with the specified name.
* @param name the name of the cache
*/
public DefaultLoadBalancerCache(String name) {
this(name, new ConcurrentHashMapWithTimedEviction<>(256,
new DelayedTaskEvictionScheduler<>()), 0, true);
}
/**
* Create a new DefaultCache with the specified name.
* @param name the name of the cache
* @param evictMs default time to evict the entries
* {@link ConcurrentMapWithTimedEviction}
* @param allowNullValues whether to accept and convert {@code null} values for this
* cache
*/
public DefaultLoadBalancerCache(String name, long evictMs, boolean allowNullValues) {
this(name, new ConcurrentHashMapWithTimedEviction<>(256,
new DelayedTaskEvictionScheduler<>()), evictMs, allowNullValues);
}
/**
* Create a new EvictorCache with the specified name.
* @param name the name of the cache
* @param allowNullValues whether to accept and convert {@code null} values for this
* cache
*/
public DefaultLoadBalancerCache(String name, boolean allowNullValues) {
this(name, new ConcurrentHashMapWithTimedEviction<>(256,
new DelayedTaskEvictionScheduler<>()), 0, allowNullValues);
}
@Override
@Null
protected Object lookup(Object key) {
return cache.get(key);
}
@Override
public String getName() {
return name;
}
@Override
public ConcurrentMap<Object, Object> getNativeCache() {
return cache;
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public <T> T get(Object key, Callable<T> valueLoader) {
return (T) fromStoreValue(cache.computeIfAbsent(key, k -> {
try {
return toStoreValue(valueLoader.call());
}
catch (Throwable ex) {
throw new ValueRetrievalException(key, valueLoader, ex);
}
}));
}
public void put(Object key, @Nullable Object value, long evictMs) {
cache.put(key, toStoreValue(value), evictMs);
}
@Override
@Nullable
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
Object existing = cache.putIfAbsent(key, toStoreValue(value), evictMs);
return toValueWrapper(existing);
}
@Nullable
public ValueWrapper putIfAbsent(Object key, @Nullable Object value, long evictMs) {
Object existing = cache.putIfAbsent(key, toStoreValue(value), evictMs);
return toValueWrapper(existing);
}
@Override
public void put(Object key, @Nullable Object value) {
cache.put(key, toStoreValue(value), evictMs);
}
@Override
public void evict(Object key) {
cache.remove(key);
}
@Override
public boolean evictIfPresent(Object key) {
return (cache.remove(key) != null);
}
@Override
public void clear() {
cache.clear();
}
@Override
public boolean invalidate() {
boolean notEmpty = !cache.isEmpty();
cache.clear();
return notEmpty;
}
// Visible for tests
long getEvictMs() {
return evictMs;
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.loadbalancer.cache;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import com.stoyanr.evictor.map.ConcurrentHashMapWithTimedEviction;
import com.stoyanr.evictor.scheduler.DelayedTaskEvictionScheduler;
import org.springframework.cache.Cache;
import org.springframework.lang.Nullable;
import static org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME;
/**
* An {@link DefaultLoadBalancerCache}-based {@link LoadBalancerCacheManager}
* implementation.
*
* NOTE: This is a very basic implementation as required for the LoadBalancer caching
* mechanism at the moment. The underlying implementation can be modified in future to
* allow for passing different properties per cache name.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
* @see <a href="https://github.com/stoyanr/Evictor">Evictor</a>
* @see ConcurrentHashMapWithTimedEviction
*/
public class DefaultLoadBalancerCacheManager implements LoadBalancerCacheManager {
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
public DefaultLoadBalancerCacheManager(
LoadBalancerCacheProperties loadBalancerCacheProperties,
String... cacheNames) {
cacheMap.putAll(createCaches(cacheNames, loadBalancerCacheProperties).stream()
.collect(Collectors.toMap(DefaultLoadBalancerCache::getName,
cache -> cache)));
}
public DefaultLoadBalancerCacheManager(
LoadBalancerCacheProperties loadBalancerCacheProperties) {
this(loadBalancerCacheProperties, SERVICE_INSTANCE_CACHE_NAME);
}
private Set<DefaultLoadBalancerCache> createCaches(String[] cacheNames,
LoadBalancerCacheProperties loadBalancerCacheProperties) {
return Arrays.stream(cacheNames).distinct()
.map(name -> new DefaultLoadBalancerCache(name,
new ConcurrentHashMapWithTimedEviction<>(
loadBalancerCacheProperties.getCapacity(),
new DelayedTaskEvictionScheduler<>()),
loadBalancerCacheProperties.getTtl().toMillis(), false))
.collect(Collectors.toSet());
}
@Override
@Nullable
public Cache getCache(String name) {
return cacheMap.get(name);
}
@Override
public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(cacheMap.keySet());
}
}

View File

@@ -22,6 +22,7 @@ import org.springframework.cache.CacheManager;
* A marker interface for Spring Cloud LoadBalancer-specific {@link CacheManager} beans.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
*/
public interface LoadBalancerCacheManager extends CacheManager {

View File

@@ -41,6 +41,11 @@ public class LoadBalancerCacheProperties {
*/
private Duration ttl = Duration.ofSeconds(30);
/**
* Initial cache capacity expressed as int.
*/
private int capacity = 256;
public Caffeine getCaffeine() {
return caffeine;
}
@@ -57,6 +62,14 @@ public class LoadBalancerCacheProperties {
this.ttl = ttl;
}
int getCapacity() {
return capacity;
}
void setCapacity(int capacity) {
this.capacity = capacity;
}
/**
* Caffeine-specific LoadBalancer cache properties. NOTE: Passing your own Caffeine
* specification will override any other LoadBalancerCache settings, including TTL.

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.loadbalancer.config;
import javax.annotation.PostConstruct;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.stoyanr.evictor.ConcurrentMapWithTimedEviction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -32,6 +33,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheAspectSupport;
import org.springframework.cloud.loadbalancer.cache.CaffeineBasedLoadBalancerCacheManager;
import org.springframework.cloud.loadbalancer.cache.DefaultLoadBalancerCacheManager;
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheProperties;
import org.springframework.context.annotation.Bean;
@@ -39,15 +41,15 @@ import org.springframework.context.annotation.Configuration;
/**
* An AutoConfiguration that automatically enables caching when when Spring Boot, and
* Spring Framework Cache support and Caffeine classes are present and warns if Caffeine
* is not present (we are only warning about Caffeine because the other dependencies are
* in spring-cloud-starter-loadbalancer).
* Spring Framework Cache support are present. If Caffeine is present in the classpath, it
* will be used for loadbalancer caching. If not, a default cache will be used.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
* @see CacheManager
* @see CacheAutoConfiguration
* @see CacheAspectSupport
* @see <a href="https://github.com/ben-manes/caffeine>Caffeine</a>
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ CacheManager.class, CacheAutoConfiguration.class })
@@ -77,8 +79,8 @@ public class LoadBalancerCacheAutoConfiguration {
void logWarning() {
if (LOG.isWarnEnabled()) {
LOG.warn(
"Spring Cloud LoadBalancer is currently working without cache. To enable cache, add "
+ "com.github.ben-manes.caffeine:caffeine dependency to classpath.");
"Spring Cloud LoadBalancer is currently working with default default cache. "
+ "You can switch to using Caffeine cache, by adding it to the classpath.");
}
}
@@ -86,15 +88,29 @@ public class LoadBalancerCacheAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Caffeine.class)
protected static class LoadBalancerCacheManagerConfiguration {
protected static class CaffeineLoadBalancerCacheManagerConfiguration {
@Bean(autowireCandidate = false)
@ConditionalOnMissingBean
LoadBalancerCacheManager loadBalancerCacheManager(
LoadBalancerCacheManager caffeineLoadBalancerCacheManager(
LoadBalancerCacheProperties cacheProperties) {
return new CaffeineBasedLoadBalancerCacheManager(cacheProperties);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("com.github.benmanes.caffeine.cache.Caffeine")
@ConditionalOnClass(ConcurrentMapWithTimedEviction.class)
protected static class DefaultLoadBalancerCacheManagerConfiguration {
@Bean(autowireCandidate = false)
@ConditionalOnMissingBean
LoadBalancerCacheManager defaultLoadBalancerCacheManager(
LoadBalancerCacheProperties cacheProperties) {
return new DefaultLoadBalancerCacheManager(cacheProperties);
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.loadbalancer.cache;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.cache.CacheManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME;
/**
* Tests for {@link DefaultLoadBalancerCacheManager}.
*
* @author Olga Maciaszek-Sharma
*/
class DefaultLoadBalancerCacheManagerTests {
@SuppressWarnings("ConstantConditions")
@Test
void shouldCreateLoadBalancerCacheFromProperties() {
LoadBalancerCacheProperties properties = new LoadBalancerCacheProperties();
properties.setTtl(Duration.ofMinutes(5));
properties.setCapacity(128);
DefaultLoadBalancerCacheManager cacheManager = new DefaultLoadBalancerCacheManager(
properties);
assertThat(cacheManager.getCacheNames()).hasSize(1);
assertThat(cacheManager.getCache(SERVICE_INSTANCE_CACHE_NAME))
.isInstanceOf(DefaultLoadBalancerCache.class);
assertThat(((DefaultLoadBalancerCache) cacheManager
.getCache(SERVICE_INSTANCE_CACHE_NAME)).getEvictMs()).isEqualTo(300000);
}
@Test
void shouldNotThrowExceptionOnDuplicateCacheName() {
LoadBalancerCacheProperties properties = new LoadBalancerCacheProperties();
assertThatCode(
() -> new DefaultLoadBalancerCacheManager(properties, "test", "test"))
.doesNotThrowAnyException();
}
@Test
void shouldOnlyCreateOneCacheWithGivenName() {
LoadBalancerCacheProperties properties = new LoadBalancerCacheProperties();
CacheManager cacheManager = new DefaultLoadBalancerCacheManager(properties,
"test", "test");
assertThat(cacheManager.getCacheNames()).hasSize(1);
assertThat(cacheManager.getCache("test"))
.isInstanceOf(DefaultLoadBalancerCache.class);
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.loadbalancer.cache;
import com.stoyanr.evictor.map.ConcurrentHashMapWithTimedEviction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link DefaultLoadBalancerCache}.
*
* @author Olga Maciaszek-Sharma
*/
@ExtendWith(MockitoExtension.class)
class DefaultLoadBalancerCacheTests {
@Test
void shouldAllowNullValuesByDefault() {
DefaultLoadBalancerCache cache = new DefaultLoadBalancerCache("test");
assertThatCode(() -> cache.put("testKey", null)).doesNotThrowAnyException();
}
@Test
void shouldThrowExceptionIfNullPutWithNonNullSetup() {
DefaultLoadBalancerCache cache = new DefaultLoadBalancerCache("test", false);
assertThatIllegalArgumentException().isThrownBy(() -> cache.put("testKey", null))
.withMessageContaining(
"Cache 'test' is configured to not allow null values but null was provided");
}
@Test
void shouldNotEvictEntriesByDefault() {
DefaultLoadBalancerCache cache = new DefaultLoadBalancerCache("test");
assertThat(cache.getEvictMs()).isEqualTo(0);
}
@SuppressWarnings("unchecked")
@Test
void assertThatTtlApplied() {
ConcurrentHashMapWithTimedEviction nativeCache = mock(
ConcurrentHashMapWithTimedEviction.class);
DefaultLoadBalancerCache cache = new DefaultLoadBalancerCache("test", nativeCache,
50, true);
cache.put("testKey", "testValue");
verify(nativeCache, times(1)).put("testKey", "testValue", 50);
}
}

View File

@@ -16,15 +16,19 @@
package org.springframework.cloud.loadbalancer.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.support.NoOpCacheManager;
import org.springframework.cloud.loadbalancer.cache.DefaultLoadBalancerCacheManager;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
@@ -43,24 +47,27 @@ class LoadBalancerCacheAutoConfigurationTests {
contextRunner.run(context -> {
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(1);
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
.getCacheNames()).hasSize(1);
assertThat(context.getBean("loadBalancerCacheManager"))
assertThat(
((CacheManager) context.getBean("caffeineLoadBalancerCacheManager"))
.getCacheNames()).hasSize(1);
assertThat(context.getBean("caffeineLoadBalancerCacheManager"))
.isInstanceOf(CaffeineCacheManager.class);
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
.getCacheNames()).contains("CachingServiceInstanceListSupplierCache");
assertThat(
((CacheManager) context.getBean("caffeineLoadBalancerCacheManager"))
.getCacheNames())
.contains("CachingServiceInstanceListSupplierCache");
});
}
@Test
void loadBalancerCacheShouldNotOverrideCacheTypeSetting() {
void caffeineLoadBalancerCacheShouldNotOverrideCacheTypeSetting() {
ApplicationContextRunner contextRunner = baseApplicationRunner()
.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.cache.type=none");
contextRunner.run(context -> {
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(2);
assertThat(context.getBean("loadBalancerCacheManager"))
assertThat(context.getBean("caffeineLoadBalancerCacheManager"))
.isInstanceOf(CaffeineCacheManager.class);
assertThat(context.getBeansOfType(CacheManager.class).get("cacheManager"))
.isInstanceOf(NoOpCacheManager.class);
@@ -79,19 +86,110 @@ class LoadBalancerCacheAutoConfigurationTests {
.isInstanceOf(CaffeineCacheManager.class);
assertThat(((CacheManager) context.getBean("cacheManager")).getCacheNames())
.isEmpty();
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
assertThat(
((CacheManager) context.getBean("caffeineLoadBalancerCacheManager"))
.getCacheNames()).hasSize(1);
assertThat(
((CacheManager) context.getBean("caffeineLoadBalancerCacheManager"))
.getCacheNames())
.contains("CachingServiceInstanceListSupplierCache");
});
}
@Test
void shouldNotInstantiateCaffeineLoadBalancerCacheIfDisabled() {
ApplicationContextRunner contextRunner = baseApplicationRunner()
.withPropertyValues("spring.cloud.loadbalancer.cache.enabled=false")
.withUserConfiguration(TestConfiguration.class);
contextRunner.run(context -> {
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(1);
assertThat(context.getBean("cacheManager"))
.isInstanceOf(CaffeineCacheManager.class);
assertThat(((CacheManager) context.getBean("cacheManager")).getCacheNames())
.isEmpty();
});
}
@Test
void shouldUseDefaultCacheIfCaffeineNotInClasspath() {
ApplicationContextRunner contextRunner = noCaffeineRunner();
contextRunner.run(context -> {
assertThat(context.getBean(
LoadBalancerCacheAutoConfiguration.LoadBalancerCaffeineWarnLogger.class))
.isNotNull();
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(1);
assertThat(((CacheManager) context.getBean("defaultLoadBalancerCacheManager"))
.getCacheNames()).hasSize(1);
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
assertThat(context.getBean("defaultLoadBalancerCacheManager"))
.isInstanceOf(DefaultLoadBalancerCacheManager.class);
assertThat(((CacheManager) context.getBean("defaultLoadBalancerCacheManager"))
.getCacheNames()).contains("CachingServiceInstanceListSupplierCache");
});
}
@Test
void defaultLoadBalancerCacheShouldNotOverrideCacheTypeSetting() {
ApplicationContextRunner contextRunner = noCaffeineRunner()
.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.cache.type=none");
contextRunner.run(context -> {
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(2);
assertThat(context.getBean("defaultLoadBalancerCacheManager"))
.isInstanceOf(DefaultLoadBalancerCacheManager.class);
assertThat(context.getBeansOfType(CacheManager.class).get("cacheManager"))
.isInstanceOf(NoOpCacheManager.class);
});
}
@Test
void defaultLoadBalancerCacheShouldNotOverrideExistingCacheManager() {
ApplicationContextRunner contextRunner = noCaffeineRunner()
.withUserConfiguration(TestConfiguration.class);
contextRunner.run(context -> {
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(2);
assertThat(context.getBean("cacheManager"))
.isInstanceOf(ConcurrentMapCacheManager.class);
assertThat(((CacheManager) context.getBean("cacheManager")).getCacheNames())
.isEmpty();
assertThat(((CacheManager) context.getBean("defaultLoadBalancerCacheManager"))
.getCacheNames()).hasSize(1);
assertThat(((CacheManager) context.getBean("defaultLoadBalancerCacheManager"))
.getCacheNames()).contains("CachingServiceInstanceListSupplierCache");
});
}
@Test
void shouldNotInstantiateDefaultLoadBalancerCacheIfDisabled() {
ApplicationContextRunner contextRunner = noCaffeineRunner()
.withPropertyValues("spring.cloud.loadbalancer.cache.enabled=false")
.withUserConfiguration(TestConfiguration.class);
contextRunner.run(context -> {
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(1);
assertThat(context.getBean("cacheManager"))
.isInstanceOf(ConcurrentMapCacheManager.class);
assertThat(((CacheManager) context.getBean("cacheManager")).getCacheNames())
.isEmpty();
});
}
private ApplicationContextRunner baseApplicationRunner() {
return new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(
CacheAutoConfiguration.class, LoadBalancerCacheAutoConfiguration.class));
}
private ApplicationContextRunner noCaffeineRunner() {
return baseApplicationRunner()
.withClassLoader(new FilteredClassLoader(Caffeine.class));
}
@Configuration(proxyBeanMethods = false)
@EnableCaching
static class TestConfiguration {

View File

@@ -1,119 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>spring-cloud-starter-loadbalancer</name>
<description>Spring Cloud Starter LoadBalancer</description>
<url>https://projects.spring.io/spring-cloud</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter-loadbalancer</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter-loadbalancer</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-starter-loadbalancer</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -9,7 +9,6 @@
<relativePath>..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<name>spring-cloud-starter-loadbalancer</name>
<description>Spring Cloud Starter LoadBalancer</description>
@@ -35,5 +34,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.stoyanr</groupId>
<artifactId>evictor</artifactId>
<version>${evictor.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,141 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>spring-cloud-starter</name>
<description>Spring Cloud Starter</description>
<url>https://projects.spring.io/spring-cloud</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-starter</url>
</scm>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
<version>1.0.7.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-crypto</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -1,149 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-test-support</artifactId>
<version>2.2.0.BUILD-SNAPSHOT</version>
<name>spring-cloud-test-support</name>
<description>Spring Cloud Test Support</description>
<url>https://projects.spring.io/spring-cloud/spring-cloud-test-support/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://www.spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>Copyright 2014-2015 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.</comments>
</license>
</licenses>
<developers>
<developer>
<id>dsyer</id>
<name>Dave Syer</name>
<email>dsyer at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>sgibb</id>
<name>Spencer Gibb</name>
<email>sgibb at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>lead</role>
</roles>
</developer>
<developer>
<id>mgrzejszczak</id>
<name>Marcin Grzejszczak</name>
<email>mgrzejszczak at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>rbaxter</id>
<name>Ryan Baxter</name>
<email>rbaxter at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
<developer>
<id>omaciaszeksharma</id>
<name>Olga Maciaszek-Sharma</name>
<email>omaciaszeksharma at pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-test-support</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-test-support</developerConnection>
<url>https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-test-support</url>
</scm>
<dependencies>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
<version>1.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>3.5.4</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.1.1</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>jcl-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>