最近在使用 Nacos 过程中遇到一个场景,配置的字符串可以解析成 Map 类型使用,有一个配置如下:

map:test: key1:value1,key2:value2,key3:value3

后来有同事建议 Nacos 可以直接配置成 Map 类型,后台使用 Java Map 类型获取就可以。配置如下:

map:test:key1: value1key2: value2key3: value3

下面就来分享一下配置 Map 类型的过程中遇到的问题。

1 使用 Bean 方式获取配置

1.1 使用方式

参考网上的一些案例,第一个方式是把读取到的 Map 作为一个 Spring 的 Bean,一看代码就明白了。

@Bean
@ConfigurationProperties(prefix = "map.test")
public Map<String, String> mapping() {return new HashMap<>();
}

1.2 槽点

这样确实可以把 Nacos 中读取到的配置转换成 Map 类型,但一个致命的槽点就是 mapping 这个 bean 不能自动刷新。这样如果修改了 Nacos 中配置,要想让配置生效,就必须重启应用服务,这怎么能接受呢?

2 ConfigurationProperties2.1 使用方式

直接使用 @Value 和 @NacosValue 是获取不到值的。下面的这种方式,类的定义上加注解 @ConfigurationProperties,再定义一个变量,名称跟 Nacos 中配置的后缀一样,这样是可以获取到 Map 类型的配置的。

@Component
@RefreshScope
@ConfigurationProperties(prefix = "map")
public class NacosRefresh {private Logger logger = LoggerFactory.getLogger(getClass());public void setTest(Map<String, String> test) {this.test = test;}private Map<String, String> test;
}

注意:上面的 setTest 方法是必须要的,不然 test 变量取不到值。

2.2 槽点

这样确实可以把 Nacos 中读取到的配置转换成 Map 类型,但是跟第一种方式一样,定义的 Map 类型变量不能自动刷新。

3.使用监听

Nacos API 提供了监听功能,可以监听配置的变化,对变化进行处理,只要在监听方法上增加 @NacosConfigListener 这个注解就可以生效。见下面代码:

@Service
public class NacosListener {private Logger logger = LoggerFactory.getLogger(getClass());private Map<String, String> map = new HashMap<>();@NacosConfigListener(dataId = "maptest.yaml",groupId = "DEFAULT_GROUP")public void listener(String context){logger.info("================listener context:{}", context);if (StringUtils.isBlank(context)){return;}Yaml yaml = new Yaml();Map<String, Object> contextMap = yaml.load(context);Map<String, Object> map = (Map<String, Object>)contextMap.get("map");if (CollectionUtils.isEmpty(map)){return;}Map<String, String> test = (Map<String, String>) map.get("test");if (CollectionUtils.isEmpty(test)){return;}map.clear();map.putAll(test);map.forEach((k,v) -> logger.info("Entry in map, key:{},value:{}", k, v));}
}

这段代码是从 Nacos 配置中解析出 Map 类型的配置,然后把配置 put 到本地变量 map。这个也可以完成我们的需求,但是有几点需要注意。

3.1 服务重启

如果服务重启了,本地变量 map 拉不到值。因为上面监听的逻辑并没有走,即使在 Nacos 上重新发布一下,也不行。

上面的监听方法,只有在 Nacos 配置发生变化并且发布后才会触发,比如 map.test 配置改变如下:

map:test:key1: value1key2: value2key3: value3key4: value4

3.2 并发问题

上面监听的代码里面,需要把本地变量 map 先 clear 然后再 putAll,如果这两个方法调用中间发生了线程上下文切换,读取线程可能会因为从 map 中取不到值而发生异常。

4.改进

上面讲解了使用 Nacos 配置 Map 类型的坑,不过使用 Nacos 配置 Map 类型也有个好处,不用解析字符串,直接可以转成 Map 类型。

4.1 使用字符串

完全不使用 Map 类型了,改成配置字符串,配置如下:

map:test: key1:value1,key2:value2,key3:value3

解析代码如下:

@NacosValue(value = "${map.test}", autoRefreshed = true)
private String mapTest;public String get(String key){String[] keys = mapTest.split(",");for (String item : keys){if (!item.contains(key)){continue;}return item.split(":")[1];}return null;
}

这种写法的好处是不用监听 Nacos,配置改变后 mapTest 变量自动刷新,缺点是每次调用 get 方法都需要解析 mapTest 这个字符串。

4.2 刷新本地 Map

把解析字符串的结果放到本地变量 map 上,考虑到 Nacos 中配置可能会发生变化,用定时线程池每 1 秒刷新一次,代码如下:

private Map<String, String> map = new HashMap<>();@NacosValue(value = "${map.test}", autoRefreshed = true)
private String mapTest;@PostConstruct
public void refreshLocalMap(){ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(1);scheduled.scheduleAtFixedRate(() -> refresh(), 0, 1000, TimeUnit.MILLISECONDS);
}public void refresh(){String[] keys = mapTest.split(",");for (String item : keys){String[] kv = item.split(":");map.put(kv[0], kv[1]);}
}

