From da0e06eb7a554efe2f0993968324463374314dfc Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Mon, 25 Nov 2019 20:34:19 +0100 Subject: [PATCH] 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. --- .flattened-pom.xml | 131 ---------- .gitignore | 1 + docs/.flattened-pom.xml | 113 --------- .../main/asciidoc/spring-cloud-commons.adoc | 34 ++- pom.xml | 1 + spring-cloud-commons/.flattened-pom.xml | 227 ------------------ spring-cloud-commons/pom.xml | 1 + .../.flattened-pom.xml | 138 ----------- spring-cloud-context/.flattened-pom.xml | 172 ------------- spring-cloud-loadbalancer/.flattened-pom.xml | 173 ------------- spring-cloud-loadbalancer/pom.xml | 7 +- ...CaffeineBasedLoadBalancerCacheManager.java | 7 +- .../cache/DefaultLoadBalancerCache.java | 176 ++++++++++++++ .../DefaultLoadBalancerCacheManager.java | 87 +++++++ .../cache/LoadBalancerCacheManager.java | 1 + .../cache/LoadBalancerCacheProperties.java | 13 + .../LoadBalancerCacheAutoConfiguration.java | 30 ++- .../DefaultLoadBalancerCacheManagerTests.java | 74 ++++++ .../cache/DefaultLoadBalancerCacheTests.java | 75 ++++++ ...adBalancerCacheAutoConfigurationTests.java | 116 ++++++++- .../.flattened-pom.xml | 119 --------- spring-cloud-starter-loadbalancer/pom.xml | 6 +- spring-cloud-starter/.flattened-pom.xml | 141 ----------- spring-cloud-test-support/.flattened-pom.xml | 149 ------------ 24 files changed, 599 insertions(+), 1393 deletions(-) delete mode 100644 .flattened-pom.xml delete mode 100644 docs/.flattened-pom.xml delete mode 100644 spring-cloud-commons/.flattened-pom.xml delete mode 100644 spring-cloud-context-integration-tests/.flattened-pom.xml delete mode 100644 spring-cloud-context/.flattened-pom.xml delete mode 100644 spring-cloud-loadbalancer/.flattened-pom.xml create mode 100644 spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCache.java create mode 100644 spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheManager.java create mode 100644 spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheManagerTests.java create mode 100644 spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheTests.java delete mode 100644 spring-cloud-starter-loadbalancer/.flattened-pom.xml delete mode 100644 spring-cloud-starter/.flattened-pom.xml delete mode 100644 spring-cloud-test-support/.flattened-pom.xml diff --git a/.flattened-pom.xml b/.flattened-pom.xml deleted file mode 100644 index f95c5e4c..00000000 --- a/.flattened-pom.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-build - 2.2.0.RELEASE - - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - pom - Spring Cloud Commons Parent - Spring Cloud Commons Parent - https://projects.spring.io/spring-cloud/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git - https://github.com/spring-cloud/spring-cloud-commons - - - - spring - - - - true - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - - - false - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - - - false - - spring-releases - Spring Releases - https://repo.spring.io/release - - - - - diff --git a/.gitignore b/.gitignore index 1b8abd7d..32c1a89f 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ _site/ /spring-cloud-release-tools*.jar antrun .vscode/ +.flattened-pom.xml \ No newline at end of file diff --git a/docs/.flattened-pom.xml b/docs/.flattened-pom.xml deleted file mode 100644 index a943d960..00000000 --- a/docs/.flattened-pom.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - - org.springframework.cloud - spring-cloud-commons-docs - 2.2.0.BUILD-SNAPSHOT - pom - Spring Cloud Commons Docs - Spring Cloud Commons Docs - https://projects.spring.io/spring-cloud/spring-cloud-commons-docs/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons-docs - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons-docs - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-commons-docs - - - - org.springframework.cloud - spring-cloud-starter - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.cloud - spring-cloud-starter-loadbalancer - 2.2.0.BUILD-SNAPSHOT - compile - - - diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index 43299c83..bc6b7d13 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -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 <> 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 <> 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 <> 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 diff --git a/pom.xml b/pom.xml index 3cd01d68..8b361d2b 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ commons + 1.0.0 diff --git a/spring-cloud-commons/.flattened-pom.xml b/spring-cloud-commons/.flattened-pom.xml deleted file mode 100644 index aa25d3b8..00000000 --- a/spring-cloud-commons/.flattened-pom.xml +++ /dev/null @@ -1,227 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-commons - 2.2.0.BUILD-SNAPSHOT - Spring Cloud Commons - Spring Cloud Commons - https://projects.spring.io/spring-cloud/spring-cloud-commons/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-commons - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-commons - - - - org.springframework.boot - spring-boot-configuration-processor - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-actuator - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-web - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-webflux - 2.2.1.RELEASE - compile - true - - - org.springframework.security - spring-security-crypto - 5.2.1.RELEASE - compile - - - org.springframework.security - spring-security-rsa - 1.0.7.RELEASE - compile - - - spring-core - org.springframework - - - spring-security-crypto - org.springframework.security - - - true - - - org.springframework.integration - spring-integration-jmx - 5.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-hateoas - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-aop - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-autoconfigure-processor - 2.2.1.RELEASE - compile - true - - - org.springframework.retry - spring-retry - 1.2.4.RELEASE - compile - - - spring-core - org.springframework - - - true - - - com.jayway.jsonpath - json-path - 2.4.0 - compile - true - - - com.squareup.okhttp3 - okhttp - 3.6.0 - compile - true - - - com.squareup.okhttp3 - logging-interceptor - 3.6.0 - compile - true - - - org.apache.httpcomponents - httpclient - 4.5.4 - compile - - - commons-logging - commons-logging - - - true - - - diff --git a/spring-cloud-commons/pom.xml b/spring-cloud-commons/pom.xml index 875ca30f..35bc9f9a 100644 --- a/spring-cloud-commons/pom.xml +++ b/spring-cloud-commons/pom.xml @@ -68,6 +68,7 @@ 3.6.0 4.5.4 + 1.0.0 diff --git a/spring-cloud-context-integration-tests/.flattened-pom.xml b/spring-cloud-context-integration-tests/.flattened-pom.xml deleted file mode 100644 index c1b9d7b8..00000000 --- a/spring-cloud-context-integration-tests/.flattened-pom.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-context-integration-tests - 2.2.0.BUILD-SNAPSHOT - spring-cloud-context-integration-tests - Spring Cloud Context - https://projects.spring.io/spring-cloud/spring-cloud-context-integration-tests/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context-integration-tests - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context-integration-tests - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-context-integration-tests - - - - org.springframework.cloud - spring-cloud-context - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.boot - spring-boot-starter-actuator - 2.2.1.RELEASE - compile - - - org.springframework.boot - spring-boot-starter-web - 2.2.1.RELEASE - compile - - - org.springframework.boot - spring-boot-starter-aop - 2.2.1.RELEASE - compile - - - org.springframework.integration - spring-integration-jmx - 5.2.1.RELEASE - compile - - - org.springframework.boot - spring-boot-configuration-processor - 2.2.1.RELEASE - compile - true - - - diff --git a/spring-cloud-context/.flattened-pom.xml b/spring-cloud-context/.flattened-pom.xml deleted file mode 100644 index 0de6bf62..00000000 --- a/spring-cloud-context/.flattened-pom.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-context - 2.2.0.BUILD-SNAPSHOT - Spring Cloud Context - Spring Cloud Context - https://projects.spring.io/spring-cloud/spring-cloud-context/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-context - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-context - - - - org.springframework.boot - spring-boot-configuration-processor - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-actuator - 2.2.1.RELEASE - compile - - - log4j-to-slf4j - org.apache.logging.log4j - - - true - - - org.springframework.boot - spring-boot-starter-web - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-aop - 2.2.1.RELEASE - compile - true - - - org.springframework.security - spring-security-crypto - 5.2.1.RELEASE - compile - - - org.springframework.security - spring-security-rsa - 1.0.7.RELEASE - compile - - - spring-core - org.springframework - - - spring-security-crypto - org.springframework.security - - - true - - - org.springframework.integration - spring-integration-jmx - 5.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-autoconfigure-processor - 2.2.1.RELEASE - compile - true - - - diff --git a/spring-cloud-loadbalancer/.flattened-pom.xml b/spring-cloud-loadbalancer/.flattened-pom.xml deleted file mode 100644 index 41d4d6b9..00000000 --- a/spring-cloud-loadbalancer/.flattened-pom.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-loadbalancer - 2.2.0.BUILD-SNAPSHOT - Spring Cloud Load Balancer - Spring Cloud Balancer - https://projects.spring.io/spring-cloud/spring-cloud-loadbalancer/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-loadbalancer - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-loadbalancer - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-loadbalancer - - - - org.springframework.cloud - spring-cloud-commons - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.cloud - spring-cloud-context - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.boot - spring-boot-starter-actuator - 2.2.1.RELEASE - compile - - - log4j-to-slf4j - org.apache.logging.log4j - - - true - - - io.projectreactor - reactor-core - 3.3.0.RELEASE - compile - - - io.projectreactor.addons - reactor-extra - 3.3.0.RELEASE - compile - - - org.springframework.boot - spring-boot-autoconfigure-processor - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-configuration-processor - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-webflux - 2.2.1.RELEASE - compile - true - - - org.springframework.boot - spring-boot-starter-cache - 2.2.1.RELEASE - compile - true - - - com.github.ben-manes.caffeine - caffeine - 2.8.0 - compile - true - - - diff --git a/spring-cloud-loadbalancer/pom.xml b/spring-cloud-loadbalancer/pom.xml index 69c14c26..09e92db6 100644 --- a/spring-cloud-loadbalancer/pom.xml +++ b/spring-cloud-loadbalancer/pom.xml @@ -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"> 4.0.0 - org.springframework.cloud spring-cloud-commons-parent @@ -68,6 +67,12 @@ caffeine true + + com.stoyanr + evictor + ${evictor.version} + true + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/CaffeineBasedLoadBalancerCacheManager.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/CaffeineBasedLoadBalancerCacheManager.java index a7c40601..863ebb34 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/CaffeineBasedLoadBalancerCacheManager.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/CaffeineBasedLoadBalancerCacheManager.java @@ -29,6 +29,9 @@ import static org.springframework.cloud.loadbalancer.core.CachingServiceInstance * * @author Olga Maciaszek-Sharma * @since 2.2.0 + * @see Evictor + * @see ConcurrentMapWithTimedEviction + * @see ConcurrentMapCache + */ +public class DefaultLoadBalancerCache extends AbstractValueAdaptingCache { + + private final String name; + + private final ConcurrentMapWithTimedEviction cache; + + private final long evictMs; + + DefaultLoadBalancerCache(String name, + ConcurrentMapWithTimedEviction 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 getNativeCache() { + return cache; + } + + @SuppressWarnings("unchecked") + @Override + @Nullable + public T get(Object key, Callable 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; + } + +} diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheManager.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheManager.java new file mode 100644 index 00000000..6e70eeb4 --- /dev/null +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheManager.java @@ -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 Evictor + * @see ConcurrentHashMapWithTimedEviction + */ +public class DefaultLoadBalancerCacheManager implements LoadBalancerCacheManager { + + private final ConcurrentMap 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 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 getCacheNames() { + return Collections.unmodifiableSet(cacheMap.keySet()); + } + +} diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheManager.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheManager.java index ae8511b0..25e70039 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheManager.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheManager.java @@ -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 { diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheProperties.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheProperties.java index f396b831..731aceef 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheProperties.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/cache/LoadBalancerCacheProperties.java @@ -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. diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfiguration.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfiguration.java index 265e44fb..78a425b6 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfiguration.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfiguration.java @@ -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 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); + } + +} diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheTests.java new file mode 100644 index 00000000..289f8f4d --- /dev/null +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/cache/DefaultLoadBalancerCacheTests.java @@ -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); + } + +} diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfigurationTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfigurationTests.java index 4fdebe8a..e2d342e2 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfigurationTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfigurationTests.java @@ -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 { diff --git a/spring-cloud-starter-loadbalancer/.flattened-pom.xml b/spring-cloud-starter-loadbalancer/.flattened-pom.xml deleted file mode 100644 index 2a1b5fab..00000000 --- a/spring-cloud-starter-loadbalancer/.flattened-pom.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-starter-loadbalancer - 2.2.0.BUILD-SNAPSHOT - spring-cloud-starter-loadbalancer - Spring Cloud Starter LoadBalancer - https://projects.spring.io/spring-cloud - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter-loadbalancer - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter-loadbalancer - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-starter-loadbalancer - - - - org.springframework.cloud - spring-cloud-starter - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.cloud - spring-cloud-loadbalancer - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.boot - spring-boot-starter-cache - 2.2.1.RELEASE - compile - - - diff --git a/spring-cloud-starter-loadbalancer/pom.xml b/spring-cloud-starter-loadbalancer/pom.xml index b579826c..ca4b2eb6 100644 --- a/spring-cloud-starter-loadbalancer/pom.xml +++ b/spring-cloud-starter-loadbalancer/pom.xml @@ -9,7 +9,6 @@ .. 4.0.0 - spring-cloud-starter-loadbalancer spring-cloud-starter-loadbalancer Spring Cloud Starter LoadBalancer @@ -35,5 +34,10 @@ org.springframework.boot spring-boot-starter-cache + + com.stoyanr + evictor + ${evictor.version} + \ No newline at end of file diff --git a/spring-cloud-starter/.flattened-pom.xml b/spring-cloud-starter/.flattened-pom.xml deleted file mode 100644 index de845787..00000000 --- a/spring-cloud-starter/.flattened-pom.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - - org.springframework.cloud - spring-cloud-starter - 2.2.0.BUILD-SNAPSHOT - spring-cloud-starter - Spring Cloud Starter - https://projects.spring.io/spring-cloud - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-starter - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-starter - - - - org.springframework.boot - spring-boot-starter - 2.2.1.RELEASE - compile - - - org.springframework.cloud - spring-cloud-context - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.cloud - spring-cloud-commons - 2.2.0.BUILD-SNAPSHOT - compile - - - org.springframework.security - spring-security-rsa - 1.0.7.RELEASE - compile - - - spring-core - org.springframework - - - spring-security-crypto - org.springframework.security - - - - - org.projectlombok - lombok - 1.18.10 - compile - true - - - diff --git a/spring-cloud-test-support/.flattened-pom.xml b/spring-cloud-test-support/.flattened-pom.xml deleted file mode 100644 index b10a93d8..00000000 --- a/spring-cloud-test-support/.flattened-pom.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-commons-parent - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-test-support - 2.2.0.BUILD-SNAPSHOT - spring-cloud-test-support - Spring Cloud Test Support - https://projects.spring.io/spring-cloud/spring-cloud-test-support/ - - Pivotal Software, Inc. - https://www.spring.io - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0 - 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. - - - - - dsyer - Dave Syer - dsyer at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - sgibb - Spencer Gibb - sgibb at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - lead - - - - mgrzejszczak - Marcin Grzejszczak - mgrzejszczak at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - rbaxter - Ryan Baxter - rbaxter at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - omaciaszeksharma - Olga Maciaszek-Sharma - omaciaszeksharma at pivotal.io - Pivotal Software, Inc. - https://www.spring.io - - developer - - - - - scm:git:git://github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-test-support - scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git/spring-cloud-test-support - https://github.com/spring-cloud/spring-cloud-commons/spring-cloud-test-support - - - - org.apache.maven.resolver - maven-resolver-connector-basic - 1.1.1 - compile - - - org.apache.maven.resolver - maven-resolver-impl - 1.1.1 - compile - - - org.apache.maven - maven-resolver-provider - 3.5.4 - compile - - - guava - com.google.guava - - - - - org.apache.maven.resolver - maven-resolver-transport-http - 1.1.1 - compile - - - jcl-over-slf4j - org.slf4j - - - - - junit - junit - 4.12 - compile - - - org.springframework - spring-core - 5.2.1.RELEASE - compile - - -