Spring Cloud @RefreshScope和@EventListener实现Nacos配置更新监听

问题描述

使用@RefreshScope会刷新在Sprign IOC中所有Bean中使用@Value的值,但是在配置类中使用方法去配置的其他类参数并不会改变,例如

@Slf4j
@Configuration
@RefreshScope
public class SentinelConfig {
    @Bean
    public ZuulFilter sentinelZuulPreFilter() {
        return new SentinelZuulPreFilter();
    }

    @Bean
    public ZuulFilter sentinelZuulPostFilter() {
        return new SentinelZuulPostFilter();
    }

    @Bean
    public ZuulFilter sentinelZuulErrorFilter() {
        return new SentinelZuulErrorFilter();
    }

    @PostConstruct
    public void init() {
        ZuulBlockFallbackManager.registerProvider(new MyBlockFallbackProvider());
        Config config = ConfigService.getAppConfig();
        //Nacos后台配置更新,flowRules并不会改变,需要手动loadRules
        String flowRulesJson = config.getProperty("sentinel.flowRules",
                "[{\"burst\":0,\"controlBehavior\":0,\"count\":3.0,\"grade\":1,\"intervalSec\":1,\"maxQueueingTimeoutMs\":500,\"resource\":\"appblog-service\",\"resourceMode\":1}]");
        Set<GatewayFlowRule> flowRules = JSON.parseObject(flowRulesJson, new TypeReference<Set<GatewayFlowRule>>(){});
        GatewayRuleManager.loadRules(flowRules);
    }
}

解决方案

//使用此方法监听事件
@EventListener
public void envListener(EnvironmentChangeEvent event) {

}
@Slf4j
@Configuration
@RefreshScope
public class SentinelConfig {
    @Value("${sentinel.flowRules:[{\"burst\":0,\"controlBehavior\":0,\"count\":3.0,\"grade\":1,\"intervalSec\":1,\"maxQueueingTimeoutMs\":500,\"resource\":\"appblog-service\",\"resourceMode\":1}]}")
    private String flowRulesJson;

    @Bean
    public ZuulFilter sentinelZuulPreFilter() {
        return new SentinelZuulPreFilter();
    }

    @Bean
    public ZuulFilter sentinelZuulPostFilter() {
        return new SentinelZuulPostFilter();
    }

    @Bean
    public ZuulFilter sentinelZuulErrorFilter() {
        return new SentinelZuulErrorFilter();
    }

    @PostConstruct
    public void init() {
        ZuulBlockFallbackManager.registerProvider(new MyBlockFallbackProvider());
        Config config = ConfigService.getAppConfig();
        String flowRulesJson = config.getProperty("sentinel.flowRules",
                "[{\"burst\":0,\"controlBehavior\":0,\"count\":3.0,\"grade\":1,\"intervalSec\":1,\"maxQueueingTimeoutMs\":500,\"resource\":\"appblog-service\",\"resourceMode\":1}]");
        Set<GatewayFlowRule> flowRules = JSON.parseObject(flowRulesJson, new TypeReference<Set<GatewayFlowRule>>(){});
        GatewayRuleManager.loadRules(flowRules);
    }

    @EventListener
    public void envChangeListener(EnvironmentChangeEvent event) {
        log.info("Sentinel配置刷新");
        log.info(flowRulesJson);
        Set<GatewayFlowRule> flowRules = JSON.parseObject(flowRulesJson, new TypeReference<Set<GatewayFlowRule>>(){});
        GatewayRuleManager.loadRules(flowRules);
    }
}

原因分析

在调用刷新方法是会产生一个EnvironmentChangeEvent事件。进入ContextRefresher源码,看下refresh接口;

public synchronized Set<String> refresh() {
    Map<String, Object> before = extract(
            this.context.getEnvironment().getPropertySources());
    addConfigFilesToEnvironment();
    Set<String> keys = changes(before,
            extract(this.context.getEnvironment().getPropertySources())).keySet();
    // 注意这一行,抛出了一个变更事件
    this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
    this.scope.refreshAll();
    return keys;
}
上一篇 Spring Cloud 集成 Nacos 调试
下一篇 Spring Cloud生态的配置服务器对比
目录
文章列表
1 TestNG忽略测试
TestNG忽略测试
2
Docker容器可视化图形工具Portainer
Docker容器可视化图形工具Portainer
3
Java原生JSONObject实现JSON串与Java对象互转
Java原生JSONObject实现JSON串与Java对象互转
4
Swift - 类初始化和反初始化方法(init与deinit)
Swift - 类初始化和反初始化方法(init与deinit)
5
PHP file_get_contents获取表单POST请求内容为空问题
PHP file_get_contents获取表单POST请求内容为空问题
最新评论
一位WordPress评论者
一位WordPress评论者
2月12日
您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar。