采用 Nacos 和 Apollo 作为配置中心时@ConfigurationProperties、@RefreshScope的正确用法

2023-10-30

心中剑-手中剑

剑起

众所周知,当前各个互联网企业采用的配置中心中,无外乎 Nacos 和 Apollo 最为知名。今天不去比较优劣,因为适合自己的才是最好的,而是在两个框架出现过渡时,有些用法或者编码习惯需要调整,否则配置文件就自己单飞了。

最近因为公司技术栈过渡原因,我们从 Nacos 转为 Apollo 作为配置中心,这期间原来为了从编码规范的习惯不少类采用ConfigurationProperties注解修饰,而在接入 Apollo 配置中心后,猛然发现@RefreshScope无法自动热更新,这无疑是致命的。


剑来

下面演示Nacos 迁移到 Apollo不生效的场景

@Component
@RefreshScope
@ConfigurationProperties(prefix = "elasticsearch.check")
public class EsCheckConfig {
   // 迁移Apollo 后如果不做额外的配置 手动修改值是无法被感知的
   private Integer flag;
}

分析: 采用 SpringCloud 原生注解@RfreshScope,迁移到 Apollo 后对自定义配置的控制权都完全丢失,所以丢失相应的功能也能理解;既然不是一个体系,也不必考虑太多。

正确的打开方式

  1. 完全之策
直接依赖 SpringBoot 原生的@Value 注解,而这注定有几个问题
1. 虽然同样解决了问题,好像大家都知道的完全之策,更像是废话
2. 可偏执的我们总想知道@ConfigurationProperties 这家伙能不能热更新。
3. 如果像我们在已经搭建的体系下,去使用@Value方式,必然耗费一番功夫,而且几乎需要走一遍所有用例,确保迁移正确。
  1. 他山之石-稳定版
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.Set;

@Slf4j
@Component
public class ApolloConfig {


    private final RefreshScope refreshScope;
    
    private final EsCheckConfig esCheckConfig;


    public ApolloConfig(RefreshScope refreshScope, EsCheckConfig esCheckConfig) {
        this.refreshScope = refreshScope;
        this.esCheckConfig = esCheckConfig;
    }


    @ApolloConfigChangeListener
    private void someOnChange(ConfigChangeEvent changeEvent) {
        // 这部分是为了解决ConfigurationProperties 无法获取 apollo 变动的日志
        Set<String> changedKeys = changeEvent.changedKeys();
        changedKeys.forEach(k -> {
            ConfigChange change = changeEvent.getChange(k);
            log.info(change.toString());
        });
        // apollo 自带的热刷新
        refreshScope.refresh("esCheckConfig");
//        refreshScope.refreshAll();
    }
}

这下虽然满足了诉求,而这又带了几个问题【以下是戏精环节】

  1. 这 TMD 太离谱了,我那么多ConfigurationProperties 修饰的类,都要注入一遍?好,Apollo 还算良心,看到上面的注释了嘛,有了 refreshAll()
    好像再也不需要注入所有的类,于是长呼一口气,等等 我草这玩意儿是不是没更新都会刷新一遍,Yes!但凡大中型企业的配置,没有上万也有上千。
  2. 还有个问题,这只能解决你当下服务的配置,那么多微服务如果不依赖一个公共的底层服务去处理,那也是掩耳盗铃。

哦,对了上面还有简陋版

区别在于refreshScope.refresh("esCheckConfig")底层也是使用了this.applicationContext.publishEvent 不同的是在 spring 的发布事件基础上加锁了,Apollo 开发者也是细腻和全面,不过有谁一天无聊的操作同一个配置呢?如果只有几个人维护的话用下面倒也未尝不可

public class ApolloConfig implements ApplicationContextAware {


    private ApplicationContext applicationContext;

    @ApolloConfigChangeListener
    private void someOnChange(ConfigChangeEvent changeEvent) {
        Set<String> changedKeys = changeEvent.changedKeys();
        changedKeys.forEach(k -> {
            ConfigChange change = changeEvent.getChange(k);
            log.info(change.toString());
        });
        // 更新@ConfigurationProperties注解的bean
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changedKeys));
    }
}

