使用Caffeine Cache时manage/metrics端点cache.puts计数始终为0的问题
使用Spring Boot 2.7.2和Caffeine 2.8.5,缓存功能正常,但/actuator/metrics/cache.puts计数始终为0,其他缓存指标(cache.eviction.weight、cache.evictions、cache.gets、cache.size)均显示正常。
配置代码如下:
@Configuration @ConfigurationProperties(prefix = "importantcache") public class CaffeineCacheConfig { private Long maxSize; private Duration expire; public Long getMaxSize() { return maxSize; } public void setMaxSize(Long maxSize) { this.maxSize = maxSize; } public Duration getExpire() { return expire; } public void setExpire(Duration expire) { this.expire = expire; } }
@Component @EnableCaching public class CaffeineCache { private final CaffeineCacheConfig caffeineCacheConfig; @Autowired public CaffeineCache(CaffeineCacheConfig caffeineCacheConfig) { this.caffeineCacheConfig = caffeineCacheConfig; } @Bean public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager( "cache1", "cache2", "cache3" ); cacheManager.setCaffeine(caffeineCacheBuilder()); return cacheManager; } Caffeine<Object, Object> caffeineCacheBuilder() { Long size = 1000L; Duration expire = Duration.parse("PT1H"); if (caffeineCacheConfig.getMaxSize() != null) { size = caffeineCacheConfig.getMaxSize(); } if (caffeineCacheConfig.getExpire() != null) { expire = caffeineCacheConfig.getExpire(); } return Caffeine.newBuilder() .maximumSize(size) .expireAfterWrite(expire) .recordStats(); } }
尝试过的另一种cacheManager()实现:
@Bean public CacheManager cacheManager(MeterRegistry meterRegistry) { CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager() { protected com.github.benmanes.caffeine.cache.Cache<Object, Object> createNativeCaffeineCache(String name) { return CaffeineCacheMetrics.monitor(meterRegistry, super.createNativeCaffeineCache(name), name); } }; caffeineCacheManager.setCaffeine(caffeineCacheBuilder()); return caffeineCacheManager; }
1. 确认缓存写入的触发逻辑
Spring Cache的@Cacheable仅在缓存未命中且执行方法逻辑后才会触发put操作,对应cache.puts指标。如果你的场景大部分是缓存命中,或未通过Spring Cache注解/API主动写入,cache.puts自然不会增长。
- 验证方法:调用一个必然缓存未命中的方法,或直接使用
Cache.put(key, value)API写入数据,再检查指标是否更新。
2. 修复缓存指标的绑定逻辑
Spring Boot 2.7.x默认的Caffeine指标采集可能遗漏puts统计,需要确保CaffeineCacheMetrics正确绑定缓存实例:
@Bean public CacheManager cacheManager(MeterRegistry meterRegistry) { CaffeineCacheManager cacheManager = new CaffeineCacheManager("cache1", "cache2", "cache3"); cacheManager.setCaffeine(caffeineCacheBuilder()); // 为每个缓存实例手动注册Metrics cacheManager.getCacheNames().forEach(cacheName -> { Cache cache = cacheManager.getCache(cacheName); if (cache instanceof CaffeineCache) { com.github.benmanes.caffeine.cache.Cache<Object, Object> nativeCache = ((CaffeineCache) cache).getNativeCache(); CaffeineCacheMetrics.monitor(meterRegistry, nativeCache, cacheName); } }); return cacheManager; }
3. 升级Caffeine版本适配Spring Boot
Caffeine 2.8.5与Spring Boot 2.7.2存在轻微适配问题,建议升级到Spring Boot 2.7.x推荐的稳定版本2.9.3:
<!-- pom.xml --> <dependency> <groupId>com.github.benmanes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.9.3</version> </dependency>
4. 启用Caffeine原生日志验证统计
在application.properties中添加日志配置,直接查看Caffeine原始统计数据:
logging.level.com.github.benmanes.caffeine.cache=DEBUG
执行缓存写入操作后,查看日志中的CacheStats输出,检查totalPuts()是否大于0。如果原生统计有值但Spring Metrics未体现,说明指标绑定环节存在问题。
5. 用原生API验证统计逻辑
绕过Spring Cache,直接使用Caffeine原生API写入,验证统计是否正常:
@Autowired private CacheManager cacheManager; public void testCachePuts() { Cache cache = cacheManager.getCache("cache1"); if (cache instanceof CaffeineCache) { com.github.benmanes.caffeine.cache.Cache<Object, Object> nativeCache = ((CaffeineCache) cache).getNativeCache(); // 写入测试数据 for (int i = 0; i < 10; i++) { nativeCache.put("test-key-" + i, "test-value-" + i); } // 打印原生统计 CacheStats stats = nativeCache.stats(); System.out.println("原生统计totalPuts: " + stats.totalPuts()); } }
如果原生统计的totalPuts()正确,但Spring Metrics的cache.puts仍为0,需重点排查指标注册逻辑。
内容的提问来源于stack exchange,提问作者pesto

