You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:27:55