SpringBoot 2.6.6中@Cacheable指标在Prometheus刷新后停止更新问题
问题原因
调用/actuator/refresh后缓存指标停滞,核心原因是配置刷新过程中缓存实例与Prometheus指标注册器的绑定关系断裂:
- 若你的缓存相关Bean(如
CacheManager)被@RefreshScope标记,刷新时Spring会销毁旧Bean并创建新实例,但默认的CacheMetricsRegistrar只会在应用启动时注册一次缓存指标,不会自动关联新生成的缓存实例,导致后续缓存操作的命中/未命中数据无法被采集。 - 即使未标记
@RefreshScope,如果刷新操作触发了缓存配置的变更(比如缓存过期时间、名称),新的缓存实例创建后,指标采集器也不会主动监听这些新实例,造成指标停更。
解决方案
1. 避免不必要的@RefreshScope标记
检查你的缓存配置类,确保CacheManager或Cache相关Bean没有被@RefreshScope注解标记——除非你确实需要动态刷新缓存配置,否则没必要让这些Bean进入刷新作用域,从根源避免实例重建导致的指标绑定断裂。
2. 监听刷新事件,重新注册缓存指标
如果必须动态刷新缓存配置,通过监听Spring的RefreshScopeRefreshedEvent事件,在配置刷新后手动重新注册缓存指标:
@Component public class CacheMetricsRefreshListener implements ApplicationListener<RefreshScopeRefreshedEvent> { private final CacheMetricsRegistrar cacheMetricsRegistrar; private final CacheManager cacheManager; public CacheMetricsRefreshListener(CacheMetricsRegistrar cacheMetricsRegistrar, CacheManager cacheManager) { this.cacheMetricsRegistrar = cacheMetricsRegistrar; this.cacheManager = cacheManager; } @Override public void onApplicationEvent(RefreshScopeRefreshedEvent event) { // 先注销旧缓存的指标,避免重复采集 cacheManager.getCacheNames().forEach(cacheName -> { Cache cache = cacheManager.getCache(cacheName); if (cache != null) { cacheMetricsRegistrar.unregisterCacheMetrics(cache); } }); // 为新的缓存实例注册指标 cacheManager.getCacheNames().forEach(cacheName -> { Cache cache = cacheManager.getCache(cacheName); if (cache != null) { cacheMetricsRegistrar.registerCacheMetrics(cache); } }); } }
注意:需要确保项目引入了spring-boot-starter-actuator和micrometer-registry-prometheus依赖,CacheMetricsRegistrar会自动被Spring容器管理。
3. 自定义CacheManager的刷新逻辑
如果是通过配置文件动态调整缓存参数(如spring.cache.redis.time-to-live),可以自定义CacheManager的创建逻辑,在配置刷新时主动更新缓存实例,并同步更新指标绑定:
@Configuration public class CustomCacheConfig { @Value("${spring.cache.redis.time-to-live:3600000}") private Duration ttl; @Bean @RefreshScope public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(ttl); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(config) .build(); } }
搭配上面的CacheMetricsRefreshListener,就能在CacheManager刷新后自动重新绑定指标。
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

