目录
一、适应场景
二、制作依赖
1、pom.xml添加依赖
2、初始化vault动态配置,并配置文件监听(此处为源码)
3、使用配置热加载功能
三、问题与思考
原始需求:配置内容为外部文件,文件出现变更时能够自行刷新spring容器中的bean。
此源码初衷为应用于敏感信息治理Vault,客户端能够随着vault密钥的轮转,在不重启的情况下自动刷新密钥。
方式:源码引入,通过archiaus加载动态配置,通过springcloud context刷新bean。
org.springframework.cloud spring-cloud-starter com.netflix.archaius archaius-core 0.7.5 commons-configuration commons-configuration 1.10
org.springframework.cloud spring-cloud-dependencies 2020.0.5 pom import
注意:springcloud相关依赖为选填,原先是springcloud项目的不需要引入springcloud相关依赖
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicURLConfiguration;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;/*** Title: 动态加载vault配置文件,并刷新* Description:* author :xbl* Date:2023/2/8* Time:10:37*/
@Configuration
public class VaultConfigProcessor {private static final Log log = LogFactory.getLog(VaultConfigProcessor.class);@Autowiredprivate ContextRefresher refresher;@Value("${vault.secretPath}")private String vaultFile;@Value("${vault.secretKeys}")private String secretKeys;@PostConstructpublic void initVaultArchiausProcessor() {try {log.info("[VAULT-ARCHIAUS] - Dynamic property file is {}" + vaultFile);DynamicURLConfiguration dynamicURLConfiguration = new DynamicURLConfiguration(10000, 10000, false, vaultFile);ConcurrentCompositeConfiguration finalConfig = new ConcurrentCompositeConfiguration();finalConfig.addConfiguration(dynamicURLConfiguration);ConfigurationManager.install(finalConfig);ConfigurationManager.getConfigInstance().addConfigurationListener(new VaultConfigurationListener());} catch (RuntimeException e) {log.error("###############");log.error("[VAULT-ARCHIAUS] - project: initialization failed. Forcing shutdown now.");log.error("###############");e.printStackTrace();System.exit(0);}}class VaultConfigurationListener implements ConfigurationListener {@Overridepublic void configurationChanged(ConfigurationEvent event) {if (!event.isBeforeUpdate()) {if (secretKeys.contains(event.getPropertyName())) {log.info("[VAULT-ARCHIAUS] - " + event.getPropertyName() + " will refreshing! ");refresher.refresh();}}}}
}
1> 定位vault生成的配置文件地址,填写要求的静态配置到启动配置application.yml中
vault:#动态配置目录,即vault目标文件地址secretPath: file:/D:\project\src\main\resources\vault-secret.properties#监听哪些Key触发刷新,逗号分隔secretKeys: secretId,secretKey
2>vault-secret.properties(动态配置的真实内容,接入vault时会将配置落到此文件)
secretId=aaaaaaaavvvvvv
secretKey=acccccccckkkkk
3>客户端使用动态配置
bean初始化时使用archaius获取配置内容,添加@RefreshScope注解实现动态刷新,参考如下:
//bean对象案例
public class ClientEntity {private String secretId;public String getSecretId() {return secretId;}public void setSecretId(String secretId) {this.secretId = secretId;}
}//构建bean示例
@Bean
@RefreshScope
public ClientEntity clientEntity() {//取账号密钥String secretId = DynamicPropertyFactory.getInstance().getStringProperty("key", null).get();ClientEntity entity = new ClientEntity();entity.setSecretId(secretId);return entity;
}//使用单例bean
@Autowired
private ClientEntity clientEntity;
达到的效果:vault-secret.properties 触发变更时,spring容器内的 tencentClientEntity 也会更新 secretId,实现热加载。
对于使用者来说,只需要将密钥信息使用archiaus进行动态加载,并且加入@RefreshScope注解即可。
如果是非spring体系,不需要刷新bean,使用archiaus即可。
1、为什么不直接使用spring-cloud的动态配置加载能力,反而引入archiaus?
答:它需要在启动时指向配置文件,不够友好,我需要的是更灵活的外部配置;其次,它所提供配置的更新一般是集成actuator使用,需要对外暴露接口,需要手动触发更新,对于vault来说这种方式的接入太复杂,而archiaus能自己吃掉这个问题,解决耦合度的问题,同时使用起来更舒适。
2、为什么要使用springcloud去做bean的热更新?自己手动实现热加载不行吗?
答:原计划是手动刷新bean,从context获取到的bean能够实现热更新,这个已经跑通了,但是某些注解比如@autowired,它做的自动装配会有一层bean缓存,手动更新bean更新不了它,springcloud的RefreshScope就是用来处理这个问题的,如果自己去实现,也是参考cloud的方式。综合springcloud体系的覆盖面,决定直接使用springcloud解决这个问题。
上一篇:【数据结构-JAVA】排序
下一篇:功率放大器的增益是什么意思