所以,实际开发中该怎么做?笔者探寻一圈,难以两全,所以有了下文


剑魂

使用@Value一定没毛病的老铁哈哈哈,所以在你编码习惯上就应该有这样的意识,如果还在使用@ConfigurationProperties的老铁还是尽早悬崖勒马,否则早晚要陷入我等这样的困境,实在是想用,就要实时记得用apollo 自带的热更新去检查

当然了,如果像Redis、MySQL 的这样固定的配置,@ConfigurationProperties也是没毛病,当你要修改这些基础配置时,重启在所难免,
遗憾的是 SpringBoot 都集成了

还有,细心的童鞋应该还发现上面一段记录ConfigChangeEvent打印变更key 的先后信息,这个在使用@ConfigurationProperties避免带来的隐患,该注解修饰下的对象被 spring代理。

因此当你发生值变更的时候,what 你啥也感知不到,好像啥也没发生,这样的事情你允许在生产环境吗?所以使用@value吧,直到 SpringBoot 也能自带支持@ConfigurationProperties热更新那一天!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

采用 Nacos 和 Apollo 作为配置中心时@ConfigurationProperties、@RefreshScope的正确用法 的相关文章

  • 如何将 Java 赋值表达式转换为 Kotlin

    java中的一些东西就像 int a 1 b 2 c 1 if a b c System out print true 现在它应该转换为 kotlin 就像 var a Int 1 var b Int 2 var c Int 1 if a
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • manifest.mf 文件的附加内容的约定?

    Java JAR 中的 MANIFEST MF 文件是否有任何超出 MANIFEST MF 约定的约定 JAR规范 http download oracle com javase 1 4 2 docs guide jar jar html
  • java.io.IOException: %1 不是有效的 Win32 应用程序

    我正在尝试对 XML 文档进行数字签名 为此我有两个选择 有一个由爱沙尼亚认证中心为程序员创建的库 还有一个由银行制作的运行 Java 代码的脚本 如果使用官方 认证中心 库 那么一切都会像魅力一样进行一些调整 但是当涉及到银行脚本时 它会
  • 一种使用 Java Robot API 和 Selenium WebDriver by Java 进行文件上传的解决方案

    我看到很多人在使用 Selenium WebDriver 的测试环境中上传文件时遇到问题 我使用 selenium WebDriver 和 java 也遇到了同样的问题 我终于找到了解决方案 所以我将其发布在这里希望对其他人有所帮助 当我需
  • Microsoft Graph 身份验证 - 委派权限

    我可以使用 Microsoft Graph 访问资源无需用户即可访问 https developer microsoft com en us graph docs concepts auth v2 service 但是 此方法不允许我访问需
  • Spring引导@Transactional

    spring boot会自动在controller层添加 Transactional注解吗 我尝试将 Transactional 放在服务层 但似乎控制器层覆盖了注释 我有这个配置
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • 使用 AWS Java SDK 为现有 S3 对象设置 Expires 标头

    我正在更新 Amazon S3 存储桶中的现有对象以设置一些元数据 我想设置 HTTPExpires每个对象的标头以更好地处理 HTTP 1 0 客户端 我们正在使用AWS Java SDK http aws amazon com sdkf
  • org.jdesktop.application 包不存在

    几天以来我一直在构建一个 Java 桌面应用程序 一切都很顺利 但是今天 当我打开Netbeans并编译文件时 出现以下编译错误 Compiling 9 source files to C Documents and Settings Ad
  • 应用程序关闭时的倒计时问题

    我制作了一个 CountDownTimer 代码 我希望 CountDownTimer 在完成时重新启动 即使应用程序已关闭 但它仅在应用程序正在运行或重新启动应用程序时重新启动 因此 如果我在倒计时为 00 10 分钟 秒 时关闭应用程序
  • 当单元格内的 JComboBox 中有 ItemEvent 时,如何获取 CellRow

    我有一个 JTable 其中有一列包含 JComboBox 我有一个附加到 JComboBox 的 ItemListener 它会根据任何更改进行操作 但是 ItemListener 没有获取更改的 ComboBox 所在行的方法 当组合框
  • Windows 上的 Nifi 命令

    在我当前的项目中 我一直在Windows操作系统上使用apache nifi 我已经提取了nifi 0 7 0 bin zip文件输入C 现在 当我跑步时 bin run nifi bat as 管理员我在命令行上看到以下消息 但无法运行
  • 如何配置eclipse以保持这种代码格式?

    以下代码来自 playframework 2 0 的示例 Display the dashboard public static Result index return ok dashboard render Project findInv
  • 将2-3-4树转换为红黑树

    我正在尝试将 2 3 4 树转换为 java 中的红黑树 但我无法弄清楚它 我将这两个基本类编写如下 以使问题简单明了 但不知道从这里到哪里去 public class TwoThreeFour
  • JAVA - 如何从扫描仪读取文件中检测到“\n”字符

    第一次海报 我在读取文本文件的扫描仪中读取返回字符时遇到问题 正在读取的文本文件如下所示 test txt start 2 0 30 30 1 1 90 30 0 test txt end 第一行 2 表示两个点 第二行 位置索引 0 xp
  • java8 Collectors.toMap() 限制?

    我正在尝试使用java8Collectors toMap on a Stream of ZipEntry 这可能不是最好的想法 因为在处理过程中可能会发生异常 但我想这应该是可能的 我现在收到一个我不明白的编译错误 我猜是类型推理引擎 这是
  • javax.persistence.Table.indexes()[Ljavax/persistence/Index 中的 NoSuchMethodError

    我有一个 Play Framework 应用程序 并且我was使用 Hibernate 4 2 5 Final 通过 Maven 依赖项管理器检索 我决定升级到 Hibernate 4 3 0 Final 成功重新编译我的应用程序并运行它
  • Jackson 将单个项目反序列化到列表中

    我正在尝试使用一项服务 该服务为我提供了一个带有数组字段的实体 id 23233 items name item 1 name item 2 但是 当数组包含单个项目时 将返回该项目本身 而不是包含一个元素的数组 id 43567 item
  • Swagger/Openapi-Annotations:如何使用 $ref 生成 allOf?

    我正在生成 Rest 端点 包括添加OpenAPI Swagger对生成的代码进行注释 虽然它对于基本类型运行得很好 但我在自定义类方面遇到了一些问题 现在我有很多自定义类的重复架构条目 使用 Schema 实现 MyClass class

随机推荐

  • C语言基本知识

    基础 第一个函数 argc代表参数个数argument count argv代表参数value 第一个为放的是文件名 后面是传入的参数 编译过程 预处 gcc E hello c o hello i 编译 gcc S hello c i o
  • (Termux)安装Nginx(其他的也适用)

    这里没有直接的nginx包了 需要下载进行编辑安装了 一 下载 创建文件夹 mkdir usr local nginx cd usr local nginx 下载 wget https nginx org download nginx 1
  • socket短连接,数据交互报文采用XML形式

    socket 服务端一直等待客户端 public void threadServer TODO Auto generated method stub class ServerThread extends Thread Socket sock
  • 中国区块链网络调研分析

    2016年 国务院发布 十三五 国家信息规划 第一次将区块链纳入新技术范畴并作前沿布局 这标志着我国开始推动区块链技术和应用发展 此后 中央和地方纷纷出台了相关监管或扶持政策 为区块链技术和产业发展提供政策红利 鼓励和监管新技术的创新发展
  • ConcurrentHashMap 详解(超详细 看不懂你锤我)

    ConcurrentHashMap介绍 ConcurrentHashMap是一个 在juc包下的 map 线程安全 在jdk 1 7 之前采用数组 链表的结构 并且采用分段锁机制 来保证线程安全 而jdk1 8之后 他改成了 数组 链表 红
  • Linux和android的不同

    一 主体不同 1 linux系统 是一套免费使用和自由传播的类UNIX操作系统 2 安卓 是一种基于Linux的自由及开放源代码的操作系统 二 架构不同 1 linux系统 主要受到Minix和Unix思想的启发 是一个基于POSIX和Un
  • Extjs floating Panel 挡住 提示框或确认框的解决方法

    在弹窗代码的后面紧跟一句 Ext MessageBox getDialog getEl setStyle z index 80000 即可 如 Ext Msg alert 提示 根节点不能删除 Ext MessageBox getDialo
  • 二进制十进制小数转换

    方法 十进制的小数转为二进制 主要是小数部分乘以2 取整数部分一次从左往右放在小数点后 直至小数点后为0 就是为整数时 eg 0 125 二进制的小数转换为十进制主要是乘以2的负次方 从小数点后开始 依次乘以2的负一次方 2的负二次方 2的
  • 第10讲:Redis幂等性

    问 什么是幂等性 幂等性 就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的 不会因为多次点击而产生了了副作用 举个最简单的例子 那就是支付 用户购买商品后支付 支付扣款成功 但是返回结果的时候网络异常 此时钱已经扣了 用户再次点
  • 搭建myexam考试系统服务器,myExam

    myExam classpath myExam cvsignore myExam project myExam tomcatplugin myExam build xml myExam jsp exam jsp myExam jsp exa
  • JAVA-输出一个三角形(详解)

    public class Demo 注意 编程时不可以使用汉语和拼音 要用英文单词或者英文单词缩写 如图 想要输出一个四行的三角形 第1行 第2行 第3行 第4行 思路 1 将这个图形看成四个直角三角形 2 需要两层for循环 第一层的作用
  • Unity编辑器扩展——通用树形结构绘制工具

    我们在使用Unity进行工具开发时 有时需要绘制一些树形的目录结构 例如这样的 提供一个通用的树形目录绘制的通用类 效果如下 设计图为 TreeNodeGUIBase为树的叶子结点结构 所以必须包含它的子节点的列表 TreeGUIBase为
  • (实用)Python模块打包

    目录 前言 一 什么是setuptools 二 编写setup py文件 1 创建一个setup py文件 2 调用setuptools的setup 方法 参数如下 3 代码示例 三 执行打包 3 1 执行打包语句 3 1 1 打包成 wh
  • moment中时间为12小时制,dayjs中时间为12小时制

    前言 在使用dayjs moment 他两用法一致 时 出现 后端数据给我们的是下午 4点 但是我们转换以后是4点 不是16点的情况 问题解析 yyyy MM dd HH mm ss 后面的时分秒是24小时制 yyyy MM dd hh m
  • 13天带你了解C++ ---DAY7 c++的 模板

    目录 1 泛型 2 函数模板 3 函数模板和重载的区别 4 函数模板实例化 5 类模板 6 模板特化 1 泛型 泛型是编写与类型无关的类型代码 是代码复用的一种手段 泛型是对面向对象的一种补充 极大的提高了代码复用率 在c 中 泛型的实现方
  • 【数据分析入门】第二周 EXCEL数据透视表笔记

    第二周 Excel数据透视表笔记 一 数据透视表 数据透视表的主要功能是将数据聚合 按照各子段进行sum count 的运算 操作 选择想要的数据区域 选择插入 创建透视表 此时会新建一个Sheet 将原始数据和汇总计算数据分离 数据透视表
  • 【c语言】利用指针求三个数的最大数和最小数

    比较费空间的笨方法 include
  • xtu 1397 Patchouli的金字塔

    题目描述 Patchouli想要绘制一个金字塔 金字塔的图案由n个正三角形和倒三角形堆叠而成 具体的绘制方法如下 每个三角形由 和 组成 分别代表三角形的顶点和三条边 第一行只包含一个正三角形 其余各行的三角形按照 正三角形 倒三角形 正三
  • STM32----ADC模数转换与DAC数模转换

    目录 ADC模数转换 DAC数模转换 ADC模数转换 指模 数转换器或者模拟 数字转换器 将连续变量的模拟信号转换为离散的数字信号的器件 典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号 特点 STM32通道组 1 规则通道
  • 采用 Nacos 和 Apollo 作为配置中心时@ConfigurationProperties、@RefreshScope的正确用法

    心中剑 手中剑 剑起 剑来 剑魂 剑起 众所周知 当前各个互联网企业采用的配置中心中 无外乎 Nacos 和 Apollo 最为知名 今天不去比较优劣 因为适合自己的才是最好的 而是在两个框架出现过渡时 有些用法或者编码习惯需要调整 否则配