我的编程空间,编程开发者的网络收藏夹
学习永远不晚

nacos配置动态刷新及监听到变化触发一些方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

nacos配置动态刷新及监听到变化触发一些方法

介绍

在使用spring 时,动态更新配置是常见的,属性值更新,但是需要开启支持刷新功能,一个是spring.cloud.nacos.config.isRefreshEnabled=true; 这个值一般是默认的,可以在nacosConfigProperties这个类中看到。还要在扩展配置中开启refresh = true

spring    cloud:      nacos:        config:          server-addr: ${nacos-ip}          extension-configs[0]:            data-id: ${spring.application.name}.yml            group: base        # 这个地方必须开启,否则不会自动刷新            refresh: true

2 使用

2.1 新建配置类

import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;@Data@Configuration@ConfigurationProperties(prefix = "apply.demo")public class DemoConfig {        private String config;}

2.2 新建测试访问类

import com.purgeteam.dynamic.config.starter.event.ActionConfigEvent;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;import java.util.Map;@RestController@Slf4j@RequestMapping("/api/test2")public class Test2Controller {//    @Autowired    private DemoConfig demoConfig;    @GetMapping(value = "dd")    public String test4(String params){        log.info("dsds" + params);        System.out.println(demoConfig.getConfig());        System.out.println(SpringUtil.getApplicationContext().getBean("testController"));        // 保存数据        return demoConfig.getConfig();    }}

2.3 yml配置

apply:  demo:    config: 2225dssww

测试结果: 配置中心值改变,对应的属性值也改变

------这里好像没用加@RefreshScope注解

3. 监听到变化触发方法

在监听到配置值变化后,需要触发一些方法,需要实现ApplicationListener 接口,重写onApplicationEvent方法

3.1 触发代码

import com.purgeteam.dynamic.config.starter.event.ActionConfigEvent;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;import java.util.Map;@RestController@Slf4j@RequestMapping("/api/test2")public class Test2Controller implements ApplicationListener {//    @Autowired    private DemoConfig demoConfig;    @GetMapping(value = "dd")    public String test4(String params){        log.info("dsds" + params);        System.out.println(demoConfig.getConfig());        System.out.println(SpringUtil.getApplicationContext().getBean("testController"));        // 保存数据        return demoConfig.getConfig();    }// 这个方法会在属性变化后调用,这里可以根据某个值变化去处理其他逻辑    @Override    public void onApplicationEvent(ActionConfigEvent actionConfigEvent) {// 获取变化的key        Map propertyMap = actionConfigEvent.getPropertyMap();// 取出变化的key的map        HashMap hashMap = propertyMap.get("spring.profiles1.active1");// 变化后的值        Object after = hashMap.get("after");// 变化前的值        Object after = hashMap.get("before");// 打印属性值        log.info("====env========={}",this.demoConfig.getConfig());    }}

4. 执行流程分析

处理属性变化绑定值类org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder#onApplicationEvent

自己可以打断点,看方法走向。

获取服务端配置最后是一个string,在com.alibaba.nacos.client.config.impl.ClientWorker.LongPollingRunnable#run这个方法中

String[] ct = ClientWorker.this.getServerConfig(dataId, group, tenant, 3000L);

4.1 服务启动注册配置监听

com.alibaba.cloud.nacos.refresh.NacosContextRefresher#onApplicationEvent这里会调用注册方法com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListenersForApplications

// 注册监听方法private void registerNacosListenersForApplications() {// 全局开启刷新,默认是true        if (isRefreshEnabled()) {            for (NacosPropertySource propertySource : NacosPropertySourceRepository                    .getAll()) {            // 判断单个配置文件是否支持刷新,就是refresh = true,开启了就会注册监听,有变化就会及时通知                if (!propertySource.isRefreshable()) {                    continue;                }                String dataId = propertySource.getDataId();                // 调用注册方法                registerNacosListener(propertySource.getGroup(), dataId);            }        }    }
private void registerNacosListener(final String groupKey, final String dataKey) {        String key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);        // 创建监听        Listener listener = listenerMap.computeIfAbsent(key,                lst -> new AbstractSharedListener() {                    @Override                    public void innerReceive(String dataId, String group,String configInfo) {                        refreshCountIncrement();                        nacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);                        // todo feature: support single refresh for listening                        applicationContext.publishEvent(    new RefreshEvent(this, null, "Refresh Nacos config"));                        if (log.isDebugEnabled()) {log.debug(String.format(        "Refresh Nacos config group=%s,dataId=%s,configInfo=%s",        group, dataId, configInfo));                        }                    }                });        try {        // 这里是最重要的,将监听添加到,config里,注册上            configService.addListener(dataKey, groupKey, listener);        }        catch (NacosException e) {            log.warn(String.format(                    "register fail for nacos listener ,dataId=[%s],group=[%s]", dataKey,                    groupKey), e);        }    }

4.2 配置改变刷新配置属性

调用到org.springframework.cloud.context.refresh.ContextRefresher#refreshEnvironment

// 返回变化的keypublic synchronized Set refreshEnvironment() {// 以前的配置的值        Map before = this.extract(this.context.getEnvironment().getPropertySources());        this.addConfigFilesToEnvironment();// 改变后的key        Set keys = this.changes(before, this.extract(this.context.getEnvironment().getPropertySources())).keySet();// 发布环境变化时间,spring内部事件        this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));// 返回变化的key        return keys;    }

求出以前和现在变化的key

private Map changes(Map before, Map after) {        Map result = new HashMap();        Iterator var4 = before.keySet().iterator();        String key;        while(var4.hasNext()) {            key = (String)var4.next();            if (!after.containsKey(key)) {                result.put(key, (Object)null);            } else if (!this.equal(before.get(key), after.get(key))) {                result.put(key, after.get(key));            }        }        var4 = after.keySet().iterator();        while(var4.hasNext()) {            key = (String)var4.next();            if (!before.containsKey(key)) {                result.put(key, after.get(key));            }        }        return result;    }

环境变化事件处理

org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder#onApplicationEvent

public void onApplicationEvent(EnvironmentChangeEvent event) {        if (this.applicationContext.equals(event.getSource()) || event.getKeys().equals(event.getSource())) {// 重新绑定值            this.rebind();        }    }

这里会看到需要绑定的配置类


开始绑定

这里绑定值后,虽然经过了销毁和初始化,发现,地址没有变,里面的值变了

刷新后还会调用这个方法org.springframework.cloud.context.refresh.ContextRefresher#refresh

发布一个RefreshScopeRefreshedEvent事件

com.purgeteam.dynamic.config.starter.event.DynamicConfigApplicationListener#onApplicationEvent

public void onApplicationEvent(RefreshEvent event) {        ConfigurableEnvironment beforeEnv = (ConfigurableEnvironment)this.context.getEnvironment();        MutablePropertySources propertySources = beforeEnv.getPropertySources();        MutablePropertySources beforeSources = new MutablePropertySources(propertySources);        Set refresh = this.refresh.refresh();        Map contrast = this.propertyUtil.contrast(beforeSources, propertySources);// 发布一个配置变化事件        this.context.publishEvent(new ActionConfigEvent(this, "Refresh config", contrast));        log.info("[ActionApplicationListener] The update is successful {}", refresh);    }

调用到自己的方法

public void onApplicationEvent(ActionConfigEvent actionConfigEvent) {        Map propertyMap = actionConfigEvent.getPropertyMap();        HashMap hashMap = propertyMap.get("spring.profiles1.active1");        Object after = hashMap.get("after");// 触发其他逻辑        log.info("====env========={}",this.demoConfig.getConfig());    }

5. 总结

这里主要介绍了使用。

如果属性刷新需要处理逻辑,就需要实现ApplicationListener接口

需要注意配置是怎么注册监听的。

来源地址:https://blog.csdn.net/wangfenglei123456/article/details/128634050

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

nacos配置动态刷新及监听到变化触发一些方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录