当前位置:网站首页>手写分布式配置中心(1)
手写分布式配置中心(1)
2022-08-04 23:33:00 【InfoQ】
1 什是分布式配置中心
1.1 分布式配置中心有哪些组成
1.1.1, 有一个界面能操作配置
1.1.2, 数据能够持久化(防止丢失,服务下线在启动配置还是存在的)
1.1.3, 存在客户端和服务端, 客户端主动去拉去数据或者服务端主动推送数据。 并且刷新本机的配置。(核心)
1.1.4, 一些管理界面的操作日志, 权限系统等。
2,市面上主流的配置中心
2.1 阿里的 nacos
2.2 nacos 的原理,就是service 监控配置是否发生改变,通过长链接在发送给客户端
2.3 携程的Apollo
2.3 spirgcloud config
2.4 百度disconf
3如何实现自己的分布式配置中心
3.1 动态修改本地@Value注解的配置
3.2 在不同的bean 中, 相同的value 怎么同时修改。
4 具体思路
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
//怎么加载资源
addPropertySources(environment, application.getResourceLoader());
}
protected void addPropertySources(ConfigurableEnvironment environment,
ResourceLoader resourceLoader) {
RandomValuePropertySource.addToEnvironment(environment);
// 把资源给load 到环境变量里面
new Loader(environment, resourceLoader).load();
}
// 再用 propertySource 解析器给解析
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
this.environment = environment;
this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(
this.environment);
this.resourceLoader = (resourceLoader != null) ? resourceLoade
: new DefaultResourceLoader();
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(
PropertySourceLoader.class, getClass().getClassLoader());
}
4.1 代码实现
@Autowired
ConfigurableEnvironment configurableEnvironment;
@Autowired
Environment environment;
@Test
public void test() {
String name = environment.getProperty("name");
System.out.printf("动态加载之前" +name);
Map<String,String> map = new HashMap<>();
map.put("name","嘟嘟");
configurableEnvironment.getPropertySources().addLast(
new OriginTrackedMapPropertySource("xxxx.xml", map)
);
String property = environment.getProperty("name");
System.out.printf("动态加载之后" +property);
}
4.1.2 单元测试
4.2 代码实现
public static void refreshBean(Object bean, ConfigurablePropertyResolver propertyResolver) {
// 定义EL表达式解释器
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
TemplateParserContext templateParserContext= new TemplateParserContext();
String keyResolver, valueResolver = null;
Object parserValue;
// 获取真实对象属性
Field[] declaredFields = bean.getClass().getDeclaredFields();
boolean cglib = Arrays.stream(declaredFields).anyMatch(x -> x.getName().contains("CGLIB"));
// 如果是cglib 代理找其父类
if(cglib){
declaredFields = bean.getClass().getSuperclass().getDeclaredFields();
}
// 遍历Bean实例所有属性
for (Field field : declaredFields) {
// 判断field是否含有@Value注解
if (field.isAnnotationPresent(Value.class)) {
// 读取Value注解占位符
keyResolver = field.getAnnotation(Value.class).value();
try {
// 读取属性值
valueResolver = propertyResolver.resolveRequiredPlaceholders(keyResolver);
// EL表达式解析
// 兼容形如:@Value("#{'${codest.five.url}'.split(',')}")含有EL表达式的情况
Expression expression = spelExpressionParser.parseExpression(valueResolver, templateParserContext);
if(field.getType() == Boolean.class){
parserValue =Boolean.valueOf(expression.getValue().toString());
}
else if(field.getType() == Integer.class){
parserValue =Integer.valueOf(expression.getValue().toString());
}
else if(field.getType() == Long.class){
parserValue =Long.valueOf(expression.getValue().toString());
}else {
parserValue = expression.getValue(field.getType());
}
} catch (IllegalArgumentException e) {
continue;
}
// 判断配置项是否存在
if (Objects.nonNull(valueResolver)) {
field.setAccessible(true);
try {
field.set(bean, parserValue);
continue;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
4.2.1 单元测试
@Autowired
ConfigurableEnvironment configurableEnvironment;
@Autowired
ConfigurablePropertyResolver configurablePropertyResolver;
@Autowired
Person person;
@Test
public void test() {
System.out.printf("动态加载之前" +person.getName());
Map<String,Object> map = new HashMap<>();
map.put("name","嘟嘟");
configurableEnvironment.getPropertySources().forEach( x->{
if (x instanceof OriginTrackedMapPropertySource ) {
Map<String,Object> map1 = (Map<String, Object>) x.getSource();
map1.putAll(map);
}
}
);
refreshBean(person,configurablePropertyResolver);
System.out.printf("动态加载之后" +person.getName());
}
边栏推荐
- 自从新来了个字节20K出来的,就见识到了什么是天花板
- Uniapp dynamic sliding navigation effect demo (finishing)
- uniapp sharing function - share to friends group chat circle of friends effect (sorting)
- 加解密在线工具和进制转化在线工具
- 【无标题】
- Security software Avast and Symantec NortonLifeLock merge with UK approval, market value soars 43%
- VMware NSX 4.0 -- 网络安全虚拟化平台
- 堪称奔驰“理财产品”,空间媲美宝马X5,采用了非常运动的外观
- 没有这些「伪需求」,产品经理的 KPI 怎么完成?
- 2022年华数杯数学建模
猜你喜欢

MySQL增删改查基础

Community Sharing|Tencent Overseas Games builds game security operation capabilities based on JumpServer

被领导拒绝涨薪申请,跳槽后怒涨9.5K,这是我的心路历程
![[Cultivation of internal skills of string functions] strncpy + strncat + strncmp (2)](/img/9f/9221c081cfa86caccbbd02916a6208.png)
[Cultivation of internal skills of string functions] strncpy + strncat + strncmp (2)

MySQL基础篇【聚合函数】

为何越来越多人选择进入软件测试行业?深度剖析软件测试的优势...

Vscode连接远程服务器(一套配置成功)

小黑leetcode冲浪:94. 二叉树的中序遍历

功耗控制之DVFS介绍

一点点读懂cpufreq(二)
随机推荐
Will we still need browsers in the future?(feat. Maple words Maple language)
【字符串函数内功修炼】strlen + strstr + strtok + strerror(三)
2022年华数杯数学建模
[Cultivation of internal skills of string functions] strncpy + strncat + strncmp (2)
MYS-6ULX-IOT 开发板测评——使用 Yocto 添加软件包
Nuclei(二)进阶——深入理解workflows、Matchers和Extractors
基于Appian低代码平台开发一个SpaceX网站
【手撕AHB-APB Bridge】~ AMBA总线 之 AHB
Day118. Shangyitong: order list, details, payment
@Import注解的作用以及如何使用
VMware NSX 4.0 -- 网络安全虚拟化平台
零基础如何入门软件测试?再到测开(小编心得)
Pytest learning - fixtures
[Cultivation of internal skills of string functions] strlen + strstr + strtok + strerror (3)
吐槽 | 参加IT培训的正确姿势
从单体架构迁移到 CQRS 后,我觉得 DDD 并不可怕
Ab3d.PowerToys and Ab3d.DXEngine Crack
测试技术:关于上下文驱动测试的总结
【无标题】线程三连鞭之“线程池”
Pytorch分布式训练/多卡/多GPU训练DDP的torch.distributed.launch和torchrun