spring-cloud / spring-cloud/spring-cloud-gateway
LocalResponseCacheGatewayFilterFactory recreates Caffeine cache on every route refresh
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 4.9k
- Forks
- 3.5k
- Avg merge
- 20h 57m
- Merged PRs (30d)
- 8
Description
Description
LocalResponseCacheGatewayFilterFactory appears to recreate and register a new Caffeine cache every time Gateway routes are refreshed.
When Spring Cloud Gateway is used with Eureka DiscoveryClient, routes may be refreshed periodically. In my case, this happens every 30 seconds from the following thread:
DiscoveryClient-CacheRefreshExecutor
Each refresh causes LocalResponseCacheGatewayFilterFactory.apply() to be invoked again.
The following code creates and registers a new cache every time:
Caffeine caffeine = LocalResponseCacheUtils.createCaffeine(cacheProperties);
String cacheName = config.getRouteId() + "-cache";
caffeineCacheManager.registerCustomCache(
cacheName,
caffeine.build()
);
This produces the following log every 30 seconds:
13:32:25.740 [DiscoveryClient-CacheRefreshExecutor-%d]
INFO LocalResponseCacheUtils - Initializing Caffeine
13:32:55.779 [DiscoveryClient-CacheRefreshExecutor-%d]
INFO LocalResponseCacheUtils - Initializing Caffeine
Expected behavior
The cache associated with a route should be reused when the route is rebuilt and the cache configuration has not changed.
A route refresh should not recreate the underlying Caffeine cache or remove existing cached responses.
Actual behavior
apply() creates a new Caffeine cache and calls registerCustomCache() again using the same cache name:
String cacheName = config.getRouteId() + "-cache";
Depending on the behavior of CaffeineCacheManager.registerCustomCache(), this may replace the existing cache and clear all cached entries.
Even when the cache is not replaced, a new unused Caffeine cache instance is still created during every route refresh.
Steps to reproduce
- Configure Spring Cloud Gateway with Eureka DiscoveryClient.
- Enable the local response cache filter.
- Configure a route with
LocalResponseCache. - Start the gateway.
- Wait for Eureka registry refresh.
- Observe that
LocalResponseCacheUtils.createCaffeine()is invoked repeatedly.
Example configuration:
spring:
cloud:
gateway:
filter:
local-response-cache:
enabled: true
eureka:
client:
registry-fetch-interval-seconds: 30
Suggested fix
Before creating a new cache, check whether a cache with the same name already exists:
String cacheName = config.getRouteId() + "-cache";
Cache routeCache = caffeineCacheManager.getCache(cacheName);
if (routeCache == null) {
Caffeine caffeine =
LocalResponseCacheUtils.createCaffeine(cacheProperties);
caffeineCacheManager.registerCustomCache(
cacheName,
caffeine.build()
);
routeCache = caffeineCacheManager.getCache(cacheName);
}
A more complete solution could recreate the cache only when the route cache configuration, such as TTL or size, has actually changed.
Environment
Spring Cloud Gateway version: (v3.4.4)
Spring Boot version: (v3.4.4)
Spring Cloud version: (v3.4.4)
Java version: 21
Discovery client: Eureka
Additional context
Route refresh itself is expected behavior. The concern is that the filter factory is not idempotent and creates a new cache whenever the route definition is rebuilt.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at LocalResponseCacheGatewayFilterFactory.apply() and trace LocalResponseCacheUtils.createCaffeine() with CaffeineCacheManager.registerCustomCache(). Reproduce with Eureka route refreshes and verify that unchanged route configuration reuses the named cache without recreating it or removing cached responses.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100