caffeine cache for loadbalancer Fix gh 638 (#643)
* Add Caffeine-based loadBalancerCacheManager. * Add more tests. * Fix test. * Only enable loadBalancer caching if caffeine is on classpath. Warn if caffeine is not on classpath. * Add javadocs. * Add docs. Change property name. * Fix configuration. * Fix after code review. Add another constructor to CaffeineBasedLoadBalancerCacheManager, allowing to pass cache name, in order to support alternative ServiceInstanceListSupplierImplementations.
This commit is contained in:
committed by
GitHub
parent
d4cc825aa0
commit
bf6b31ee8a
@@ -801,6 +801,28 @@ in the following sections:
|
||||
* <<webclinet-loadbalancer-client, Spring WebClient as a Load Balancer Client>>
|
||||
* <<webflux-with-reactive-loadbalancer,Spring WebFlux WebClient with `ReactorLoadBalancerExchangeFilterFunction`>>
|
||||
|
||||
=== 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.
|
||||
|
||||
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.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Duration.html#parse(java.lang.CharSequence)[`Duration` API]
|
||||
as the value of `spring.cloud.loadbalancer.cache.ttl` property.
|
||||
|
||||
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`.
|
||||
|
||||
You can also altogether disable loadBalancer caching by setting the value of `spring.cloud.loadbalancer.cache.enabled`
|
||||
to `false`.
|
||||
|
||||
WARNING: Although the basic, non-cached, implementation is useful for prototyping and testing, it's much less efficient
|
||||
than the cached versions, so we recommend always using the cached version in production.
|
||||
|
||||
[[spring-cloud-loadbalancer-starter]]
|
||||
=== Spring Cloud LoadBalancer starter
|
||||
|
||||
@@ -808,11 +830,8 @@ We also provide a starter that allows you to easily add Spring Cloud LoadBalance
|
||||
In order to use it, just add `org.springframework.cloud:spring-cloud-starter-loadbalancer` to your Spring
|
||||
Cloud dependencies in your build file.
|
||||
|
||||
WARNING: In order to make use of the more efficient cached version of `ServiceInstanceListSupplier`,
|
||||
`spring-cloud-starter-loadbalancer` will *enable caching* by default.
|
||||
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html[Spring Boot Caching]
|
||||
mechanism will be used under the hood. If you don't want caching to be used, you can set
|
||||
the value of `spring.cache.type` to `none`.
|
||||
NOTE: Spring Cloud LoadBalancer starter includes
|
||||
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html[Spring Boot Caching].
|
||||
|
||||
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
|
||||
|
||||
@@ -61,7 +61,12 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -78,10 +83,5 @@
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -20,13 +20,13 @@ import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
|
||||
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier;
|
||||
@@ -36,6 +36,7 @@ import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceSupplier;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -73,12 +74,14 @@ public class LoadBalancerClientConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
|
||||
ReactiveDiscoveryClient discoveryClient, Environment env,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
ApplicationContext context) {
|
||||
DiscoveryClientServiceInstanceListSupplier delegate = new DiscoveryClientServiceInstanceListSupplier(
|
||||
discoveryClient, env);
|
||||
if (cacheManager.getIfAvailable() != null) {
|
||||
ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context
|
||||
.getBeanProvider(LoadBalancerCacheManager.class);
|
||||
if (cacheManagerProvider.getIfAvailable() != null) {
|
||||
return new CachingServiceInstanceListSupplier(delegate,
|
||||
cacheManager.getIfAvailable());
|
||||
cacheManagerProvider.getIfAvailable());
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
@@ -88,12 +91,14 @@ public class LoadBalancerClientConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstanceSupplier discoveryClientServiceInstanceSupplier(
|
||||
ReactiveDiscoveryClient discoveryClient, Environment env,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
ApplicationContext context) {
|
||||
DiscoveryClientServiceInstanceSupplier delegate = new DiscoveryClientServiceInstanceSupplier(
|
||||
discoveryClient, env);
|
||||
if (cacheManager.getIfAvailable() != null) {
|
||||
ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context
|
||||
.getBeanProvider(LoadBalancerCacheManager.class);
|
||||
if (cacheManagerProvider.getIfAvailable() != null) {
|
||||
return new CachingServiceInstanceSupplier(delegate,
|
||||
cacheManager.getIfAvailable());
|
||||
cacheManagerProvider.getIfAvailable());
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
@@ -110,12 +115,14 @@ public class LoadBalancerClientConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
|
||||
DiscoveryClient discoveryClient, Environment env,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
ApplicationContext context) {
|
||||
DiscoveryClientServiceInstanceListSupplier delegate = new DiscoveryClientServiceInstanceListSupplier(
|
||||
discoveryClient, env);
|
||||
if (cacheManager.getIfAvailable() != null) {
|
||||
ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context
|
||||
.getBeanProvider(LoadBalancerCacheManager.class);
|
||||
if (cacheManagerProvider.getIfAvailable() != null) {
|
||||
return new CachingServiceInstanceListSupplier(delegate,
|
||||
cacheManager.getIfAvailable());
|
||||
cacheManagerProvider.getIfAvailable());
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
@@ -125,12 +132,14 @@ public class LoadBalancerClientConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstanceSupplier discoveryClientServiceInstanceSupplier(
|
||||
DiscoveryClient discoveryClient, Environment env,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
ApplicationContext context) {
|
||||
DiscoveryClientServiceInstanceSupplier delegate = new DiscoveryClientServiceInstanceSupplier(
|
||||
discoveryClient, env);
|
||||
if (cacheManager.getIfAvailable() != null) {
|
||||
ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context
|
||||
.getBeanProvider(LoadBalancerCacheManager.class);
|
||||
if (cacheManagerProvider.getIfAvailable() != null) {
|
||||
return new CachingServiceInstanceSupplier(delegate,
|
||||
cacheManager.getIfAvailable());
|
||||
cacheManagerProvider.getIfAvailable());
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME;
|
||||
|
||||
/**
|
||||
* A Spring Cloud LoadBalancer specific implementation of {@link CaffeineCacheManager} that
|
||||
* implements the {@link LoadBalancerCacheManager} marker interface.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class CaffeineBasedLoadBalancerCacheManager extends CaffeineCacheManager
|
||||
implements LoadBalancerCacheManager {
|
||||
|
||||
public CaffeineBasedLoadBalancerCacheManager(String cacheName,
|
||||
LoadBalancerCacheProperties properties) {
|
||||
super(cacheName);
|
||||
if (!StringUtils.isEmpty(properties.getCaffeine().getSpec())) {
|
||||
setCacheSpecification(properties.getCaffeine().getSpec());
|
||||
}
|
||||
else {
|
||||
setCaffeine(Caffeine.newBuilder().expireAfterWrite(properties.getTtl())
|
||||
.softValues());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public CaffeineBasedLoadBalancerCacheManager(LoadBalancerCacheProperties properties) {
|
||||
this(SERVICE_INSTANCE_CACHE_NAME, properties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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 org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
* A marker interface for Spring Cloud LoadBalancer-specific {@link CacheManager} beans.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public interface LoadBalancerCacheManager extends CacheManager {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Spring Cloud LoadBalancer cache properties.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.loadbalancer.cache")
|
||||
public class LoadBalancerCacheProperties {
|
||||
|
||||
private Caffeine caffeine = new Caffeine();
|
||||
|
||||
/**
|
||||
* Time To Live - time counted from writing of the record, after which cache entries
|
||||
* are expired, expressed as a {@link Duration}. The property {@link String} has to be
|
||||
* in keeping with the appropriate syntax as specified in
|
||||
* {@link Duration#parse(CharSequence)}.
|
||||
*/
|
||||
private Duration ttl = Duration.ofSeconds(30);
|
||||
|
||||
public Caffeine getCaffeine() {
|
||||
return caffeine;
|
||||
}
|
||||
|
||||
public void setCaffeine(Caffeine caffeine) {
|
||||
this.caffeine = caffeine;
|
||||
}
|
||||
|
||||
public Duration getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
public void setTtl(String ttl) {
|
||||
this.ttl = Duration.parse(ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Caffeine-specific LoadBalancer cache properties.
|
||||
* NOTE: Passing your own Caffeine specification will override any other LoadBalancerCache settings,
|
||||
* including TTL.
|
||||
*/
|
||||
public static class Caffeine {
|
||||
|
||||
/**
|
||||
* The spec to use to create caches. See CaffeineSpec for more details on the spec
|
||||
* format.
|
||||
*/
|
||||
private String spec = "";
|
||||
|
||||
public String getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
public void setSpec(String spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,29 +16,85 @@
|
||||
|
||||
package org.springframework.cloud.loadbalancer.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.CacheAspectSupport;
|
||||
import org.springframework.cloud.loadbalancer.cache.CaffeineBasedLoadBalancerCacheManager;
|
||||
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
|
||||
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* An AutoConfiguration that automatically enables caching when when Spring Boot and
|
||||
* Spring Framework Cache support classes are present.
|
||||
* 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).
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.0
|
||||
* @see CacheManager
|
||||
* @see CacheAutoConfiguration
|
||||
* @see CacheAspectSupport
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ CacheManager.class, CacheAutoConfiguration.class })
|
||||
@ConditionalOnMissingBean(CacheAspectSupport.class)
|
||||
@EnableCaching
|
||||
@AutoConfigureBefore(CacheAutoConfiguration.class)
|
||||
@AutoConfigureAfter(CacheAutoConfiguration.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.cache.enabled",
|
||||
matchIfMissing = true)
|
||||
@EnableConfigurationProperties(LoadBalancerCacheProperties.class)
|
||||
public class LoadBalancerCacheAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingClass("com.github.benmanes.caffeine.cache.Caffeine")
|
||||
protected static class LoadBalancerCacheManagerWarnConfiguration {
|
||||
|
||||
@Bean
|
||||
LoadBalancerCaffeineWarnLogger caffeineWarnLogger() {
|
||||
return new LoadBalancerCaffeineWarnLogger();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class LoadBalancerCaffeineWarnLogger {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(LoadBalancerCaffeineWarnLogger.class);
|
||||
|
||||
@PostConstruct
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(Caffeine.class)
|
||||
protected static class LoadBalancerCacheManagerConfiguration {
|
||||
|
||||
@Bean(autowireCandidate = false)
|
||||
@ConditionalOnMissingBean
|
||||
LoadBalancerCacheManager loadBalancerCacheManager(
|
||||
LoadBalancerCacheProperties cacheProperties) {
|
||||
return new CaffeineBasedLoadBalancerCacheManager(cacheProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
|
||||
package org.springframework.cloud.loadbalancer.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
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.support.NoOpCacheManager;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -40,31 +39,63 @@ class LoadBalancerCacheAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
void shouldAutoEnableCaching() {
|
||||
AnnotationConfigApplicationContext context = setup("");
|
||||
assertThat(context.getBeansOfType(CacheManager.class)).isNotEmpty();
|
||||
assertThat(context.getBeansOfType(CacheManager.class).get("cacheManager"))
|
||||
.isNotInstanceOf(NoOpCacheManager.class);
|
||||
ApplicationContextRunner contextRunner = baseApplicationRunner();
|
||||
|
||||
contextRunner.run(context -> {
|
||||
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(1);
|
||||
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
|
||||
.getCacheNames()).hasSize(1);
|
||||
assertThat(context.getBean("loadBalancerCacheManager"))
|
||||
.isInstanceOf(CaffeineCacheManager.class);
|
||||
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
|
||||
.getCacheNames()).contains("CachingServiceInstanceListSupplierCache");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseNoOpCacheIfCacheTypeNone() {
|
||||
AnnotationConfigApplicationContext context = setup("spring.cache.type=none");
|
||||
assertThat(context.getBeansOfType(CacheManager.class)).isNotEmpty();
|
||||
assertThat(context.getBeansOfType(CacheManager.class).get("cacheManager"))
|
||||
.isInstanceOf(NoOpCacheManager.class);
|
||||
void loadBalancerCacheShouldNotOverrideCacheTypeSetting() {
|
||||
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"))
|
||||
.isInstanceOf(CaffeineCacheManager.class);
|
||||
assertThat(context.getBeansOfType(CacheManager.class).get("cacheManager"))
|
||||
.isInstanceOf(NoOpCacheManager.class);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private AnnotationConfigApplicationContext setup(String property) {
|
||||
List<Class> config = new ArrayList<>();
|
||||
config.add(LoadBalancerCacheAutoConfiguration.class);
|
||||
config.add(CacheAutoConfiguration.class);
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
if (StringUtils.hasText(property)) {
|
||||
TestPropertyValues.of(property).applyTo(context);
|
||||
}
|
||||
context.register(config.toArray(new Class[0]));
|
||||
context.refresh();
|
||||
return context;
|
||||
@Test
|
||||
void loadBalancerCacheShouldNotOverrideExistingCaffeineCacheManager() {
|
||||
ApplicationContextRunner contextRunner = baseApplicationRunner()
|
||||
.withUserConfiguration(TestConfiguration.class);
|
||||
|
||||
contextRunner.run(context -> {
|
||||
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(2);
|
||||
assertThat(context.getBean("cacheManager"))
|
||||
.isInstanceOf(CaffeineCacheManager.class);
|
||||
assertThat(((CacheManager) context.getBean("cacheManager")).getCacheNames())
|
||||
.isEmpty();
|
||||
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
|
||||
.getCacheNames()).hasSize(1);
|
||||
assertThat(((CacheManager) context.getBean("loadBalancerCacheManager"))
|
||||
.getCacheNames()).contains("CachingServiceInstanceListSupplierCache");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private ApplicationContextRunner baseApplicationRunner() {
|
||||
return new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(
|
||||
CacheAutoConfiguration.class, LoadBalancerCacheAutoConfiguration.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableCaching
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user