这个写法的好处是不用每次调用都解析字符串,而是由异步线程每秒钟刷新。但是也有两个问题:

  • 需要一个定时线程池,会消耗 CPU 资源。
  • refresh 方法是每秒执行一次,会有短暂的本地变量和 Nacos 配置不一致的问题。

5.总结

Nacos 中配置 Map 类型确实不香,主要原因是刷新不方便。但是对于配置不需要刷新的场景,还是很有好处的,尤其是 key 比较多的时候,比解析字符串方便很多,而且 Hash 的时间复杂度是 o(1) ,在数据结构中是最优秀的。

对于需要刷新的场景,无论使用哪种方案,都有优缺点,没有最好的,只有最适合的,要根据系统的业务场景来做选择。

Nacos 中配置 Map 类型,不香相关推荐

  1. 在IIS中配置MIME类型组建Wap网站

    1.创建站点文件夹 首先你要在IIS上创建一个新的站点. 2.创建新的MIME类型 首先选择"WAP"站点的"属性",然后选择"HTTP 头" ...

  2. Spring Cloud Alibba教程:如何使用Nacos作为配置中心

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 在上一篇文章中讲解了如何使用Nacos作为服务注册中心注册.Nacos除了可以作为服务注册中心, ...

  3. Linux启动nacos成功日志_Spring Cloud Alibaba基础教程:使用Nacos作为配置中心

    通过本教程的前两篇: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方 ...

  4. Spring Cloud Alibaba基础教程:使用Nacos作为配置中心

    通过本教程的前两篇: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方 ...

  5. Nacos分布式配置实践

    本文来说下Nacos分布式配置如何来实践 文章目录 概述 创建服务 Nacos中新建配置 服务整合Nacos配置 动态刷新 本文小结 概述 本文目的是使用 Nacos 管理服务的配置. 步骤: (1) ...

  6. eBPF: 深入探究 Map 类型

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权. 内核版本为5.4.119 文章目录 ...

  7. SpringCloud读取Nacos中的配置文件

    目录 一.配置nacos命名空间 1.通过安装路径启动nocas 2.通过localhost:8848进入nacos的页面,账号密码都为nacos 3.添加命名空间 ?3.1添加三个命名空间分别为:d ...

  8. java怎么设置不同事件_activiti 全局流程监听ActivitiEventListener,实现监听不同类型事件,不需要在acitivit中配置任务监听,非常方便...

    如果我们像给任务配置监听,按照常规的做法是这样的 一个个配置,比较麻烦. 现在利用ActivitiEventListener,监听全局事件,并且可以判断不同的事件类型,进而执行不同的业务逻辑. 1.定 ...

  9. SpringCloud(若依微服务版)读取Nacos中的配置以及多个服务共享Nacos配置的使用

    场景 若依微服务版手把手教你本地搭建环境并运行前后端项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/109363303 在上 ...

  10. java中map转为json数据_Java技术-将java中Map类型数据转化为json数据并以Ajax形式返回...

    Java技术-将java中Map类型数据转化为json数据并以Ajax形式返回html 1.自定义工具类(简单易用)-下面是我写的一个简单的工具类前端 package com.test.util; i ...

最新文章

  1. Spring Boot + Vue + Shiro 实现前后端分离、权限控制
  2. 2017年第十一届中国电子产业品牌盛会盛大开启
  3. Gradient Boost 算法流程分析
  4. 中 找多个平面_数学一轮复习30,平面向量的概念及线性运算,三个常用结论
  5. WebRTC 系列之音频会话管理
  6. VirtualBox安装linux mint教程
  7. 第三次学JAVA再学不好就吃翔(part36)--抽象类
  8. 一号团队-团队任务3:每日立会(2018-12-01)
  9. 【Spring AOP】AOP 底层实现原理 —— 动态代理类的创建(JDK、CGlib)、工厂如何加工原始对象
  10. java 链表算法_数据结构算法Java版(一) 链表
  11. 微机接口技术实用教程(第2版)-任向民,王克朝,宗明魁-课后答案
  12. day7--pandas
  13. 如何在PHP中获得有用的错误消息?
  14. 小米9008授权账号_小米AI音箱APP的秘密
  15. word如何批量免费转PDF
  16. 使用 Tampermonkey 编写高级跨网站自动化任务脚本
  17. 示例填充图片_用示例解释洪水填充算法
  18. 安卓视频播放器(TV)
  19. 【C++探索之旅】第一部分第八课:传值引用,文件源头
  20. 做Android开发 需要掌握哪些知识

热门文章

  1. 以太网卡支持的工作模式
  2. SSM | Spring
  3. 深度:融360还是一家有价值的公司吗?
  4. linux和windows文件加密,在Linux和 Windows 上使用 EncFS,如何加密雲存儲
  5. 自定义UISearchBar 适配IOS6和IOS7 修改放大镜图标 修改光标颜色 修改边框颜色 placeholder颜色 设置文本框背景
  6. K-periodic Garland
  7. Java使用微软Exchange邮箱发送与接收邮件
  8. 充分利用微博加快社区发展
  9. 卸载360企业版密码
  10. From Intrusion Detection to Attacker Attribution: A Comprehensive Survey of Unsupervised Methods翻译